diff options
Diffstat (limited to 'hw')
-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 |
3 files changed, 115 insertions, 7 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) { |