sim-card
/
qemu
Archived
10
0
Fork 0

Merge remote branch 'spice/usb.5' into staging

This commit is contained in:
Anthony Liguori 2011-02-01 15:21:23 -06:00
commit cfb41c82ab
6 changed files with 287 additions and 116 deletions

10
hw/hw.h
View File

@ -587,6 +587,16 @@ extern const VMStateDescription vmstate_i2c_slave;
.offset = vmstate_offset_value(_state, _field, i2c_slave), \ .offset = vmstate_offset_value(_state, _field, i2c_slave), \
} }
extern const VMStateDescription vmstate_usb_device;
#define VMSTATE_USB_DEVICE(_field, _state) { \
.name = (stringify(_field)), \
.size = sizeof(USBDevice), \
.vmsd = &vmstate_usb_device, \
.flags = VMS_STRUCT, \
.offset = vmstate_offset_value(_state, _field, USBDevice), \
}
#define vmstate_offset_macaddr(_state, _field) \ #define vmstate_offset_macaddr(_state, _field) \
vmstate_offset_array(_state, _field.a, uint8_t, \ vmstate_offset_array(_state, _field.a, uint8_t, \
sizeof(typeof_field(_state, _field))) sizeof(typeof_field(_state, _field)))

View File

@ -23,6 +23,22 @@ static struct BusInfo usb_bus_info = {
static int next_usb_bus = 0; static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses); static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
const VMStateDescription vmstate_usb_device = {
.name = "USBDevice",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
VMSTATE_UINT8(addr, USBDevice),
VMSTATE_INT32(state, USBDevice),
VMSTATE_INT32(remote_wakeup, USBDevice),
VMSTATE_INT32(setup_state, USBDevice),
VMSTATE_INT32(setup_len, USBDevice),
VMSTATE_INT32(setup_index, USBDevice),
VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
VMSTATE_END_OF_LIST(),
}
};
void usb_bus_new(USBBus *bus, DeviceState *host) void usb_bus_new(USBBus *bus, DeviceState *host)
{ {
qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL); qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
@ -282,20 +298,22 @@ static char *usb_get_fw_dev_path(DeviceState *qdev)
{ {
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
char *fw_path, *in; char *fw_path, *in;
int pos = 0; ssize_t pos = 0, fw_len;
long nr; long nr;
fw_path = qemu_malloc(32 + strlen(dev->port->path) * 6); fw_len = 32 + strlen(dev->port->path) * 6;
fw_path = qemu_malloc(fw_len);
in = dev->port->path; in = dev->port->path;
while (true) { while (fw_len - pos > 0) {
nr = strtol(in, &in, 10); nr = strtol(in, &in, 10);
if (in[0] == '.') { if (in[0] == '.') {
/* some hub between root port and device */ /* some hub between root port and device */
pos += sprintf(fw_path + pos, "hub@%ld/", nr); pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
in++; in++;
} else { } else {
/* the device itself */ /* the device itself */
pos += sprintf(fw_path + pos, "%s@%ld", qdev_fw_name(qdev), nr); pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
qdev_fw_name(qdev), nr);
break; break;
} }
} }

View File

@ -45,18 +45,27 @@
#define USB_TABLET 2 #define USB_TABLET 2
#define USB_KEYBOARD 3 #define USB_KEYBOARD 3
typedef struct USBPointerEvent {
int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
int32_t dz, buttons_state;
} USBPointerEvent;
#define QUEUE_LENGTH 16 /* should be enough for a triple-click */
#define QUEUE_MASK (QUEUE_LENGTH-1u)
#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
typedef struct USBMouseState { typedef struct USBMouseState {
int dx, dy, dz, buttons_state; USBPointerEvent queue[QUEUE_LENGTH];
int x, y;
int mouse_grabbed; int mouse_grabbed;
QEMUPutMouseEntry *eh_entry; QEMUPutMouseEntry *eh_entry;
} USBMouseState; } USBMouseState;
typedef struct USBKeyboardState { typedef struct USBKeyboardState {
uint32_t keycodes[QUEUE_LENGTH];
uint16_t modifiers; uint16_t modifiers;
uint8_t leds; uint8_t leds;
uint8_t key[16]; uint8_t key[16];
int keys; int32_t keys;
} USBKeyboardState; } USBKeyboardState;
typedef struct USBHIDState { typedef struct USBHIDState {
@ -65,8 +74,10 @@ typedef struct USBHIDState {
USBMouseState ptr; USBMouseState ptr;
USBKeyboardState kbd; USBKeyboardState kbd;
}; };
uint32_t head; /* index into circular queue */
uint32_t n;
int kind; int kind;
int protocol; int32_t protocol;
uint8_t idle; uint8_t idle;
int64_t next_idle_clock; int64_t next_idle_clock;
int changed; int changed;
@ -433,40 +444,79 @@ static void usb_hid_changed(USBHIDState *hs)
usb_wakeup(&hs->dev); usb_wakeup(&hs->dev);
} }
static void usb_mouse_event(void *opaque, static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
int dx1, int dy1, int dz1, int buttons_state) e->xdx = e->ydy = e->dz = 0;
{ e->buttons_state = buttons;
USBHIDState *hs = opaque;
USBMouseState *s = &hs->ptr;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
usb_hid_changed(hs);
} }
static void usb_tablet_event(void *opaque, static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
int x, int y, int dz, int buttons_state) int x1, int y1, int z1) {
if (xyrel) {
e->xdx += x1;
e->ydy += y1;
} else {
e->xdx = x1;
e->ydy = y1;
}
e->dz += z1;
}
static void usb_pointer_event(void *opaque,
int x1, int y1, int z1, int buttons_state)
{ {
USBHIDState *hs = opaque; USBHIDState *hs = opaque;
USBMouseState *s = &hs->ptr; USBMouseState *s = &hs->ptr;
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
s->x = x; /* We combine events where feasible to keep the queue small. We shouldn't
s->y = y; * combine anything with the first event of a particular button state, as
s->dz += dz; * that would change the location of the button state change. When the
s->buttons_state = buttons_state; * queue is empty, a second event is needed because we don't know if
* the first event changed the button state. */
if (hs->n == QUEUE_LENGTH) {
/* Queue full. Discard old button state, combine motion normally. */
s->queue[use_slot].buttons_state = buttons_state;
} else if (hs->n < 2 ||
s->queue[use_slot].buttons_state != buttons_state ||
s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
/* Cannot or should not combine, so add an empty item to the queue. */
QUEUE_INCR(use_slot);
hs->n++;
usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
}
usb_pointer_event_combine(&s->queue[use_slot],
hs->kind == USB_MOUSE,
x1, y1, z1);
usb_hid_changed(hs); usb_hid_changed(hs);
} }
static void usb_keyboard_event(void *opaque, int keycode) static void usb_keyboard_event(void *opaque, int keycode)
{ {
USBHIDState *hs = opaque; USBHIDState *hs = opaque;
USBKeyboardState *s = &hs->kbd;
int slot;
if (hs->n == QUEUE_LENGTH) {
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
s->keycodes[slot] = keycode;
usb_hid_changed(hs);
}
static void usb_keyboard_process_keycode(USBHIDState *hs)
{
USBKeyboardState *s = &hs->kbd; USBKeyboardState *s = &hs->kbd;
uint8_t hid_code, key; uint8_t hid_code, key;
int i; int i, keycode, slot;
if (hs->n == 0) {
return;
}
slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
keycode = s->keycodes[slot];
key = keycode & 0x7f; key = keycode & 0x7f;
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
@ -499,7 +549,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
if (s->key[i] == hid_code) { if (s->key[i] == hid_code) {
s->key[i] = s->key[-- s->keys]; s->key[i] = s->key[-- s->keys];
s->key[s->keys] = 0x00; s->key[s->keys] = 0x00;
usb_hid_changed(hs);
break; break;
} }
if (i < 0) if (i < 0)
@ -514,8 +563,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
} else } else
return; return;
} }
usb_hid_changed(hs);
} }
static inline int int_clamp(int val, int vmin, int vmax) static inline int int_clamp(int val, int vmin, int vmax)
@ -528,86 +575,96 @@ static inline int int_clamp(int val, int vmin, int vmax)
return val; return val;
} }
static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len) static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
{ {
int dx, dy, dz, b, l; int dx, dy, dz, b, l;
int index;
USBMouseState *s = &hs->ptr; USBMouseState *s = &hs->ptr;
USBPointerEvent *e;
if (!s->mouse_grabbed) { if (!s->mouse_grabbed) {
qemu_activate_mouse_event_handler(s->eh_entry); qemu_activate_mouse_event_handler(s->eh_entry);
s->mouse_grabbed = 1; s->mouse_grabbed = 1;
} }
dx = int_clamp(s->dx, -127, 127); /* When the buffer is empty, return the last event. Relative
dy = int_clamp(s->dy, -127, 127); movements will all be zero. */
dz = int_clamp(s->dz, -127, 127); index = (hs->n ? hs->head : hs->head - 1);
e = &s->queue[index & QUEUE_MASK];
s->dx -= dx; if (hs->kind == USB_MOUSE) {
s->dy -= dy; dx = int_clamp(e->xdx, -127, 127);
s->dz -= dz; dy = int_clamp(e->ydy, -127, 127);
e->xdx -= dx;
e->ydy -= dy;
} else {
dx = e->xdx;
dy = e->ydy;
}
dz = int_clamp(e->dz, -127, 127);
e->dz -= dz;
b = 0;
if (e->buttons_state & MOUSE_EVENT_LBUTTON)
b |= 0x01;
if (e->buttons_state & MOUSE_EVENT_RBUTTON)
b |= 0x02;
if (e->buttons_state & MOUSE_EVENT_MBUTTON)
b |= 0x04;
if (hs->n &&
!e->dz &&
(hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
/* that deals with this event */
QUEUE_INCR(hs->head);
hs->n--;
}
/* Appears we have to invert the wheel direction */ /* Appears we have to invert the wheel direction */
dz = 0 - dz; dz = 0 - 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;
l = 0; l = 0;
if (len > l) switch (hs->kind) {
buf[l ++] = b; case USB_MOUSE:
if (len > l) if (len > l)
buf[l ++] = dx; buf[l++] = b;
if (len > l) if (len > l)
buf[l ++] = dy; buf[l++] = dx;
if (len > l) if (len > l)
buf[l ++] = dz; buf[l++] = dy;
return l; if (len > l)
} buf[l++] = dz;
break;
static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len) case USB_TABLET:
{ if (len > l)
int dz, b, l; buf[l++] = b;
USBMouseState *s = &hs->ptr; if (len > l)
buf[l++] = dx & 0xff;
if (len > l)
buf[l++] = dx >> 8;
if (len > l)
buf[l++] = dy & 0xff;
if (len > l)
buf[l++] = dy >> 8;
if (len > l)
buf[l++] = dz;
break;
if (!s->mouse_grabbed) { default:
qemu_activate_mouse_event_handler(s->eh_entry); abort();
s->mouse_grabbed = 1;
} }
dz = int_clamp(s->dz, -127, 127);
s->dz -= dz;
/* Appears we have to invert the wheel direction */
dz = 0 - 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;
buf[5] = dz;
l = 6;
return l; return l;
} }
static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len) static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
{ {
USBKeyboardState *s = &hs->kbd;
if (len < 2) if (len < 2)
return 0; return 0;
usb_keyboard_process_keycode(hs);
buf[0] = s->modifiers & 0xff; buf[0] = s->modifiers & 0xff;
buf[1] = 0; buf[1] = 0;
if (s->keys > 6) if (s->keys > 6)
@ -643,12 +700,9 @@ static void usb_mouse_handle_reset(USBDevice *dev)
{ {
USBHIDState *s = (USBHIDState *)dev; USBHIDState *s = (USBHIDState *)dev;
s->ptr.dx = 0; memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
s->ptr.dy = 0; s->head = 0;
s->ptr.dz = 0; s->n = 0;
s->ptr.x = 0;
s->ptr.y = 0;
s->ptr.buttons_state = 0;
s->protocol = 1; s->protocol = 1;
} }
@ -657,6 +711,11 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
USBHIDState *s = (USBHIDState *)dev; USBHIDState *s = (USBHIDState *)dev;
qemu_add_kbd_event_handler(usb_keyboard_event, s); qemu_add_kbd_event_handler(usb_keyboard_event, s);
memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
s->head = 0;
s->n = 0;
memset(s->kbd.key, 0, sizeof (s->kbd.key));
s->kbd.keys = 0;
s->protocol = 1; s->protocol = 1;
} }
@ -708,12 +767,10 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
} }
break; break;
case GET_REPORT: case GET_REPORT:
if (s->kind == USB_MOUSE) if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
ret = usb_mouse_poll(s, data, length); ret = usb_pointer_poll(s, data, length);
else if (s->kind == USB_TABLET)
ret = usb_tablet_poll(s, data, length);
else if (s->kind == USB_KEYBOARD) else if (s->kind == USB_KEYBOARD)
ret = usb_keyboard_poll(&s->kbd, data, length); ret = usb_keyboard_poll(s, data, length);
break; break;
case SET_REPORT: case SET_REPORT:
if (s->kind == USB_KEYBOARD) if (s->kind == USB_KEYBOARD)
@ -762,13 +819,13 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0)) if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
return USB_RET_NAK; return USB_RET_NAK;
usb_hid_set_next_idle(s, curtime); usb_hid_set_next_idle(s, curtime);
s->changed = 0; if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
if (s->kind == USB_MOUSE) ret = usb_pointer_poll(s, p->data, p->len);
ret = usb_mouse_poll(s, p->data, p->len); }
else if (s->kind == USB_TABLET) else if (s->kind == USB_KEYBOARD) {
ret = usb_tablet_poll(s, p->data, p->len); ret = usb_keyboard_poll(s, p->data, p->len);
else if (s->kind == USB_KEYBOARD) }
ret = usb_keyboard_poll(&s->kbd, p->data, p->len); s->changed = s->n > 0;
} else { } else {
goto fail; goto fail;
} }
@ -803,13 +860,13 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
s->kind = kind; s->kind = kind;
if (s->kind == USB_MOUSE) { if (s->kind == USB_MOUSE) {
s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
0, "QEMU USB Mouse"); 0, "QEMU USB Mouse");
} else if (s->kind == USB_TABLET) { } else if (s->kind == USB_TABLET) {
s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s, s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
1, "QEMU USB Tablet"); 1, "QEMU USB Tablet");
} }
/* Force poll routine to be run and grab input the first time. */ /* Force poll routine to be run and grab input the first time. */
s->changed = 1; s->changed = 1;
return 0; return 0;
@ -838,12 +895,72 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
s->datain = datain; s->datain = datain;
} }
static int usb_hid_post_load(void *opaque, int version_id)
{
USBHIDState *s = opaque;
if (s->idle) {
usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
}
return 0;
}
static const VMStateDescription vmstate_usb_ptr_queue = {
.name = "usb-ptr-queue",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
VMSTATE_INT32(xdx, USBPointerEvent),
VMSTATE_INT32(ydy, USBPointerEvent),
VMSTATE_INT32(dz, USBPointerEvent),
VMSTATE_INT32(buttons_state, USBPointerEvent),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_usb_ptr = {
.name = "usb-ptr",
.version_id = 1,
.minimum_version_id = 1,
.post_load = usb_hid_post_load,
.fields = (VMStateField []) {
VMSTATE_USB_DEVICE(dev, USBHIDState),
VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
vmstate_usb_ptr_queue, USBPointerEvent),
VMSTATE_UINT32(head, USBHIDState),
VMSTATE_UINT32(n, USBHIDState),
VMSTATE_INT32(protocol, USBHIDState),
VMSTATE_UINT8(idle, USBHIDState),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_usb_kbd = {
.name = "usb-kbd",
.version_id = 1,
.minimum_version_id = 1,
.post_load = usb_hid_post_load,
.fields = (VMStateField []) {
VMSTATE_USB_DEVICE(dev, USBHIDState),
VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
VMSTATE_UINT32(head, USBHIDState),
VMSTATE_UINT32(n, USBHIDState),
VMSTATE_UINT16(kbd.modifiers, USBHIDState),
VMSTATE_UINT8(kbd.leds, USBHIDState),
VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
VMSTATE_INT32(kbd.keys, USBHIDState),
VMSTATE_INT32(protocol, USBHIDState),
VMSTATE_UINT8(idle, USBHIDState),
VMSTATE_END_OF_LIST()
}
};
static struct USBDeviceInfo hid_info[] = { static struct USBDeviceInfo hid_info[] = {
{ {
.product_desc = "QEMU USB Tablet", .product_desc = "QEMU USB Tablet",
.qdev.name = "usb-tablet", .qdev.name = "usb-tablet",
.usbdevice_name = "tablet", .usbdevice_name = "tablet",
.qdev.size = sizeof(USBHIDState), .qdev.size = sizeof(USBHIDState),
.qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_tablet, .usb_desc = &desc_tablet,
.init = usb_tablet_initfn, .init = usb_tablet_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,
@ -856,6 +973,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-mouse", .qdev.name = "usb-mouse",
.usbdevice_name = "mouse", .usbdevice_name = "mouse",
.qdev.size = sizeof(USBHIDState), .qdev.size = sizeof(USBHIDState),
.qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_mouse, .usb_desc = &desc_mouse,
.init = usb_mouse_initfn, .init = usb_mouse_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,
@ -868,6 +986,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-kbd", .qdev.name = "usb-kbd",
.usbdevice_name = "keyboard", .usbdevice_name = "keyboard",
.qdev.size = sizeof(USBHIDState), .qdev.size = sizeof(USBHIDState),
.qdev.vmsd = &vmstate_usb_kbd,
.usb_desc = &desc_keyboard, .usb_desc = &desc_keyboard,
.init = usb_keyboard_initfn, .init = usb_keyboard_initfn,
.handle_packet = usb_generic_handle_packet, .handle_packet = usb_generic_handle_packet,

View File

@ -544,11 +544,35 @@ static int usb_hub_initfn(USBDevice *dev)
return 0; return 0;
} }
static const VMStateDescription vmstate_usb_hub_port = {
.name = "usb-hub-port",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
VMSTATE_UINT16(wPortStatus, USBHubPort),
VMSTATE_UINT16(wPortChange, USBHubPort),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_usb_hub = {
.name = "usb-hub",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
VMSTATE_USB_DEVICE(dev, USBHubState),
VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
vmstate_usb_hub_port, USBHubPort),
VMSTATE_END_OF_LIST()
}
};
static struct USBDeviceInfo hub_info = { static struct USBDeviceInfo hub_info = {
.product_desc = "QEMU USB Hub", .product_desc = "QEMU USB Hub",
.qdev.name = "usb-hub", .qdev.name = "usb-hub",
.qdev.fw_name = "hub", .qdev.fw_name = "hub",
.qdev.size = sizeof(USBHubState), .qdev.size = sizeof(USBHubState),
.qdev.vmsd = &vmstate_usb_hub,
.usb_desc = &desc_hub, .usb_desc = &desc_hub,
.init = usb_hub_initfn, .init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet, .handle_packet = usb_hub_handle_packet,

View File

@ -165,13 +165,13 @@ struct USBDevice {
int auto_attach; int auto_attach;
int attached; int attached;
int state; int32_t state;
uint8_t setup_buf[8]; uint8_t setup_buf[8];
uint8_t data_buf[1024]; uint8_t data_buf[1024];
int remote_wakeup; int32_t remote_wakeup;
int setup_state; int32_t setup_state;
int setup_len; int32_t setup_len;
int setup_index; int32_t setup_index;
QLIST_HEAD(, USBDescString) strings; QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device; const USBDescDevice *device;

View File

@ -1504,7 +1504,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
break; break;
} }
if (vs->vd->lock_key_sync && if (down && vs->vd->lock_key_sync &&
keycode_is_keypad(vs->vd->kbd_layout, keycode)) { keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
/* If the numlock state needs to change then simulate an additional /* If the numlock state needs to change then simulate an additional
keypress before sending this one. This will happen if the user keypress before sending this one. This will happen if the user
@ -1523,7 +1523,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
} }
} }
if (vs->vd->lock_key_sync && if (down && vs->vd->lock_key_sync &&
((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) { ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
/* If the capslock state needs to change then simulate an additional /* If the capslock state needs to change then simulate an additional
keypress before sending this one. This will happen if the user keypress before sending this one. This will happen if the user