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 16:39:06 -0500
User-agent: Mail/News 1.5 (X11/20060309)

Brad Campbell wrote:
Anthony Liguori wrote:
Hi Brad,

I have your patch applied and the previous one and it doesn't seem to work under win2k. Can you post a patch of what you have?

I've got what I have attached. I did a little bit of SDL plumbing based on my touchscreen patch.


Ok.. now I've embarrassed myself by publicly releasing my spaghetti, I've had a look at what you are up to.. The VNC patch extends the existing mouse handler by passing it abs coordinates as well, (this is the basis of what I used) so there are no additional routines.. I figure if you pass both relative (faked if need be) and abs to the routine then the mouse can use whatever it likes.

I don't really like that myself.


It looks like you are adding a completely separate handler there ?

Yeah, I figure if a device is interested only in relative movements (like the PS/2 mouse), that's all it should get.

I had to stop the ps2 mouse handler registering itself to let the usb one have a go. But now its working. I've left both cursors live so you can see how well it mates up. There is a minor elastic discrepancy toward the bottom right of the screen, but I'm *sure* its just due to my off the top of my head hacky position calculations and it can be refined further..

Everything seems to work fine for me. Both mice get their own coordinates and the guest choices which one it wants. In Windows, once you log in the first time, it detects the mouse and switches over to the USB mouse.

I've added the necessary stuff to SDL so that the switch over occurs gracefully. Once the USB mouse starts being used, SDL no longer triggers grab on left click (but still on ctrl-alt) and always reports mouse movements. I also got rid of the ShowCursor() calls as that warps the host mouse.

I figure a command line switch for usbmouse/usbabs/ps2 might be in order so you can change depending on your os. Hopefully the evdev patch in X gets up and running and we can just default to abs mode.

I'm not sure a command line switch is needed. I think we can have it automatically do the right thing. Attached is my latest patch. I did some awful things to SDL that I'd like to clean up. The only real "feature" I'd like to add is automatic breaking of grap when the USB mouse is detected.


I'll get hold of a wheel mouse tomorrow (my trackpad does not have a Z) and see if I can get the Z axis going..

Tested under win2k-SP4. How cool is it to be grabless and change resolutions on the fly.. I'll clean it up tomorrow and graft it into the vnc patch also.. virtual servers here we come!

Seriously, awesome job here :-)

Regards,

Anthony Liguori


Brad

diff -r 8937c657c23f 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:29: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,40 @@
     }
     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 */
+    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 +254,8 @@
     s->dx = 0;
     s->dy = 0;
     s->dz = 0;
+    s->X = 0;
+    s->Y = 0;
     s->buttons_state = 0;
 }
 
@@ -341,7 +417,8 @@
     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_event_handler(NULL, NULL);
+    qemu_add_mouse_abs_event_handler(usb_mouse_event, s);
     
     return (USBDevice *)s;
 }
diff -r 8937c657c23f sdl.c
--- a/sdl.c     Sun Mar 26 01:31:22 2006 +0000
+++ b/sdl.c     Sun Apr  9 16:29:35 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 cursor_hidden = 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);
@@ -273,7 +280,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 +293,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 +313,17 @@
     if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
         buttons |= MOUSE_EVENT_MBUTTON;
     kbd_mouse_event(dx, dy, dz, buttons);
+
+    SDL_GetMouseState(&dx, &dy);
+    kbd_mouse_abs_event(dx * 0x7FFF / width,
+                       dy * 0x7FFF / height,
+                       dz, buttons);
+    if (absolute_mouse && !cursor_hidden) {
+       sdl_cursor_normal = SDL_GetCursor();
+       SDL_SetCursor(sdl_cursor_hidden);
+       cursor_hidden = 1;
+    }
+       
 }
 
 static void toggle_full_screen(DisplayState *ds)
@@ -427,7 +450,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 +458,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 +498,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 +532,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 vl.c
--- a/vl.c      Sun Mar 26 01:31:22 2006 +0000
+++ b/vl.c      Sun Apr  9 16:29: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 vl.h
--- a/vl.h      Sun Mar 26 01:31:22 2006 +0000
+++ b/vl.h      Sun Apr  9 16:29: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]