usb-hid: add event callback

Add callback for event notification, which allows to un-usbify more
functions.  Also split separate hid_* functions for reset and release.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2011-07-15 14:37:15 +02:00
parent 0d878eec1e
commit 8bde680541

View File

@ -54,6 +54,9 @@ typedef struct HIDPointerEvent {
#define QUEUE_MASK (QUEUE_LENGTH-1u) #define QUEUE_MASK (QUEUE_LENGTH-1u)
#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK) #define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
typedef struct HIDState HIDState;
typedef void (*HIDEventFunc)(HIDState *s);
typedef struct HIDMouseState { typedef struct HIDMouseState {
HIDPointerEvent queue[QUEUE_LENGTH]; HIDPointerEvent queue[QUEUE_LENGTH];
int mouse_grabbed; int mouse_grabbed;
@ -68,7 +71,7 @@ typedef struct HIDKeyboardState {
int32_t keys; int32_t keys;
} HIDKeyboardState; } HIDKeyboardState;
typedef struct HIDState { struct HIDState {
union { union {
HIDMouseState ptr; HIDMouseState ptr;
HIDKeyboardState kbd; HIDKeyboardState kbd;
@ -76,7 +79,8 @@ typedef struct HIDState {
uint32_t head; /* index into circular queue */ uint32_t head; /* index into circular queue */
uint32_t n; uint32_t n;
int kind; int kind;
} HIDState; HIDEventFunc event;
};
typedef struct USBHIDState { typedef struct USBHIDState {
USBDevice dev; USBDevice dev;
@ -440,14 +444,17 @@ static const uint8_t usb_hid_usage_keys[0x100] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
static void usb_hid_changed(USBHIDState *hs) static void usb_hid_changed(HIDState *hs)
{ {
hs->changed = 1; USBHIDState *us = container_of(hs, USBHIDState, hid);
if (hs->datain) us->changed = 1;
hs->datain(hs->datain_opaque);
usb_wakeup(&hs->dev); if (us->datain) {
us->datain(us->datain_opaque);
}
usb_wakeup(&us->dev);
} }
static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons) static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons)
@ -473,11 +480,10 @@ static void hid_pointer_event_combine(HIDPointerEvent *e, int xyrel,
e->dz += z1; e->dz += z1;
} }
static void usb_pointer_event(void *opaque, static void hid_pointer_event(void *opaque,
int x1, int y1, int z1, int buttons_state) int x1, int y1, int z1, int buttons_state)
{ {
USBHIDState *us = opaque; HIDState *hs = opaque;
HIDState *hs = &us->hid;
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK; unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK; unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
@ -501,13 +507,12 @@ static void usb_pointer_event(void *opaque,
hid_pointer_event_combine(&hs->ptr.queue[use_slot], hid_pointer_event_combine(&hs->ptr.queue[use_slot],
hs->kind == HID_MOUSE, hs->kind == HID_MOUSE,
x1, y1, z1); x1, y1, z1);
usb_hid_changed(us); hs->event(hs);
} }
static void usb_keyboard_event(void *opaque, int keycode) static void hid_keyboard_event(void *opaque, int keycode)
{ {
USBHIDState *us = opaque; HIDState *hs = opaque;
HIDState *hs = &us->hid;
int slot; int slot;
if (hs->n == QUEUE_LENGTH) { if (hs->n == QUEUE_LENGTH) {
@ -516,7 +521,7 @@ static void usb_keyboard_event(void *opaque, int keycode)
} }
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++; slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
hs->kbd.keycodes[slot] = keycode; hs->kbd.keycodes[slot] = keycode;
usb_hid_changed(us); hs->event(hs);
} }
static void hid_keyboard_process_keycode(HIDState *hs) static void hid_keyboard_process_keycode(HIDState *hs)
@ -713,26 +718,29 @@ static int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len)
return 0; return 0;
} }
static void usb_mouse_handle_reset(USBDevice *dev) static void hid_handle_reset(HIDState *hs)
{ {
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); switch (hs->kind) {
case HID_KEYBOARD:
memset(us->hid.ptr.queue, 0, sizeof(us->hid.ptr.queue)); qemu_add_kbd_event_handler(hid_keyboard_event, hs);
us->hid.head = 0; memset(hs->kbd.keycodes, 0, sizeof(hs->kbd.keycodes));
us->hid.n = 0; memset(hs->kbd.key, 0, sizeof(hs->kbd.key));
us->protocol = 1; hs->kbd.keys = 0;
break;
case HID_MOUSE:
case HID_TABLET:
memset(hs->ptr.queue, 0, sizeof(hs->ptr.queue));
break;
}
hs->head = 0;
hs->n = 0;
} }
static void usb_keyboard_handle_reset(USBDevice *dev) static void usb_hid_handle_reset(USBDevice *dev)
{ {
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
qemu_add_kbd_event_handler(usb_keyboard_event, us); hid_handle_reset(&us->hid);
memset(us->hid.kbd.keycodes, 0, sizeof(us->hid.kbd.keycodes));
us->hid.head = 0;
us->hid.n = 0;
memset(us->hid.kbd.key, 0, sizeof(us->hid.kbd.key));
us->hid.kbd.keys = 0;
us->protocol = 1; us->protocol = 1;
} }
@ -866,34 +874,46 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
return ret; return ret;
} }
static void hid_free(HIDState *hs)
{
switch (hs->kind) {
case HID_KEYBOARD:
qemu_remove_kbd_event_handler();
break;
case HID_MOUSE:
case HID_TABLET:
qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
break;
}
}
static void usb_hid_handle_destroy(USBDevice *dev) static void usb_hid_handle_destroy(USBDevice *dev)
{ {
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
switch (us->hid.kind) { hid_free(&us->hid);
case HID_KEYBOARD: }
qemu_remove_kbd_event_handler();
break; static void hid_init(HIDState *hs, int kind, HIDEventFunc event)
default: {
qemu_remove_mouse_event_handler(us->hid.ptr.eh_entry); hs->kind = kind;
hs->event = event;
if (hs->kind == HID_MOUSE) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0, "QEMU HID Mouse");
} else if (hs->kind == HID_TABLET) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
1, "QEMU HID Tablet");
} }
} }
static int usb_hid_initfn(USBDevice *dev, int kind) static int usb_hid_initfn(USBDevice *dev, int kind)
{ {
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
HIDState *hs = &us->hid;
usb_desc_init(dev); usb_desc_init(dev);
hs->kind = kind; hid_init(&us->hid, kind, usb_hid_changed);
if (hs->kind == HID_MOUSE) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, us,
0, "QEMU HID Mouse");
} else if (hs->kind == HID_TABLET) {
hs->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, us,
1, "QEMU HID Tablet");
}
/* Force poll routine to be run and grab input the first time. */ /* Force poll routine to be run and grab input the first time. */
us->changed = 1; us->changed = 1;
@ -992,7 +1012,7 @@ static struct USBDeviceInfo hid_info[] = {
.usb_desc = &desc_tablet, .usb_desc = &desc_tablet,
.init = usb_tablet_initfn, .init = usb_tablet_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_mouse_handle_reset, .handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control, .handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data, .handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy, .handle_destroy = usb_hid_handle_destroy,
@ -1005,7 +1025,7 @@ static struct USBDeviceInfo hid_info[] = {
.usb_desc = &desc_mouse, .usb_desc = &desc_mouse,
.init = usb_mouse_initfn, .init = usb_mouse_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_mouse_handle_reset, .handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control, .handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data, .handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy, .handle_destroy = usb_hid_handle_destroy,
@ -1018,7 +1038,7 @@ static struct USBDeviceInfo hid_info[] = {
.usb_desc = &desc_keyboard, .usb_desc = &desc_keyboard,
.init = usb_keyboard_initfn, .init = usb_keyboard_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,
.handle_reset = usb_keyboard_handle_reset, .handle_reset = usb_hid_handle_reset,
.handle_control = usb_hid_handle_control, .handle_control = usb_hid_handle_control,
.handle_data = usb_hid_handle_data, .handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy, .handle_destroy = usb_hid_handle_destroy,