All of lore.kernel.org
 help / color / mirror / Atom feed
From: "François Revol" <revol@free.fr>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd)
Date: Tue, 31 Mar 2009 15:51:50 +0200 CEST	[thread overview]
Message-ID: <5111661812-BeMail@laptop> (raw)

[-- 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;
 }
+

             reply	other threads:[~2009-03-31 13:51 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-31 13:51 François Revol [this message]
2009-03-31 14:22 ` [Qemu-devel] [RESEND][PATCH][RFC] usb-wacom.c merge into usb-hid.c (fwd) Paul Brook
2009-03-31 14:40   ` François Revol

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5111661812-BeMail@laptop \
    --to=revol@free.fr \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.