qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] Support detaching of USB-HID devices


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH] Support detaching of USB-HID devices
Date: Sat, 15 Apr 2006 11:34:01 -0500
User-agent: Mail/News 1.5 (X11/20060309)

The attached patch allows one to detach USB-HID devices with usb_del. It adds the necessary logic to switch back and forth between PS/2 and USB-HID devices. I've tested with Windows and Linux guests (using the evtouch driver). See the changeset commit message for more details.

I wasn't confident on some of the changes (like where I hooked USB device detach) so feedback is greatly appreciated.

Regards,

Anthony Liguori
# HG changeset patch
# User Anthony Liguori <address@hidden>
# Node ID 22c4f274525ecf9e084324263f2994a6f0889156
# Parent  aeef66a23a99331481a589968d2ba5d6eda49593
Add support for detaching USB devices.

This patch adds the necessary infrastructure to USBDevice so that devices can
be notified when they are removed.  This patch also introduces stackable mouse
event handlers so that the USB mice can remove their mouse event handlers
allowing the PS/2 mouse to be restored.

Finally, this patch updates the SDL interface so that the transition from
relative mode to absolute and vice versa is transparent to the user.

diff -r aeef66a23a99 -r 22c4f274525e hw/usb-hid.c
--- a/hw/usb-hid.c      Thu Apr 13 02:59:55 2006 +0000
+++ b/hw/usb-hid.c      Sat Apr 15 11:23:24 2006 -0500
@@ -38,7 +38,7 @@
     int dx, dy, dz, buttons_state;
     int x, y;
     int kind;
-    int mouse_grabbed;
+    int mouse_id;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -258,9 +258,8 @@
 {
     int dx, dy, dz, b, l;
 
-    if (!s->mouse_grabbed) {
-       qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
-       s->mouse_grabbed = 1;
+    if (!s->mouse_id) {
+       s->mouse_id = qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
     }
     
     dx = int_clamp(s->dx, -128, 127);
@@ -294,9 +293,8 @@
 {
     int dz, b, l;
 
-    if (!s->mouse_grabbed) {
-       qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
-       s->mouse_grabbed = 1;
+    if (!s->mouse_id) {
+        s->mouse_id = qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
     }
     
     dz = int_clamp(s->dz, -128, 127);
@@ -500,6 +498,15 @@
     return ret;
 }
 
+static void usb_mouse_detach(USBDevice *dev)
+{
+    USBMouseState *s = (USBMouseState *)dev;
+
+    if (s->mouse_id) {
+       qemu_del_mouse_event_handler(s->mouse_id);
+    }
+}
+
 USBDevice *usb_tablet_init(void)
 {
     USBMouseState *s;
@@ -509,11 +516,12 @@
         return NULL;
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
-
+    s->dev.handle_detach = usb_mouse_detach;
     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_TABLET;
+    s->mouse_id = 0;
 
     return (USBDevice *)s;
 }
@@ -527,11 +535,12 @@
         return NULL;
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
-
+    s->dev.handle_detach = usb_mouse_detach;
     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;
+    s->mouse_id = 0;
 
     return (USBDevice *)s;
 }
diff -r aeef66a23a99 -r 22c4f274525e hw/usb.c
--- a/hw/usb.c  Thu Apr 13 02:59:55 2006 +0000
+++ b/hw/usb.c  Sat Apr 15 11:23:24 2006 -0500
@@ -354,6 +354,10 @@
     } else {
         dev = port->port.dev;
         if (dev) {
+           if (dev->handle_detach) {
+               dev->handle_detach(dev);
+           }
+
             port->wPortStatus &= ~PORT_STAT_CONNECTION;
             port->wPortChange |= PORT_STAT_C_CONNECTION;
             if (port->wPortStatus & PORT_STAT_ENABLE) {
diff -r aeef66a23a99 -r 22c4f274525e hw/usb.h
--- a/hw/usb.h  Thu Apr 13 02:59:55 2006 +0000
+++ b/hw/usb.h  Sat Apr 15 11:23:24 2006 -0500
@@ -126,6 +126,7 @@
                           int index, int length, uint8_t *data);
     int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
                        uint8_t *data, int len);
+    void (*handle_detach)(USBDevice *dev);
     uint8_t addr;
     
     int state;
diff -r aeef66a23a99 -r 22c4f274525e sdl.c
--- a/sdl.c     Thu Apr 13 02:59:55 2006 +0000
+++ b/sdl.c     Sat Apr 15 11:23:24 2006 -0500
@@ -285,7 +285,7 @@
 
 static void sdl_show_cursor(void)
 {
-    if (!kbd_mouse_is_absolute()) {
+    if (!absolute_enabled) {
        SDL_SetCursor(sdl_cursor_normal);
     }
 }
@@ -306,6 +306,26 @@
     sdl_show_cursor();
     gui_grab = 0;
     sdl_update_caption();
+}
+
+/* check to see if we've enabled or disabled an absolute or relative mouse */
+
+static void sdl_check_mouse_change(void *opaque, int absolute)
+{
+    if (absolute) {
+        if (!absolute_enabled) {
+            absolute_enabled = 1;
+            sdl_hide_cursor();
+            if (gui_grab) {
+                sdl_grab_end();
+            }
+        }
+    } else if (absolute_enabled) {
+        absolute_enabled = 0;
+        if (!gui_grab) {
+            sdl_show_cursor();
+        }
+    }
 }
 
 static void sdl_send_mouse_event(int dz)
@@ -320,18 +340,10 @@
     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;
+    if (absolute_enabled) {
+        SDL_GetMouseState(&dx, &dy);
+        dx = dx * 0x7FFF / width;
+        dy = dy * 0x7FFF / height;
     }
 
     kbd_mouse_event(dx, dy, dz, buttons);
@@ -457,7 +469,7 @@
             qemu_system_shutdown_request();
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab || kbd_mouse_is_absolute()) {
+            if (gui_grab || absolute_enabled) {
                 sdl_send_mouse_event(0);
             }
             break;
@@ -465,7 +477,7 @@
         case SDL_MOUSEBUTTONUP:
             {
                 SDL_MouseButtonEvent *bev = &ev->button;
-                if (!gui_grab && !kbd_mouse_is_absolute()) {
+                if (!gui_grab && !absolute_enabled) {
                     if (ev->type == SDL_MOUSEBUTTONDOWN &&
                         (bev->state & SDL_BUTTON_LMASK)) {
                         /* start grabbing all events */
@@ -542,6 +554,8 @@
     sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
     sdl_cursor_normal = SDL_GetCursor();
 
+    qemu_add_mouse_change_handler(sdl_check_mouse_change, NULL);
+
     atexit(sdl_cleanup);
     if (full_screen) {
         gui_fullscreen = 1;
diff -r aeef66a23a99 -r 22c4f274525e vl.c
--- a/vl.c      Thu Apr 13 02:59:55 2006 +0000
+++ b/vl.c      Sat Apr 15 11:23:24 2006 -0500
@@ -472,9 +472,6 @@
 
 static QEMUPutKBDEvent *qemu_put_kbd_event;
 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)
 {
@@ -482,11 +479,94 @@
     qemu_put_kbd_event = func;
 }
 
-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;
+typedef struct QEMUMouseEventHandler
+{
+    QEMUPutMouseEvent *handler;
+    void *opaque;
+    int is_absolute;
+    int id;
+    struct QEMUMouseEventHandler *next;
+} QEMUMouseEventHandler;
+
+static QEMUMouseEventHandler *qemu_put_mouse_event;
+static QEMUMouseChangeEvent *qemu_mouse_change_event;
+static void *qemu_mouse_change_event_opaque;
+
+int qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque,
+                                int absolute)
+{
+    QEMUMouseEventHandler *mouse;
+    int old_absolute = 0;
+
+    if (qemu_put_mouse_event) {
+       old_absolute = qemu_put_mouse_event->is_absolute;
+    }
+
+    mouse = qemu_mallocz(sizeof(QEMUMouseEventHandler));
+    if (!mouse)
+       return -1;
+
+    mouse->handler = func;
+    mouse->opaque = opaque;
+    mouse->is_absolute = absolute;
+
+    if (qemu_put_mouse_event) {
+       mouse->id = qemu_put_mouse_event->id + 1;
+    } else {
+       mouse->id = 1;
+    }
+
+    mouse->next = qemu_put_mouse_event;
+    qemu_put_mouse_event = mouse;
+
+    if (old_absolute != absolute && qemu_mouse_change_event) {
+       qemu_mouse_change_event(qemu_mouse_change_event_opaque, absolute);
+    }
+
+    return mouse->id;
+}
+
+void qemu_del_mouse_event_handler(int id)
+{
+    QEMUMouseEventHandler **pm, *m;
+    int old_absolute = 0;
+    int absolute = 0;
+
+    if (qemu_put_mouse_event) {
+       old_absolute = qemu_put_mouse_event->is_absolute;
+    }
+    
+    pm = &qemu_put_mouse_event;
+    for(;;) {
+       m = *pm;
+       if (!m)
+           break;
+       if (m->id == id) {
+           *pm = m->next;
+           qemu_free(m);
+           break;
+       }
+       pm = &m->next;
+    }
+
+    if (qemu_put_mouse_event) {
+       absolute = qemu_put_mouse_event->is_absolute;
+    }
+    
+    if (old_absolute != absolute && qemu_mouse_change_event) {
+       qemu_mouse_change_event(qemu_mouse_change_event_opaque, absolute);
+    }
+}
+
+void qemu_add_mouse_change_handler(QEMUMouseChangeEvent *func, void *opaque)
+{
+    qemu_mouse_change_event = func;
+    qemu_mouse_change_event_opaque = opaque;
+
+    /* fire once in the event that we're already absolute */
+    if (qemu_put_mouse_event && qemu_put_mouse_event->is_absolute) {
+       func(opaque, qemu_put_mouse_event->is_absolute);
+    }
 }
 
 void kbd_put_keycode(int keycode)
@@ -499,14 +579,9 @@
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
 {
     if (qemu_put_mouse_event) {
-        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;
+       qemu_put_mouse_event->handler(qemu_put_mouse_event->opaque,
+                                     dx, dy, dz, buttons_state);
+    }
 }
 
 /***********************************************************/
diff -r aeef66a23a99 -r 22c4f274525e vl.h
--- a/vl.h      Thu Apr 13 02:59:55 2006 +0000
+++ b/vl.h      Sat Apr 15 11:23:24 2006 -0500
@@ -156,13 +156,16 @@
 
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int 
buttons_state);
+typedef void QEMUMouseChangeEvent(void *opaque, int absolute);
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int 
absolute);
+
+int qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int 
absolute);
+void qemu_del_mouse_event_handler(int handle);
+void qemu_add_mouse_change_handler(QEMUMouseChangeEvent *func, void *opaque);
 
 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]