[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH][RFC] usb-wacom.c merge into usb-hid.c
From: |
François Revol |
Subject: |
[Qemu-devel] [PATCH][RFC] usb-wacom.c merge into usb-hid.c |
Date: |
Sun, 29 Mar 2009 03:55:38 +0200 CEST |
After the fixes to usb-wacom.c I proposed, I managed to merge it into
usb-hid.c.
Seems to work, at least for wacom in Haiku guest, but would need some
cleanup.
Comments ?
François.
Index: hw/usb-hid.c
===================================================================
--- hw/usb-hid.c (révision 6944)
+++ hw/usb-hid.c (copie de travail)
@@ -1,6 +1,10 @@
/*
* QEMU USB HID devices
*
+ * Wacom PenPartner USB tablet emulation:
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Author: Andrzej Zaborowski <address@hidden>
+ *
* Copyright (c) 2005 Fabrice Bellard
* Copyright (c) 2007 OpenMoko, Inc. (address@hidden)
*
@@ -26,23 +30,32 @@
#include "console.h"
#include "usb.h"
+/* Interface requests */
+#define WACOM_GET_REPORT 0x2101
+#define WACOM_SET_REPORT 0x2109
+
/* HID interface requests */
-#define GET_REPORT 0xa101
-#define GET_IDLE 0xa102
-#define GET_PROTOCOL 0xa103
-#define SET_REPORT 0x2109
-#define SET_IDLE 0x210a
-#define SET_PROTOCOL 0x210b
+#define HID_GET_REPORT 0xa101
+#define HID_GET_IDLE 0xa102
+#define HID_GET_PROTOCOL 0xa103
+#define HID_SET_REPORT 0x2109
+#define HID_SET_IDLE 0x210a
+#define HID_SET_PROTOCOL 0x210b
+
/* HID descriptor types */
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHY 0x23
-#define USB_MOUSE 1
-#define USB_TABLET 2
-#define USB_KEYBOARD 3
+#define USB_MOUSE 1
+#define USB_TABLET 2
+#define USB_KEYBOARD 3
+#define USB_WACOM_TABLET 4
+#define WACOM_MODE_HID 1
+#define WACOM_MODE_WACOM 2
+
typedef struct USBMouseState {
int dx, dy, dz, buttons_state;
int x, y;
@@ -63,10 +76,13 @@
USBMouseState ptr;
USBKeyboardState kbd;
};
+ const uint8_t *dev_descriptor, *config_descriptor, *hid_report_descriptor;
+ int dev_descriptor_size, config_descriptor_size,
hid_report_descriptor_size;
int kind;
int protocol;
uint8_t idle;
int changed;
+ int (*hook_poll)(struct USBHIDState *, uint8_t *, int);
void *datain_opaque;
void (*datain)(void *);
} USBHIDState;
@@ -92,6 +108,26 @@
0x01 /* u8 bNumConfigurations; */
};
+static const uint8_t qemu_wacom_dev_descriptor[] = {
+ 0x12, /* u8 bLength; */
+ 0x01, /* u8 bDescriptorType; Device */
+ 0x10, 0x10, /* u16 bcdUSB; v1.10 */
+
+ 0x00, /* u8 bDeviceClass; */
+ 0x00, /* u8 bDeviceSubClass; */
+ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
+ 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
+
+ 0x6a, 0x05, /* u16 idVendor; */
+ 0x00, 0x00, /* u16 idProduct; */
+ 0x10, 0x42, /* u16 bcdDevice */
+
+ 0x01, /* u8 iManufacturer; */
+ 0x02, /* u8 iProduct; */
+ 0x00, /* u8 iSerialNumber; */
+ 0x01, /* u8 bNumConfigurations; */
+};
+
static const uint8_t qemu_mouse_config_descriptor[] = {
/* one configuration */
0x09, /* u8 bLength; */
@@ -257,6 +293,50 @@
0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
+static const uint8_t qemu_wacom_config_descriptor[] = {
+ /* one configuration */
+ 0x09, /* u8 bLength; */
+ 0x02, /* u8 bDescriptorType; Configuration */
+ 0x22, 0x00, /* u16 wTotalLength; */
+ 0x01, /* u8 bNumInterfaces; (1) */
+ 0x01, /* u8 bConfigurationValue; */
+ 0x00, /* u8 iConfiguration; */
+ 0x80, /* u8 bmAttributes;
+ Bit 7: must be set,
+ 6: Self-powered,
+ 5: Remote wakeup,
+ 4..0: resvd */
+ 40, /* u8 MaxPower; */
+
+ /* one interface */
+ 0x09, /* u8 if_bLength; */
+ 0x04, /* u8 if_bDescriptorType; Interface */
+ 0x00, /* u8 if_bInterfaceNumber; */
+ 0x00, /* u8 if_bAlternateSetting; */
+ 0x01, /* u8 if_bNumEndpoints; */
+ 0x03, /* u8 if_bInterfaceClass; HID */
+ 0x01, /* u8 if_bInterfaceSubClass; Boot */
+ 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
+ 0x00, /* u8 if_iInterface; */
+
+ /* HID descriptor */
+ 0x09, /* u8 bLength; */
+ 0x21, /* u8 bDescriptorType; */
+ 0x01, 0x10, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ 0x22, /* u8 type; Report */
+ 0x6e, 0x00, /* u16 len */
+
+ /* one endpoint (status change endpoint) */
+ 0x07, /* u8 ep_bLength; */
+ 0x05, /* u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* u8 ep_bmAttributes; Interrupt */
+ 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
+ 0x0a, /* u8 ep_bInterval; */
+};
+
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x02, /* Usage (Mouse) */
@@ -440,6 +520,26 @@
usb_hid_changed(hs);
}
+static void usb_wacom_event(void *opaque,
+ int x, int y, int dz, int buttons_state)
+{
+ USBHIDState *hs = opaque;
+ USBMouseState *s = &hs->ptr;
+
+ if (hs->protocol == WACOM_MODE_HID) {
+ usb_mouse_event(opaque, x, y, dz, buttons_state);
+ return;
+ }
+
+ /* scale to Penpartner resolution */
+ s->x = (x * 5040 / 0x7FFF);
+ s->y = (y * 3780 / 0x7FFF);
+ s->dz += dz;
+ s->buttons_state = buttons_state;
+
+ usb_hid_changed(hs);
+}
+
static void usb_keyboard_event(void *opaque, int keycode)
{
USBHIDState *hs = opaque;
@@ -581,8 +681,50 @@
return l;
}
-static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
+static int usb_wacom_poll(USBHIDState *hs, uint8_t *buf, int len)
{
+ int b;
+ USBMouseState *s = &hs->ptr;
+
+ if (!s->mouse_grabbed) {
+ s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, hs, 1,
+ "QEMU PenPartner tablet");
+ s->mouse_grabbed = 1;
+ }
+
+ if (hs->protocol == WACOM_MODE_HID)
+ return usb_mouse_poll(hs, buf, len);
+
+ b = 0;
+ if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+ b |= 0x01;
+ if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+ b |= 0x40;
+ if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+ b |= 0x20; /* eraser */
+
+ if (len < 7)
+ return 0;
+
+ buf[0] = hs->protocol;
+ buf[5] = 0x00 | (b & 0xf0);
+ buf[1] = s->x & 0xff;
+ buf[2] = s->x >> 8;
+ buf[3] = s->y & 0xff;
+ buf[4] = s->y >> 8;
+ if (b & 0x3f) {
+ buf[6] = 0;
+ } else {
+ buf[6] = (unsigned char) -127;
+ }
+
+ return 7;
+}
+
+static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
+{
+ USBKeyboardState *s = &hs->kbd;
+
if (len < 2)
return 0;
@@ -622,6 +764,13 @@
s->protocol = 1;
}
+static void usb_wacom_handle_reset(USBDevice *dev)
+{
+ USBHIDState *s = (USBHIDState *)dev;
+ usb_mouse_handle_reset(dev);
+ s->protocol = WACOM_MODE_HID;
+}
+
static void usb_keyboard_handle_reset(USBDevice *dev)
{
USBHIDState *s = (USBHIDState *)dev;
@@ -666,24 +815,14 @@
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
switch(value >> 8) {
case USB_DT_DEVICE:
- memcpy(data, qemu_mouse_dev_descriptor,
- sizeof(qemu_mouse_dev_descriptor));
- ret = sizeof(qemu_mouse_dev_descriptor);
+ if (s->dev_descriptor)
+ memcpy(data, s->dev_descriptor, s->dev_descriptor_size);
+ ret = s->dev_descriptor_size;
break;
case USB_DT_CONFIG:
- if (s->kind == USB_MOUSE) {
- memcpy(data, qemu_mouse_config_descriptor,
- sizeof(qemu_mouse_config_descriptor));
- ret = sizeof(qemu_mouse_config_descriptor);
- } else if (s->kind == USB_TABLET) {
- memcpy(data, qemu_tablet_config_descriptor,
- sizeof(qemu_tablet_config_descriptor));
- ret = sizeof(qemu_tablet_config_descriptor);
- } else if (s->kind == USB_KEYBOARD) {
- memcpy(data, qemu_keyboard_config_descriptor,
- sizeof(qemu_keyboard_config_descriptor));
- ret = sizeof(qemu_keyboard_config_descriptor);
- }
+ if (s->config_descriptor)
+ memcpy(data, s->config_descriptor, s->config_descriptor_size);
+ ret = s->config_descriptor_size;
break;
case USB_DT_STRING:
switch(value & 0xff) {
@@ -716,6 +855,11 @@
case 6:
ret = set_usb_string(data, "HID Keyboard");
break;
+ /*
+ case 4:
+ ret = set_usb_string(data, "Wacom Tablet");
+ break;
+ */
case 7:
ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
break;
@@ -741,59 +885,60 @@
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
ret = 0;
break;
+ /* wacom specific requests */
+ case WACOM_GET_REPORT:
+ data[0] = 0;
+ data[1] = s->protocol;
+ ret = 2;
+ break;
/* hid specific requests */
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
switch(value >> 8) {
case 0x22:
- if (s->kind == USB_MOUSE) {
- memcpy(data, qemu_mouse_hid_report_descriptor,
- sizeof(qemu_mouse_hid_report_descriptor));
- ret = sizeof(qemu_mouse_hid_report_descriptor);
- } else if (s->kind == USB_TABLET) {
- memcpy(data, qemu_tablet_hid_report_descriptor,
- sizeof(qemu_tablet_hid_report_descriptor));
- ret = sizeof(qemu_tablet_hid_report_descriptor);
- } else if (s->kind == USB_KEYBOARD) {
- memcpy(data, qemu_keyboard_hid_report_descriptor,
- sizeof(qemu_keyboard_hid_report_descriptor));
- ret = sizeof(qemu_keyboard_hid_report_descriptor);
- }
+ if (s->hid_report_descriptor)
+ memcpy(data, s->hid_report_descriptor,
+ s->hid_report_descriptor_size);
+ ret = s->hid_report_descriptor_size;
break;
default:
goto fail;
}
break;
- case GET_REPORT:
- if (s->kind == USB_MOUSE)
- ret = usb_mouse_poll(s, data, length);
- else if (s->kind == USB_TABLET)
- ret = usb_tablet_poll(s, data, length);
- else if (s->kind == USB_KEYBOARD)
- ret = usb_keyboard_poll(&s->kbd, data, length);
+ case HID_GET_REPORT:
+ if (s->hook_poll)
+ ret = s->hook_poll(s, data, length);
break;
- case SET_REPORT:
+ //case WACOM_SET_REPORT:
+ case HID_SET_REPORT:
if (s->kind == USB_KEYBOARD)
ret = usb_keyboard_write(&s->kbd, data, length);
- else
- goto fail;
+ else if (s->kind == USB_WACOM_TABLET) {
+ if (s->ptr.eh_entry)
+ qemu_remove_mouse_event_handler(s->ptr.eh_entry);
+ s->ptr.eh_entry = NULL;
+ s->ptr.mouse_grabbed = 0;
+ s->protocol = data[0];
+ ret = 0;
+ } else
+ goto fail;
break;
- case GET_PROTOCOL:
+ case HID_GET_PROTOCOL:
if (s->kind != USB_KEYBOARD)
goto fail;
ret = 1;
data[0] = s->protocol;
break;
- case SET_PROTOCOL:
+ case HID_SET_PROTOCOL:
if (s->kind != USB_KEYBOARD)
goto fail;
ret = 0;
s->protocol = value;
break;
- case GET_IDLE:
+ case HID_GET_IDLE:
ret = 1;
data[0] = s->idle;
break;
- case SET_IDLE:
+ case HID_SET_IDLE:
s->idle = (uint8_t) (value >> 8);
ret = 0;
break;
@@ -817,12 +962,8 @@
if (!(s->changed || s->idle))
return USB_RET_NAK;
s->changed = 0;
- if (s->kind == USB_MOUSE)
- ret = usb_mouse_poll(s, p->data, p->len);
- else if (s->kind == USB_TABLET)
- ret = usb_tablet_poll(s, p->data, p->len);
- else if (s->kind == USB_KEYBOARD)
- ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
+ if (s->hook_poll)
+ ret = s->hook_poll(s, p->data, p->len);
} else {
goto fail;
}
@@ -858,7 +999,15 @@
s->dev.handle_control = usb_hid_handle_control;
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
+
+ s->dev_descriptor = qemu_mouse_dev_descriptor;
+ s->dev_descriptor_size = sizeof(qemu_mouse_dev_descriptor);
+ s->config_descriptor = qemu_tablet_config_descriptor;
+ s->config_descriptor_size = sizeof(qemu_tablet_config_descriptor);
+ s->hid_report_descriptor = qemu_tablet_hid_report_descriptor;
+ s->hid_report_descriptor_size = sizeof(qemu_tablet_hid_report_descriptor);
s->kind = USB_TABLET;
+ s->hook_poll = usb_tablet_poll;
/* Force poll routine to be run and grab input the first time. */
s->changed = 1;
@@ -867,6 +1016,37 @@
return (USBDevice *)s;
}
+USBDevice *usb_wacom_init(void)
+{
+ USBHIDState *s;
+
+ s = qemu_mallocz(sizeof(USBHIDState));
+ s->dev.speed = USB_SPEED_FULL;
+ s->dev.handle_packet = usb_generic_handle_packet;
+
+ s->dev.handle_reset = usb_wacom_handle_reset;
+ s->dev.handle_control = usb_hid_handle_control;
+ s->dev.handle_data = usb_hid_handle_data;
+ s->dev.handle_destroy = usb_hid_handle_destroy;
+
+ s->dev_descriptor = qemu_wacom_dev_descriptor;
+ s->dev_descriptor_size = sizeof(qemu_wacom_dev_descriptor);
+ s->config_descriptor = qemu_tablet_config_descriptor;
+ s->config_descriptor_size = sizeof(qemu_tablet_config_descriptor);
+ s->hid_report_descriptor = NULL;
+ s->hid_report_descriptor_size = 0;
+ s->kind = USB_WACOM_TABLET;
+ s->hook_poll = &usb_wacom_poll;
+ /* Force poll routine to be run and grab input the first time. */
+ s->changed = 1;
+
+ //pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
+ pstrcpy(s->dev.devname, sizeof(s->dev.devname),
+ "QEMU PenPartner Tablet");
+
+ return (USBDevice *)s;
+}
+
USBDevice *usb_mouse_init(void)
{
USBHIDState *s;
@@ -879,7 +1059,15 @@
s->dev.handle_control = usb_hid_handle_control;
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
+
+ s->dev_descriptor = qemu_mouse_dev_descriptor;
+ s->dev_descriptor_size = sizeof(qemu_mouse_dev_descriptor);
+ s->config_descriptor = qemu_mouse_config_descriptor;
+ s->config_descriptor_size = sizeof(qemu_mouse_config_descriptor);
+ s->hid_report_descriptor = qemu_mouse_hid_report_descriptor;
+ s->hid_report_descriptor_size = sizeof(qemu_mouse_hid_report_descriptor);
s->kind = USB_MOUSE;
+ s->hook_poll = usb_mouse_poll;
/* Force poll routine to be run and grab input the first time. */
s->changed = 1;
@@ -900,7 +1088,15 @@
s->dev.handle_control = usb_hid_handle_control;
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
+
+ s->dev_descriptor = qemu_mouse_dev_descriptor;
+ s->dev_descriptor_size = sizeof(qemu_mouse_dev_descriptor);
+ s->config_descriptor = qemu_keyboard_config_descriptor;
+ s->config_descriptor_size = sizeof(qemu_keyboard_config_descriptor);
+ s->hid_report_descriptor = qemu_keyboard_hid_report_descriptor;
+ s->hid_report_descriptor_size =
sizeof(qemu_keyboard_hid_report_descriptor);
s->kind = USB_KEYBOARD;
+ s->hook_poll = usb_keyboard_poll;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
@@ -914,3 +1110,4 @@
s->datain_opaque = opaque;
s->datain = datain;
}
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH][RFC] usb-wacom.c merge into usb-hid.c,
François Revol <=