* [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd)
@ 2009-03-31 13:51 François Revol
2009-03-31 14:22 ` Paul Brook
0 siblings, 1 reply; 3+ messages in thread
From: François Revol @ 2009-03-31 13:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 466 bytes --]
ping ?
(hw/usb-wacom.c would just go away then)
François.
------ Forwarded Message: ------
To: qemu-devel@nongnu.org
From: "François Revol" <revol@free.fr>
Subject: [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.
[-- Attachment #2: qemu-usb-wacom-merged-to-hid.001.diff.txt --]
[-- Type: text/plain, Size: 15238 bytes --]
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 <balrog@zabor.org>
+ *
* Copyright (c) 2005 Fabrice Bellard
* Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
*
@@ -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;
}
+
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd)
2009-03-31 13:51 [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd) François Revol
@ 2009-03-31 14:22 ` Paul Brook
2009-03-31 14:40 ` François Revol
0 siblings, 1 reply; 3+ messages in thread
From: Paul Brook @ 2009-03-31 14:22 UTC (permalink / raw)
To: qemu-devel; +Cc: François Revol
On Tuesday 31 March 2009, François Revol wrote:
> ping ?
There seem to be several unrelated name changes, and several bits of commented
out code. The latter is always wrong. Disabled code just bitrots. Either fix
it, or replace it with a comment describing whatever that code was supposed
to indicate.
Paul
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd)
2009-03-31 14:22 ` Paul Brook
@ 2009-03-31 14:40 ` François Revol
0 siblings, 0 replies; 3+ messages in thread
From: François Revol @ 2009-03-31 14:40 UTC (permalink / raw)
To: qemu-devel
> On Tuesday 31 March 2009, François Revol wrote:
> > ping ?
>
> There seem to be several unrelated name changes, and several bits of
> commented
> out code. The latter is always wrong. Disabled code just bitrots.
> Either fix
> it, or replace it with a comment describing whatever that code was
> supposed
> to indicate.
The names were different in usb-wacom (HID_GET_* instead of GET_*), and
those seemed cleaner to use. Simple :%s/// in vim.
The first commented line is due to an identical value in the case that
I wanted to advertise, and it's why it's tagged [RFC].
The other commented line is just the name of the device, I think I
was't sure which to have here, RFC too.
François.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-03-31 14:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-31 13:51 [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd) François Revol
2009-03-31 14:22 ` Paul Brook
2009-03-31 14:40 ` François Revol
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).