qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] USB Tablet Emulation (was: Gentlemen we have absolute m


From: Anthony Liguori
Subject: Re: [Qemu-devel] USB Tablet Emulation (was: Gentlemen we have absolute movement! was:Absolute USB-HID device musings (was Re: VNC Terminal Server))
Date: Sun, 09 Apr 2006 22:40:06 -0500
User-agent: Mail/News 1.5 (X11/20060309)

I spent some time cleaning this all up. The following integrates Brad's patches and the patch from http://gnome.dnsalias.net/patches/qemu-hidmousexp.patch

It adds a new emulated USB device that reports absolute coordinates. It also modifies SDL to operate in grabless mode when an absolute input device is enabled. I think it's pretty close to apply-able. To use, just specify: -usbdevice tablet

With Xorg from CVS, the evdev driver segfaults. This is apparently expected behavior. Hopefully it will be fixed soon. It works quite nicely under Win2k.

Regards,

Anthony Liguori

Brad Campbell wrote:
Anthony Liguori wrote:

Final one of the night. This patch disables relative mouse reporting and disables grab automatically the first time SDL detects that the absolute mouse was enabled. Needs a lot of cleanup but I'm very happy with the user experience on this one.


Wish I'd just gone to bed now..
Heres a patch against your last one to implement wheel support.

Brad
------------------------------------------------------------------------

diff -ur qemu-clean/hw/usb-hid.c qemu/hw/usb-hid.c
--- qemu-clean/hw/usb-hid.c     2006-04-10 02:57:46.000000000 +0400
+++ qemu/hw/usb-hid.c   2006-04-10 03:11:58.000000000 +0400
@@ -101,7 +101,7 @@
         0x00,        /*  u8 country_code */
         0x01,        /*  u8 num_descriptors */
         0x22,        /*  u8 type; Report */
-        53, 0,       /*  u16 len */
+        65, 0,       /*  u16 len */
/* one endpoint (status change endpoint) */
        0x07,       /*  u8  ep_bLength; */
@@ -145,14 +145,15 @@
         0x09, 0x31, /* Usage Y */
         0x15, 0x00, /* Logical Minimum 0 */
         0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum 0xffff */
-        0x75, 0x10, /* Report Size 32 */
+        0x75, 0x10, /* Report Size 16 */
         0x95, 0x02, /* Report Count 2 */
         0x81, 0x02, /* Input (Data, Var, Abs) */
-//      0x09, 0x32, /* Usage Z */
-//      0x15, 0x81, /* Logical Minimum -127 */
-//      0x25, 0x7F, /* Logical Maximum 127 */
-//      0x75, 0x08, /* Report Size 8 */
-//      0x95, 0x01, /* Report Count 1 */
+        0x09, 0x38, /* Usage Wheel */
+        0x15, 0x81, /* Logical Minimum -127 */
+        0x25, 0x7F, /* Logical Maximum 127 */
+        0x75, 0x08, /* Report Size 8 */
+        0x95, 0x01, /* Report Count 1 */
+        0x81, 0x02, /* Input (Data, Var, Rel) */
         0xC0,       /* End Collection */
         0xC0,       /* End Collection */
 };
@@ -224,14 +225,18 @@
        qemu_add_mouse_event_handler(NULL, NULL);
        absolute_mouse = 1;
     }
-
+/*
     dx = int_clamp(s->dx, -128, 127);
     dy = int_clamp(s->dy, -128, 127);
-    dz = int_clamp(s->dz, -128, 127);
s->dx -= dx;
     s->dy -= dy;
+*/
+
+    dz = int_clamp(s->dz, -128, 127);
     s->dz -= dz;
+/* Appears we have to invert the wheel direction */
+    dz = 0 - dz;
     b = 0;
     if (s->buttons_state & MOUSE_EVENT_LBUTTON)
         b |= 0x01;
@@ -245,7 +250,8 @@
     buf[2] = s->X >> 8;
     buf[3] = s->Y & 0xff;
     buf[4] = s->Y >> 8;
-    l = 5;
+    buf[5] = dz;
+    l = 6;
return l;
 }
------------------------------------------------------------------------

_______________________________________________
Qemu-devel mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/qemu-devel

diff -r 6a786a97b822 hw/ps2.c
--- a/hw/ps2.c  Mon Apr 10 01:47:35 2006 +0000
+++ b/hw/ps2.c  Sun Apr  9 22:34:20 2006 -0500
@@ -560,7 +560,7 @@
     s->common.update_arg = update_arg;
     ps2_reset(&s->common);
     register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
-    qemu_add_mouse_event_handler(ps2_mouse_event, s);
+    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
     qemu_register_reset(ps2_reset, &s->common);
     return s;
 }
diff -r 6a786a97b822 hw/usb-hid.c
--- a/hw/usb-hid.c      Mon Apr 10 01:47:35 2006 +0000
+++ b/hw/usb-hid.c      Sun Apr  9 22:34:20 2006 -0500
@@ -30,9 +30,15 @@
 #define SET_IDLE     0x210a
 #define SET_PROTOCOL 0x210b
 
+#define USB_MOUSE  1
+#define USB_TABLET 2
+
 typedef struct USBMouseState {
     USBDevice dev;
     int dx, dy, dz, buttons_state;
+    int x, y;
+    int kind;
+    int mouse_grabbed;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -93,14 +99,6 @@
        0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
        0x05,       /*  u8  if_iInterface; */
      
-       /* 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 */
-       0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
-       0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-
         /* HID descriptor */
         0x09,        /*  u8  bLength; */
         0x21,        /*  u8 bDescriptorType; */
@@ -109,6 +107,69 @@
         0x01,        /*  u8 num_descriptors */
         0x22,        /*  u8 type; Report */
         50, 0,       /*  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 */
+       0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
+       0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+};
+
+static const uint8_t qemu_tablet_config_descriptor[] = {
+       /* one configuration */
+       0x09,       /*  u8  bLength; */
+       0x02,       /*  u8  bDescriptorType; Configuration */
+       0x22, 0x00, /*  u16 wTotalLength; */
+       0x01,       /*  u8  bNumInterfaces; (1) */
+       0x01,       /*  u8  bConfigurationValue; */
+       0x04,       /*  u8  iConfiguration; */
+       0xa0,       /*  u8  bmAttributes; 
+                                Bit 7: must be set,
+                                    6: Self-powered,
+                                    5: Remote wakeup,
+                                    4..0: resvd */
+       50,         /*  u8  MaxPower; */
+      
+       /* USB 1.1:
+        * USB 2.0, single TT organization (mandatory):
+        *      one interface, protocol 0
+        *
+        * USB 2.0, multiple TT organization (optional):
+        *      two interfaces, protocols 1 (like single TT)
+        *      and 2 (multiple TT mode) ... config is
+        *      sometimes settable
+        *      NOT IMPLEMENTED
+        */
+
+       /* 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; */
+       0x01,       /*  u8  if_bInterfaceSubClass; */
+       0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
+       0x05,       /*  u8  if_iInterface; */
+
+        /* HID descriptor */
+        0x09,        /*  u8  bLength; */
+        0x21,        /*  u8 bDescriptorType; */
+        0x01, 0x00,  /*  u16 HID_class */
+        0x00,        /*  u8 country_code */
+        0x01,        /*  u8 num_descriptors */
+        0x22,        /*  u8 type; Report */
+        65, 0,       /*  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; */
+       0x03,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
 };
 
 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
@@ -121,6 +182,41 @@
     0xC0, 0xC0,
 };
 
+static const uint8_t qemu_tablet_hid_report_descriptor[] = {
+        0x05, 0x01, /* Usage Page Generic Desktop */
+        0x09, 0x01, /* Usage Mouse */
+        0xA1, 0x01, /* Collection Application */
+        0x09, 0x01, /* Usage Pointer */
+        0xA1, 0x00, /* Collection Physical */
+        0x05, 0x09, /* Usage Page Button */
+        0x19, 0x01, /* Usage Minimum Button 1 */
+        0x29, 0x03, /* Usage Maximum Button 3 */
+        0x15, 0x00, /* Logical Minimum 0 */
+        0x25, 0x01, /* Logical Maximum 1 */
+        0x95, 0x03, /* Report Count 3 */
+        0x75, 0x01, /* Report Size 1 */
+        0x81, 0x02, /* Input (Data, Var, Abs) */
+        0x95, 0x01, /* Report Count 1 */
+        0x75, 0x05, /* Report Size 5 */
+        0x81, 0x01, /* Input (Cnst, Var, Abs) */
+        0x05, 0x01, /* Usage Page Generic Desktop */
+        0x09, 0x30, /* Usage X */
+        0x09, 0x31, /* Usage Y */
+        0x15, 0x00, /* Logical Minimum 0 */
+        0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum 0xffff */
+        0x75, 0x10, /* Report Size 16 */
+        0x95, 0x02, /* Report Count 2 */
+        0x81, 0x02, /* Input (Data, Var, Abs) */
+        0x09, 0x38, /* Usage Wheel */
+        0x15, 0x81, /* Logical Minimum -127 */
+        0x25, 0x7F, /* Logical Maximum 127 */
+        0x75, 0x08, /* Report Size 8 */
+        0x95, 0x01, /* Report Count 1 */
+        0x81, 0x02, /* Input (Data, Var, Rel) */
+        0xC0,       /* End Collection */
+        0xC0,       /* End Collection */
+};
+
 static void usb_mouse_event(void *opaque,
                             int dx1, int dy1, int dz1, int buttons_state)
 {
@@ -129,6 +225,17 @@
     s->dx += dx1;
     s->dy += dy1;
     s->dz += dz1;
+    s->buttons_state = buttons_state;
+}
+
+static void usb_tablet_event(void *opaque,
+                            int x, int y, int dz, int buttons_state)
+{
+    USBMouseState *s = opaque;
+
+    s->x = x;
+    s->y = y;
+    s->dz += dz;
     s->buttons_state = buttons_state;
 }
 
@@ -146,6 +253,11 @@
 {
     int dx, dy, dz, b, l;
 
+    if (!s->mouse_grabbed) {
+       qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+       s->mouse_grabbed = 1;
+    }
+    
     dx = int_clamp(s->dx, -128, 127);
     dy = int_clamp(s->dy, -128, 127);
     dz = int_clamp(s->dz, -128, 127);
@@ -173,6 +285,39 @@
     return l;
 }
 
+static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
+{
+    int dz, b, l;
+
+    if (!s->mouse_grabbed) {
+       qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+       s->mouse_grabbed = 1;
+    }
+    
+    dz = int_clamp(s->dz, -128, 127);
+    s->dz -= dz;
+
+    /* Appears we have to invert the wheel direction */
+    dz = 0 - dz;
+    b = 0;
+    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+        b |= 0x01;
+    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+        b |= 0x02;
+    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+        b |= 0x04;
+
+    buf[0] = b;
+    buf[1] = s->x & 0xff;
+    buf[2] = s->x >> 8;
+    buf[3] = s->y & 0xff;
+    buf[4] = s->y >> 8;
+    buf[5] = dz;
+    l = 6;
+
+    return l;
+}
+
 static void usb_mouse_handle_reset(USBDevice *dev)
 {
     USBMouseState *s = (USBMouseState *)dev;
@@ -180,6 +325,8 @@
     s->dx = 0;
     s->dy = 0;
     s->dz = 0;
+    s->x = 0;
+    s->y = 0;
     s->buttons_state = 0;
 }
 
@@ -187,7 +334,7 @@
                                   int index, int length, uint8_t *data)
 {
     USBMouseState *s = (USBMouseState *)dev;
-    int ret;
+    int ret = 0;
 
     switch(request) {
     case DeviceRequest | USB_REQ_GET_STATUS:
@@ -224,9 +371,15 @@
             ret = sizeof(qemu_mouse_dev_descriptor);
             break;
         case USB_DT_CONFIG:
-            memcpy(data, qemu_mouse_config_descriptor, 
-                   sizeof(qemu_mouse_config_descriptor));
-            ret = sizeof(qemu_mouse_config_descriptor);
+           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);
+           }           
             break;
         case USB_DT_STRING:
             switch(value & 0xff) {
@@ -244,7 +397,10 @@
                 break;
             case 2:
                 /* product description */
-                ret = set_usb_string(data, "QEMU USB Mouse");
+               if (s->kind == USB_MOUSE)
+                   ret = set_usb_string(data, "QEMU USB Mouse");
+               else if (s->kind == USB_TABLET)
+                   ret = set_usb_string(data, "QEMU USB Tablet");
                 break;
             case 3:
                 /* vendor description */
@@ -282,16 +438,25 @@
     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
         switch(value >> 8) {
         case 0x22:
-            memcpy(data, qemu_mouse_hid_report_descriptor, 
-                   sizeof(qemu_mouse_hid_report_descriptor));
-            ret = sizeof(qemu_mouse_hid_report_descriptor);
-            break;
+           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);
+           }
+           break;
         default:
             goto fail;
         }
         break;
     case GET_REPORT:
-        ret = usb_mouse_poll(s, data, length);
+       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);
         break;
     case SET_IDLE:
         ret = 0;
@@ -308,12 +473,15 @@
                                  uint8_t devep, uint8_t *data, int len)
 {
     USBMouseState *s = (USBMouseState *)dev;
-    int ret;
+    int ret = 0;
 
     switch(pid) {
     case USB_TOKEN_IN:
         if (devep == 1) {
-            ret = usb_mouse_poll(s, data, len);
+           if (s->kind == USB_MOUSE)
+               ret = usb_mouse_poll(s, data, len);
+           else if (s->kind == USB_TABLET)
+               ret = usb_tablet_poll(s, data, len);
         } else {
             goto fail;
         }
@@ -327,7 +495,7 @@
     return ret;
 }
 
-USBDevice *usb_mouse_init(void)
+USBDevice *usb_tablet_init(void)
 {
     USBMouseState *s;
 
@@ -340,8 +508,25 @@
     s->dev.handle_reset = usb_mouse_handle_reset;
     s->dev.handle_control = usb_mouse_handle_control;
     s->dev.handle_data = usb_mouse_handle_data;
-
-    qemu_add_mouse_event_handler(usb_mouse_event, s);
-    
+    s->kind = USB_TABLET;
+
     return (USBDevice *)s;
 }
+
+USBDevice *usb_mouse_init(void)
+{
+    USBMouseState *s;
+
+    s = qemu_mallocz(sizeof(USBMouseState));
+    if (!s)
+        return NULL;
+    s->dev.speed = USB_SPEED_FULL;
+    s->dev.handle_packet = usb_generic_handle_packet;
+
+    s->dev.handle_reset = usb_mouse_handle_reset;
+    s->dev.handle_control = usb_mouse_handle_control;
+    s->dev.handle_data = usb_mouse_handle_data;
+    s->kind = USB_MOUSE;
+
+    return (USBDevice *)s;
+}
diff -r 6a786a97b822 hw/usb.h
--- a/hw/usb.h  Mon Apr 10 01:47:35 2006 +0000
+++ b/hw/usb.h  Sun Apr  9 22:34:20 2006 -0500
@@ -163,3 +163,4 @@
 
 /* usb-hid.c */
 USBDevice *usb_mouse_init(void);
+USBDevice *usb_tablet_init(void);
diff -r 6a786a97b822 sdl.c
--- a/sdl.c     Mon Apr 10 01:47:35 2006 +0000
+++ b/sdl.c     Sun Apr  9 22:34:20 2006 -0500
@@ -39,6 +39,10 @@
 static int gui_fullscreen_initial_grab;
 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
 static uint8_t modifiers_state[256];
+static int width, height;
+static SDL_Cursor *sdl_cursor_normal;
+static SDL_Cursor *sdl_cursor_hidden;
+static int absolute_enabled = 0;
 
 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 {
@@ -55,6 +59,9 @@
     flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
     if (gui_fullscreen)
         flags |= SDL_FULLSCREEN;
+
+    width = w;
+    height = h;
 
  again:
     screen = SDL_SetVideoMode(w, h, 0, flags);
@@ -271,9 +278,21 @@
     SDL_WM_SetCaption(buf, "QEMU");
 }
 
+static void sdl_hide_cursor(void)
+{
+    SDL_SetCursor(sdl_cursor_hidden);
+}
+
+static void sdl_show_cursor(void)
+{
+    if (!kbd_mouse_is_absolute()) {
+       SDL_SetCursor(sdl_cursor_normal);
+    }
+}
+
 static void sdl_grab_start(void)
 {
-    SDL_ShowCursor(0);
+    sdl_hide_cursor();
     SDL_WM_GrabInput(SDL_GRAB_ON);
     /* dummy read to avoid moving the mouse */
     SDL_GetRelativeMouseState(NULL, NULL);
@@ -284,7 +303,7 @@
 static void sdl_grab_end(void)
 {
     SDL_WM_GrabInput(SDL_GRAB_OFF);
-    SDL_ShowCursor(1);
+    sdl_show_cursor();
     gui_grab = 0;
     sdl_update_caption();
 }
@@ -300,6 +319,21 @@
         buttons |= MOUSE_EVENT_RBUTTON;
     if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
         buttons |= MOUSE_EVENT_MBUTTON;
+
+    if (kbd_mouse_is_absolute()) {
+       if (!absolute_enabled) {
+           sdl_hide_cursor();
+           if (gui_grab) {
+               sdl_grab_end();
+           }
+           absolute_enabled = 1;
+       }
+
+       SDL_GetMouseState(&dx, &dy);
+       dx = dx * 0x7FFF / width;
+       dy = dy * 0x7FFF / height;
+    }
+
     kbd_mouse_event(dx, dy, dz, buttons);
 }
 
@@ -423,7 +457,7 @@
             qemu_system_shutdown_request();
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab) {
+            if (gui_grab || kbd_mouse_is_absolute()) {
                 sdl_send_mouse_event(0);
             }
             break;
@@ -431,7 +465,7 @@
         case SDL_MOUSEBUTTONUP:
             {
                 SDL_MouseButtonEvent *bev = &ev->button;
-                if (!gui_grab) {
+                if (!gui_grab && !kbd_mouse_is_absolute()) {
                     if (ev->type == SDL_MOUSEBUTTONDOWN &&
                         (bev->state & SDL_BUTTON_LMASK)) {
                         /* start grabbing all events */
@@ -471,6 +505,7 @@
 void sdl_display_init(DisplayState *ds, int full_screen)
 {
     int flags;
+    uint8_t data = 0;
 
 #if defined(__APPLE__)
     /* always use generic keymaps */
@@ -504,6 +539,9 @@
     SDL_EnableUNICODE(1);
     gui_grab = 0;
 
+    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
+    sdl_cursor_normal = SDL_GetCursor();
+
     atexit(sdl_cleanup);
     if (full_screen) {
         gui_fullscreen = 1;
diff -r 6a786a97b822 vl.c
--- a/vl.c      Mon Apr 10 01:47:35 2006 +0000
+++ b/vl.c      Sun Apr  9 22:34:20 2006 -0500
@@ -474,6 +474,7 @@
 static void *qemu_put_kbd_event_opaque;
 static QEMUPutMouseEvent *qemu_put_mouse_event;
 static void *qemu_put_mouse_event_opaque;
+static int qemu_put_mouse_event_absolute;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
@@ -481,10 +482,11 @@
     qemu_put_kbd_event = func;
 }
 
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
+void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int 
absolute)
 {
     qemu_put_mouse_event_opaque = opaque;
     qemu_put_mouse_event = func;
+    qemu_put_mouse_event_absolute = absolute;
 }
 
 void kbd_put_keycode(int keycode)
@@ -500,6 +502,11 @@
         qemu_put_mouse_event(qemu_put_mouse_event_opaque, 
                              dx, dy, dz, buttons_state);
     }
+}
+
+int kbd_mouse_is_absolute(void)
+{
+    return qemu_put_mouse_event_absolute;
 }
 
 /***********************************************************/
@@ -2855,6 +2862,10 @@
         dev = usb_mouse_init();
         if (!dev)
             return -1;
+    } else if (!strcmp(devname, "tablet")) {
+       dev = usb_tablet_init();
+       if (!dev)
+           return -1;
     } else {
         return -1;
     }
diff -r 6a786a97b822 vl.h
--- a/vl.h      Mon Apr 10 01:47:35 2006 +0000
+++ b/vl.h      Sun Apr  9 22:34:20 2006 -0500
@@ -158,10 +158,11 @@
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int 
buttons_state);
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque);
+void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int 
absolute);
 
 void kbd_put_keycode(int keycode);
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
+int kbd_mouse_is_absolute(void);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]