diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-04-13 20:35:23 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-04-13 20:35:23 +0100 |
commit | 33e570288985611345c7d6e073a4b258c97573a8 (patch) | |
tree | 2d1953ee05dc1211a5efa7167d06de61290da70b | |
parent | 8b4aaba736e55c8ab6d71350f850a6642f0165b9 (diff) | |
parent | b065e275a8066c3ec478f326f39c5fc3c9db103c (diff) | |
download | qemu-33e570288985611345c7d6e073a4b258c97573a8.tar.gz qemu-33e570288985611345c7d6e073a4b258c97573a8.tar.bz2 qemu-33e570288985611345c7d6e073a4b258c97573a8.zip |
Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-20160413-1' into staging
virtio-input; live migration support, various bugfixes.
# gpg: Signature made Wed 13 Apr 2016 16:41:27 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
* remotes/kraxel/tags/pull-input-20160413-1:
virtio-input: support absolute axis config in pass-through
input-linux: refine mouse detection
virtio-input: fix emulated tablet axis ranges
virtio-input: add live migration support
virtio-input: implement pass-through evdev writes
virtio-input: retrieve EV_LED host config bits
virtio-input: add missing key mappings
move const_le{16, 23} to qemu/bswap.h, add comment
virtio-input: add parenthesis to const_le{16, 32}
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/input/virtio-input-hid.c | 6 | ||||
-rw-r--r-- | hw/input/virtio-input-host.c | 70 | ||||
-rw-r--r-- | hw/input/virtio-input.c | 46 | ||||
-rw-r--r-- | include/hw/virtio/virtio-input.h | 17 | ||||
-rw-r--r-- | include/qemu/bswap.h | 19 | ||||
-rw-r--r-- | ui/input-linux.c | 30 |
6 files changed, 162 insertions, 26 deletions
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c index 5d12157114..3ee0c1814a 100644 --- a/hw/input/virtio-input-hid.c +++ b/hw/input/virtio-input-hid.c @@ -121,6 +121,8 @@ static const unsigned int keymap_qcode[Q_KEY_CODE__MAX] = { [Q_KEY_CODE_CTRL_R] = KEY_RIGHTCTRL, [Q_KEY_CODE_SYSRQ] = KEY_SYSRQ, + [Q_KEY_CODE_PRINT] = KEY_SYSRQ, + [Q_KEY_CODE_PAUSE] = KEY_PAUSE, [Q_KEY_CODE_ALT_R] = KEY_RIGHTALT, [Q_KEY_CODE_HOME] = KEY_HOME, @@ -482,12 +484,12 @@ static struct virtio_input_config virtio_tablet_config[] = { .select = VIRTIO_INPUT_CFG_ABS_INFO, .subsel = ABS_X, .size = sizeof(virtio_input_absinfo), - .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE), + .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1), },{ .select = VIRTIO_INPUT_CFG_ABS_INFO, .subsel = ABS_Y, .size = sizeof(virtio_input_absinfo), - .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE), + .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1), }, { /* end of list */ }, }; diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c index 9e0f46d88f..cb79e80024 100644 --- a/hw/input/virtio-input-host.c +++ b/hw/input/virtio-input-host.c @@ -70,13 +70,39 @@ static void virtio_input_bits_config(VirtIOInputHost *vih, virtio_input_add_config(VIRTIO_INPUT(vih), &bits); } +static void virtio_input_abs_config(VirtIOInputHost *vih, int axis) +{ + virtio_input_config config; + struct input_absinfo absinfo; + int rc; + + rc = ioctl(vih->fd, EVIOCGABS(axis), &absinfo); + if (rc < 0) { + return; + } + + memset(&config, 0, sizeof(config)); + config.select = VIRTIO_INPUT_CFG_ABS_INFO; + config.subsel = axis; + config.size = sizeof(virtio_input_absinfo); + + config.u.abs.min = cpu_to_le32(absinfo.minimum); + config.u.abs.max = cpu_to_le32(absinfo.maximum); + config.u.abs.fuzz = cpu_to_le32(absinfo.fuzz); + config.u.abs.flat = cpu_to_le32(absinfo.flat); + config.u.abs.res = cpu_to_le32(absinfo.resolution); + + virtio_input_add_config(VIRTIO_INPUT(vih), &config); +} + static void virtio_input_host_realize(DeviceState *dev, Error **errp) { VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev); VirtIOInput *vinput = VIRTIO_INPUT(dev); - virtio_input_config id; + virtio_input_config id, *abs; struct input_id ids; - int rc, ver; + int rc, ver, i, axis; + uint8_t byte; if (!vih->evdev) { error_setg(errp, "evdev property is required"); @@ -125,6 +151,23 @@ static void virtio_input_host_realize(DeviceState *dev, Error **errp) virtio_input_bits_config(vih, EV_ABS, ABS_CNT); virtio_input_bits_config(vih, EV_MSC, MSC_CNT); virtio_input_bits_config(vih, EV_SW, SW_CNT); + virtio_input_bits_config(vih, EV_LED, LED_CNT); + + abs = virtio_input_find_config(VIRTIO_INPUT(vih), + VIRTIO_INPUT_CFG_EV_BITS, EV_ABS); + if (abs) { + for (i = 0; i < abs->size; i++) { + byte = abs->u.bitmap[i]; + axis = 8 * i; + while (byte) { + if (byte & 1) { + virtio_input_abs_config(vih, axis); + } + axis++; + byte >>= 1; + } + } + } qemu_set_fd_handler(vih->fd, virtio_input_host_event, NULL, vih); return; @@ -145,6 +188,28 @@ static void virtio_input_host_unrealize(DeviceState *dev, Error **errp) } } +static void virtio_input_host_handle_status(VirtIOInput *vinput, + virtio_input_event *event) +{ + VirtIOInputHost *vih = VIRTIO_INPUT_HOST(vinput); + struct input_event evdev; + int rc; + + if (gettimeofday(&evdev.time, NULL)) { + perror("virtio_input_host_handle_status: gettimeofday"); + return; + } + + evdev.type = le16_to_cpu(event->type); + evdev.code = le16_to_cpu(event->code); + evdev.value = le32_to_cpu(event->value); + + rc = write(vih->fd, &evdev, sizeof(evdev)); + if (rc == -1) { + perror("virtio_input_host_handle_status: write"); + } +} + static const VMStateDescription vmstate_virtio_input_host = { .name = "virtio-input-host", .unmigratable = 1, @@ -164,6 +229,7 @@ static void virtio_input_host_class_init(ObjectClass *klass, void *data) dc->props = virtio_input_host_properties; vic->realize = virtio_input_host_realize; vic->unrealize = virtio_input_host_unrealize; + vic->handle_status = virtio_input_host_handle_status; } static void virtio_input_host_init(Object *obj) diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index 672c207eb5..f59749a943 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -14,6 +14,8 @@ #include "standard-headers/linux/input.h" +#define VIRTIO_INPUT_VM_VERSION 1 + /* ----------------------------------------------------------------- */ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) @@ -97,9 +99,9 @@ static void virtio_input_handle_sts(VirtIODevice *vdev, VirtQueue *vq) virtio_notify(vdev, vinput->sts); } -static virtio_input_config *virtio_input_find_config(VirtIOInput *vinput, - uint8_t select, - uint8_t subsel) +virtio_input_config *virtio_input_find_config(VirtIOInput *vinput, + uint8_t select, + uint8_t subsel) { VirtIOInputConfig *cfg; @@ -214,6 +216,38 @@ static void virtio_input_reset(VirtIODevice *vdev) } } +static void virtio_input_save(QEMUFile *f, void *opaque) +{ + VirtIOInput *vinput = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(vinput); + + virtio_save(vdev, f); +} + +static int virtio_input_load(QEMUFile *f, void *opaque, int version_id) +{ + VirtIOInput *vinput = opaque; + VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vinput); + VirtIODevice *vdev = VIRTIO_DEVICE(vinput); + int ret; + + if (version_id != VIRTIO_INPUT_VM_VERSION) { + return -EINVAL; + } + + ret = virtio_load(vdev, f, version_id); + if (ret) { + return ret; + } + + /* post_load() */ + vinput->active = vdev->status & VIRTIO_CONFIG_S_DRIVER_OK; + if (vic->change_active) { + vic->change_active(vinput); + } + return 0; +} + static void virtio_input_device_realize(DeviceState *dev, Error **errp) { VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); @@ -245,14 +279,20 @@ static void virtio_input_device_realize(DeviceState *dev, Error **errp) vinput->cfg_size); vinput->evt = virtio_add_queue(vdev, 64, virtio_input_handle_evt); vinput->sts = virtio_add_queue(vdev, 64, virtio_input_handle_sts); + + register_savevm(dev, "virtio-input", -1, VIRTIO_INPUT_VM_VERSION, + virtio_input_save, virtio_input_load, vinput); } static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) { VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOInput *vinput = VIRTIO_INPUT(dev); Error *local_err = NULL; + unregister_savevm(dev, "virtio-input", vinput); + if (vic->unrealize) { vic->unrealize(dev, &local_err); if (local_err) { diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h index af1c207ab1..bddbd4b287 100644 --- a/include/hw/virtio/virtio-input.h +++ b/include/hw/virtio/virtio-input.h @@ -13,20 +13,6 @@ typedef struct virtio_input_absinfo virtio_input_absinfo; typedef struct virtio_input_config virtio_input_config; typedef struct virtio_input_event virtio_input_event; -#if defined(HOST_WORDS_BIGENDIAN) -# define const_le32(_x) \ - (((_x & 0x000000ffU) << 24) | \ - ((_x & 0x0000ff00U) << 8) | \ - ((_x & 0x00ff0000U) >> 8) | \ - ((_x & 0xff000000U) >> 24)) -# define const_le16(_x) \ - (((_x & 0x00ff) << 8) | \ - ((_x & 0xff00) >> 8)) -#else -# define const_le32(_x) (_x) -# define const_le16(_x) (_x) -#endif - /* ----------------------------------------------------------------- */ /* qemu internals */ @@ -111,6 +97,9 @@ struct VirtIOInputHost { void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event); void virtio_input_init_config(VirtIOInput *vinput, virtio_input_config *config); +virtio_input_config *virtio_input_find_config(VirtIOInput *vinput, + uint8_t select, + uint8_t subsel); void virtio_input_add_config(VirtIOInput *vinput, virtio_input_config *config); void virtio_input_idstr_config(VirtIOInput *vinput, diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index fcedf0d249..ce3c42e4d9 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -125,6 +125,25 @@ static inline uint32_t qemu_bswap_len(uint32_t value, int len) return bswap32(value) >> (32 - 8 * len); } +/* + * Same as cpu_to_le{16,23}, except that gcc will figure the result is + * a compile-time constant if you pass in a constant. So this can be + * used to initialize static variables. + */ +#if defined(HOST_WORDS_BIGENDIAN) +# define const_le32(_x) \ + ((((_x) & 0x000000ffU) << 24) | \ + (((_x) & 0x0000ff00U) << 8) | \ + (((_x) & 0x00ff0000U) >> 8) | \ + (((_x) & 0xff000000U) >> 24)) +# define const_le16(_x) \ + ((((_x) & 0x00ff) << 8) | \ + (((_x) & 0xff00) >> 8)) +#else +# define const_le32(_x) (_x) +# define const_le16(_x) (_x) +#endif + /* Unions for reinterpreting between floats and integers. */ typedef union { diff --git a/ui/input-linux.c b/ui/input-linux.c index 9c921cc0ad..1d33b5c121 100644 --- a/ui/input-linux.c +++ b/ui/input-linux.c @@ -337,7 +337,7 @@ static void input_linux_event_mouse(void *opaque) static void input_linux_complete(UserCreatable *uc, Error **errp) { InputLinux *il = INPUT_LINUX(uc); - uint32_t evtmap; + uint32_t evtmap, relmap, absmap; int rc, ver; if (!il->evdev) { @@ -359,16 +359,36 @@ static void input_linux_complete(UserCreatable *uc, Error **errp) } rc = ioctl(il->fd, EVIOCGBIT(0, sizeof(evtmap)), &evtmap); + if (rc < 0) { + error_setg(errp, "%s: failed to read event bits", il->evdev); + goto err_close; + } if (evtmap & (1 << EV_REL)) { - /* has relative axis -> assume mouse */ + rc = ioctl(il->fd, EVIOCGBIT(EV_REL, sizeof(relmap)), &relmap); + if (rc < 0) { + relmap = 0; + } + } + + if (evtmap & (1 << EV_ABS)) { + ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap); + if (rc < 0) { + absmap = 0; + } + } + + if ((evtmap & (1 << EV_REL)) && + (relmap & (1 << REL_X))) { + /* has relative x axis -> assume mouse */ qemu_set_fd_handler(il->fd, input_linux_event_mouse, NULL, il); - } else if (evtmap & (1 << EV_ABS)) { - /* has absolute axis -> not supported */ + } else if ((evtmap & (1 << EV_ABS)) && + (absmap & (1 << ABS_X))) { + /* has absolute x axis -> not supported */ error_setg(errp, "tablet/touchscreen not supported"); goto err_close; } else if (evtmap & (1 << EV_KEY)) { - /* has keys/buttons (and no axis) -> assume keyboard */ + /* has keys/buttons (and no x axis) -> assume keyboard */ qemu_set_fd_handler(il->fd, input_linux_event_keyboard, NULL, il); } else { /* Huh? What is this? */ |