qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] Gentlemen we have absolute movement! was:Absolute USB-H


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

Brad Campbell wrote:
Anthony Liguori wrote:

+    kbd_mouse_abs_event(dx * 0x7FFF / width,
+            dy * 0x7FFF / height,

I had just made that same mod to my tree.. solved the tracking problem perfectly.

Now if only it would work under win98 without modification..

Look what I just stumbled across.. irrelevant now I guess..

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/Hid_d/hh/HID_d/km-ovr_8d838937-f6b9-4245-8bb0-758bf162af7e.xml.asp

I wonder.. does windows switch over from ps2 to hid or just react to both and given hid is more positive about where it wants the mouse to go it wins ? I'm sure I've used a ps2 mouse and a usb mouse on windows before.. I'm thought they both worked at the same time.

I think they do. I think the absolute movements just override the relative ones. However, this may just be a twist of fate so I think it's safer to disable relative reporting.

Like what you have with the rest of the patch.. I'll clean up my tree and go with that I think..

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.

That should work quite well for sdl, gtk and vnc displays.. I guess cocoa also.. Now all we need is X support. I guess as a temporary measure the wacom patch works with linux..

Creating a VM right now to try out the latest Xorg driver. Wacom for older Linux guests is probably not a bad idea.

Do you find having usb enabled makes the windows session feel a bit less responsive or jerkier ? I know the mouse tracking is not as smooth with usb.. perhaps having ps2 and usb on together will smooth that out a little.

I don't really see a difference. It actually seems a bit nicer with the USB mouse enabled (as the mouse moves with the same acceleration as under the host). One thing I noticed with the Wacom driver is that the PS/2 mouse tends to accelerate faster than the host mouse and that tends to give a feeling of a "snappier" interface. That may be what you're experiencing.

Regards,

Anthony Liguori

# HG changeset patch
# User Anthony Liguori <address@hidden>
# Node ID c2a6c24121b8a56622cafddf39812a37ab887600
# Parent  8937c657c23f99c8d352cc2b68a2e8a814243ec7
USB Mouse support for with absolute coordinates.  The HID modifications are
all from Brad Campbell <address@hidden>

diff -r 8937c657c23f -r c2a6c24121b8 hw/usb-hid.c
--- a/hw/usb-hid.c      Sun Mar 26 01:31:22 2006 +0000
+++ b/hw/usb-hid.c      Sun Apr  9 16:59:35 2006 -0500
@@ -33,6 +33,7 @@
 typedef struct USBMouseState {
     USBDevice dev;
     int dx, dy, dz, buttons_state;
+    int X, Y;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -92,14 +93,6 @@
        0x01,       /*  u8  if_bInterfaceSubClass; */
        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; */
@@ -108,9 +101,18 @@
         0x00,        /*  u8 country_code */
         0x01,        /*  u8 num_descriptors */
         0x22,        /*  u8 type; Report */
-        50, 0,       /*  u16 len */
+        53, 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) */
 };
 
+#if 0
 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
     0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 
     0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
@@ -120,6 +122,41 @@
     0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
     0xC0, 0xC0,
 };
+#else
+static const uint8_t qemu_mouse_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 32 */
+        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 */
+        0xC0,       /* End Collection */
+        0xC0,       /* End Collection */
+};
+#endif 
 
 static void usb_mouse_event(void *opaque,
                             int dx1, int dy1, int dz1, int buttons_state)
@@ -129,6 +166,8 @@
     s->dx += dx1;
     s->dy += dy1;
     s->dz += dz1;
+    s->X = dx1;
+    s->Y = dy1;
     s->buttons_state = buttons_state;
 }
 
@@ -142,6 +181,7 @@
         return val;
 }
 
+#if 0
 static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
 {
     int dx, dy, dz, b, l;
@@ -172,6 +212,44 @@
     }
     return l;
 }
+#else
+
+static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
+{
+    int dx, dy, dz, b, l;
+
+    /* FIXME this is ugly */
+    if (absolute_mouse == 0) {
+       /* disable the PS/2 mouse */
+       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;
+    s->dz -= 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;
+    l = 5;
+
+    return l;
+}
+#endif
 
 static void usb_mouse_handle_reset(USBDevice *dev)
 {
@@ -180,6 +258,8 @@
     s->dx = 0;
     s->dy = 0;
     s->dz = 0;
+    s->X = 0;
+    s->Y = 0;
     s->buttons_state = 0;
 }
 
@@ -341,7 +421,7 @@
     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);
+    qemu_add_mouse_abs_event_handler(usb_mouse_event, s);
     
     return (USBDevice *)s;
 }
diff -r 8937c657c23f -r c2a6c24121b8 sdl.c
--- a/sdl.c     Sun Mar 26 01:31:22 2006 +0000
+++ b/sdl.c     Sun Apr  9 16:59:35 2006 -0500
@@ -39,6 +39,11 @@
 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 cursor_hidden = 0;
+static int absolute_enabled = 0;
 
 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 {
@@ -55,6 +60,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);
@@ -273,7 +281,9 @@
 
 static void sdl_grab_start(void)
 {
-    SDL_ShowCursor(0);
+    sdl_cursor_normal = SDL_GetCursor();
+    SDL_SetCursor(sdl_cursor_hidden);
+    cursor_hidden = 1;
     SDL_WM_GrabInput(SDL_GRAB_ON);
     /* dummy read to avoid moving the mouse */
     SDL_GetRelativeMouseState(NULL, NULL);
@@ -284,7 +294,10 @@
 static void sdl_grab_end(void)
 {
     SDL_WM_GrabInput(SDL_GRAB_OFF);
-    SDL_ShowCursor(1);
+    if (!absolute_mouse) {
+       SDL_SetCursor(sdl_cursor_normal);
+       cursor_hidden = 1;
+    }
     gui_grab = 0;
     sdl_update_caption();
 }
@@ -301,6 +314,25 @@
     if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
         buttons |= MOUSE_EVENT_MBUTTON;
     kbd_mouse_event(dx, dy, dz, buttons);
+
+    if (absolute_mouse) {
+       if (!absolute_enabled) {
+           if (!cursor_hidden) {
+               sdl_cursor_normal = SDL_GetCursor();
+               SDL_SetCursor(sdl_cursor_hidden);
+               cursor_hidden = 1;
+           }
+           if (gui_grab) {
+               sdl_grab_end();
+           }
+           absolute_enabled = 1;
+       }
+
+       SDL_GetMouseState(&dx, &dy);
+       kbd_mouse_abs_event(dx * 0x7FFF / width,
+                           dy * 0x7FFF / height,
+                           dz, buttons);
+    }
 }
 
 static void toggle_full_screen(DisplayState *ds)
@@ -427,7 +459,7 @@
             qemu_system_shutdown_request();
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab) {
+            if (gui_grab || absolute_mouse) {
                 sdl_send_mouse_event(0);
             }
             break;
@@ -435,7 +467,7 @@
         case SDL_MOUSEBUTTONUP:
             {
                 SDL_MouseButtonEvent *bev = &ev->button;
-                if (!gui_grab) {
+                if (!gui_grab && !absolute_mouse) {
                     if (ev->type == SDL_MOUSEBUTTONDOWN &&
                         (bev->state & SDL_BUTTON_LMASK)) {
                         /* start grabbing all events */
@@ -475,6 +507,7 @@
 void sdl_display_init(DisplayState *ds, int full_screen)
 {
     int flags;
+    uint8_t data = 0;
 
 #if defined(__APPLE__)
     /* always use generic keymaps */
@@ -508,6 +541,8 @@
     SDL_EnableUNICODE(1);
     gui_grab = 0;
 
+    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
+
     atexit(sdl_cleanup);
     if (full_screen) {
         gui_fullscreen = 1;
diff -r 8937c657c23f -r c2a6c24121b8 vl.c
--- a/vl.c      Sun Mar 26 01:31:22 2006 +0000
+++ b/vl.c      Sun Apr  9 16:59:35 2006 -0500
@@ -148,6 +148,7 @@
 USBDevice *vm_usb_hub;
 static VLANState *first_vlan;
 int smp_cpus = 1;
+int absolute_mouse = 0;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -475,6 +476,8 @@
 static void *qemu_put_kbd_event_opaque;
 static QEMUPutMouseEvent *qemu_put_mouse_event;
 static void *qemu_put_mouse_event_opaque;
+static QEMUPutMouseAbsEvent *qemu_put_mouse_abs_event;
+static void *qemu_put_mouse_abs_event_opaque;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
@@ -486,6 +489,12 @@
 {
     qemu_put_mouse_event_opaque = opaque;
     qemu_put_mouse_event = func;
+}
+
+void qemu_add_mouse_abs_event_handler(QEMUPutMouseAbsEvent *func, void *opaque)
+{
+    qemu_put_mouse_abs_event_opaque = opaque;
+    qemu_put_mouse_abs_event = func;
 }
 
 void kbd_put_keycode(int keycode)
@@ -500,6 +509,14 @@
     if (qemu_put_mouse_event) {
         qemu_put_mouse_event(qemu_put_mouse_event_opaque, 
                              dx, dy, dz, buttons_state);
+    }
+}
+
+void kbd_mouse_abs_event(int x, int y, int dz, int buttons_state)
+{
+    if (qemu_put_mouse_abs_event) {
+       qemu_put_mouse_abs_event(qemu_put_mouse_abs_event_opaque,
+                                x, y, dz, buttons_state);
     }
 }
 
diff -r 8937c657c23f -r c2a6c24121b8 vl.h
--- a/vl.h      Sun Mar 26 01:31:22 2006 +0000
+++ b/vl.h      Sun Apr  9 16:59:35 2006 -0500
@@ -138,6 +138,7 @@
 extern int win2k_install_hack;
 extern int usb_enabled;
 extern int smp_cpus;
+extern int absolute_mouse;
 
 /* XXX: make it dynamic */
 #if defined (TARGET_PPC)
@@ -156,12 +157,15 @@
 
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int 
buttons_state);
+typedef void QEMUPutMouseAbsEvent(void *opaque, int x, int y, 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_abs_event_handler(QEMUPutMouseAbsEvent *func, void 
*opaque);
 
 void kbd_put_keycode(int keycode);
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
+void kbd_mouse_abs_event(int x, int y, int dz, int buttons_state);
 
 /* 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]