mirror of https://gitee.com/openkylin/qemu.git
virtio-input; live migration support, various bugfixes.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJXDminAAoJEEy22O7T6HE4aawP/2iK9EmCdH20+rIBEbSjbC8t ReXI3TO5knGhFSmgaEsgq8AtiqalVV5nk14SVSAZfE5QRRKYohvj0xT1J2yTJ5hB 1Y0aD6sC+agzxDcOPm9ZZ/6q80bbTw8LxCr2sBTZ+Rvof8igdsVHawwow4eEbpzk U1ijjT76eqvGOzCAM9tryiMDniV0uN9vRHgEyxl1g1ctKBonj7B8VXIiwsBwY7L5 EKFpMv8mBTTuoyvMl485YBX/p8k4D/NFYhUvAwvuWspsV1bgyuqcsdBxPMtK2mqb Et2Zu484S0ere090G+X83NmkR+1X1OlgA+47BQB/ekC6lUTaCXHux4jvwgggLICT zp0jOV/xiXeNn/+Dm49/Od2qJZlEMNM3LbFAr9/T6Zmais2YGZHGSHA1BUC5hb1H rd/dWhxVd+7MEI/wVIhlXHnlCH12Na+WYr3gy+rrweQ0ItpZVNfo0POrBEKLYf1n MZSZ5AnxfQ19setY5TL1hjDuAkMUThXqvco8VcSoVfGdzXWcYYCMzfB7VGGUyBjV g6N7EuJihnnTTJ+lQisKveo7o5VXdg8IOoE7/zihWjiD5Ohf9tAEi3/6yncin2G2 0KSiv6ZJ/TJfrrnWNNNtHMAImIWWX8JyBl1yXz1h/fXvAXBMzHIy8raWr6WTSRMG GoXYoaCz9McVTvTalsk1 =p3bE -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
33e5702889
|
@ -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 */ },
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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? */
|
||||
|
|
Loading…
Reference in New Issue