📄 usb-mouse-tablet-status-check
字号:
# HG changeset patch# User kfraser@localhost.localdomain# Node ID 60bbcf799384d779c2a561b9d9ba30f28e31d970# Parent fb3cb6f52a2905be938559529ae43b6ba990c878[HVM] qemu mouse: Adds support for USB mouse/tablet status check andrestricts Universal Host Controller interrupt generating when receivedNAK in interrupt transfer.According to usb spec, USB mouse/tablet device returns NAK to hostcontroller if its status does not alter in interrupt transfer.And UHC should leave a TD active when receiving NAK and execute thisincompleted TD in a subseqent frame. UHC only generates an interrupton 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@intel.com>Index: ioemu/hw/usb-hid.c===================================================================--- ioemu.orig/hw/usb-hid.c 2007-05-09 14:11:27.000000000 +0100+++ ioemu/hw/usb-hid.c 2007-05-09 14:12:06.000000000 +0100@@ -39,6 +39,7 @@ int x, y; int kind; int mouse_grabbed;+ int status_changed; QEMUPutMouseEntry *eh_entry; } USBMouseState; @@ -232,6 +233,7 @@ s->dy += dy1; s->dz += dz1; s->buttons_state = buttons_state;+ s->status_changed = 1; } static void usb_tablet_event(void *opaque,@@ -243,6 +245,7 @@ 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)@@ -485,10 +488,16 @@ switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) {- if (s->kind == USB_MOUSE)- ret = usb_mouse_poll(s, p->data, p->len);- else if (s->kind == USB_TABLET)- ret = usb_tablet_poll(s, p->data, p->len);+ if (s->kind == USB_MOUSE)+ ret = usb_mouse_poll(s, p->data, p->len);+ else if (s->kind == USB_TABLET)+ ret = usb_tablet_poll(s, p->data, p->len);++ if (!s->status_changed)+ ret = USB_RET_NAK;+ else+ s->status_changed = 0;+ } else { goto fail; }@@ -570,6 +579,7 @@ 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"); @@ -593,6 +603,7 @@ 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"); Index: ioemu/hw/usb-uhci.c===================================================================--- ioemu.orig/hw/usb-uhci.c 2007-05-09 14:12:05.000000000 +0100+++ ioemu/hw/usb-uhci.c 2007-05-09 14:12:06.000000000 +0100@@ -43,9 +43,15 @@ #define TD_CTRL_IOC (1 << 24) #define TD_CTRL_ACTIVE (1 << 23) #define TD_CTRL_STALL (1 << 22)+#define TD_CTRL_BUFFER (1 << 21) #define TD_CTRL_BABBLE (1 << 20) #define TD_CTRL_NAK (1 << 19) #define TD_CTRL_TIMEOUT (1 << 18)+#define TD_CTRL_BITSTUFF \+ (1 << 17)+#define TD_CTRL_MASK \+ (TD_CTRL_BITSTUFF | TD_CTRL_TIMEOUT | TD_CTRL_NAK \+ | TD_CTRL_BABBLE | TD_CTRL_BUFFER | TD_CTRL_STALL) #define UHCI_PORT_RESET (1 << 9) #define UHCI_PORT_LSDA (1 << 8)@@ -431,13 +437,13 @@ uint8_t pid; int len, max_len, err, ret; - /* ??? This is wrong for async completion. */- if (td->ctrl & TD_CTRL_IOC) {- *int_mask |= 0x01;+ if (!(td->ctrl & TD_CTRL_ACTIVE)) {+ ret = 1;+ goto out; }- - if (!(td->ctrl & TD_CTRL_ACTIVE))- return 1;++ /* Clear TD's status field explicitly */+ td->ctrl = td->ctrl & (~TD_CTRL_MASK); /* TD is active */ max_len = ((td->token >> 21) + 1) & 0x7ff;@@ -493,11 +499,13 @@ /* invalid pid : frame interrupted */ s->status |= UHCI_STS_HCPERR; uhci_update_irq(s);- return -1;+ ret = -1;+ goto out; } } if (ret == USB_RET_ASYNC) {- return 2;+ ret = 2;+ goto out; } if (td->ctrl & TD_CTRL_IOS) td->ctrl &= ~TD_CTRL_ACTIVE;@@ -509,10 +517,12 @@ 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) {@@ -531,23 +541,34 @@ } 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_async_complete_packet(USBPacket * packet, void *opaque)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -