[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] qemu mouse: Adds support for USB mouse/tablet status check and
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 60bbcf799384d779c2a561b9d9ba30f28e31d970 # Parent fb3cb6f52a2905be938559529ae43b6ba990c878 [HVM] qemu mouse: Adds support for USB mouse/tablet status check and restricts Universal Host Controller interrupt generating when received NAK in interrupt transfer. According to usb spec, USB mouse/tablet device returns NAK to host controller if its status does not alter in interrupt transfer. And UHC should leave a TD active when receiving NAK and execute this incompleted TD in a subseqent frame. UHC only generates an interrupt on complete after the TD with ICO bit is completed. This patch make UHC & USB mouse/tablet behave consistently with spec. Signed-off-by: Xinmei Huang <xinmei.huang@xxxxxxxxx> --- tools/ioemu/hw/usb-hid.c | 19 +++++++++++++++---- tools/ioemu/hw/usb-uhci.c | 42 +++++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff -r fb3cb6f52a29 -r 60bbcf799384 tools/ioemu/hw/usb-hid.c --- a/tools/ioemu/hw/usb-hid.c Thu Dec 07 11:51:22 2006 +0000 +++ b/tools/ioemu/hw/usb-hid.c Thu Dec 07 11:52:26 2006 +0000 @@ -39,6 +39,7 @@ typedef struct USBMouseState { int x, y; int kind; int mouse_grabbed; + int status_changed; } USBMouseState; /* mostly the same values as the Bochs USB Mouse device */ @@ -231,6 +232,7 @@ static void usb_mouse_event(void *opaque s->dy += dy1; s->dz += dz1; s->buttons_state = buttons_state; + s->status_changed = 1; } static void usb_tablet_event(void *opaque, @@ -242,6 +244,7 @@ static void usb_tablet_event(void *opaqu s->y = y; s->dz += dz; s->buttons_state = buttons_state; + s->status_changed = 1; } static inline int int_clamp(int val, int vmin, int vmax) @@ -483,10 +486,16 @@ static int usb_mouse_handle_data(USBDevi switch(pid) { case USB_TOKEN_IN: if (devep == 1) { - 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); + 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); + + if (!s->status_changed) + ret = USB_RET_NAK; + else + s->status_changed = 0; + } else { goto fail; } @@ -523,6 +532,7 @@ USBDevice *usb_tablet_init(void) s->dev.handle_data = usb_mouse_handle_data; s->dev.handle_destroy = usb_mouse_handle_destroy; s->kind = USB_TABLET; + s->status_changed = 0; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); @@ -544,6 +554,7 @@ USBDevice *usb_mouse_init(void) s->dev.handle_data = usb_mouse_handle_data; s->dev.handle_destroy = usb_mouse_handle_destroy; s->kind = USB_MOUSE; + s->status_changed = 0; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); diff -r fb3cb6f52a29 -r 60bbcf799384 tools/ioemu/hw/usb-uhci.c --- a/tools/ioemu/hw/usb-uhci.c Thu Dec 07 11:51:22 2006 +0000 +++ b/tools/ioemu/hw/usb-uhci.c Thu Dec 07 11:52:26 2006 +0000 @@ -424,12 +424,10 @@ static int uhci_handle_td(UHCIState *s, uint8_t buf[2048]; int len, max_len, err, ret; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - - if (!(td->ctrl & TD_CTRL_ACTIVE)) - return 1; + if (!(td->ctrl & TD_CTRL_ACTIVE)){ + ret = 1; + goto out; + } /* TD is active */ max_len = ((td->token >> 21) + 1) & 0x7ff; @@ -467,7 +465,8 @@ static int uhci_handle_td(UHCIState *s, /* invalid pid : frame interrupted */ s->status |= UHCI_STS_HCPERR; uhci_update_irq(s); - return -1; + ret = -1; + goto out; } if (td->ctrl & TD_CTRL_IOS) td->ctrl &= ~TD_CTRL_ACTIVE; @@ -479,10 +478,12 @@ static int uhci_handle_td(UHCIState *s, len < max_len) { *int_mask |= 0x02; /* short packet: do not update QH */ - return 1; + ret = 1; + goto out; } else { /* success */ - return 0; + ret = 0; + goto out; } } else { switch(ret) { @@ -501,23 +502,34 @@ static int uhci_handle_td(UHCIState *s, } td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | (err << TD_CTRL_ERROR_SHIFT); - return 1; + ret = 1; + goto out; case USB_RET_NAK: td->ctrl |= TD_CTRL_NAK; if (pid == USB_TOKEN_SETUP) goto do_timeout; - return 1; + ret = 1; + goto out; case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; - return 1; + ret = 1; + goto out; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; /* frame interrupted */ - return -1; - } - } + ret = -1; + goto out; + } + } + +out: + /* If TD is inactive and IOC bit set to 1 then update int_mask */ + if ((td->ctrl & TD_CTRL_IOC) && (!(td->ctrl & TD_CTRL_ACTIVE))) { + *int_mask |= 0x01; + } + return ret; } static void uhci_frame_timer(void *opaque) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |