From a1fddda2eabbf856e567a34bd373570fdc663824 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 27 May 2015 09:58:03 -0400 Subject: [PATCH] Enable in-kernel vmmouse driver (rhbz 1214474) --- Input-add-vmmouse-driver.patch | 685 +++++++++++++++++++++++++++++++++ config-x86-generic | 1 + kernel.spec | 10 + 3 files changed, 696 insertions(+) create mode 100644 Input-add-vmmouse-driver.patch diff --git a/Input-add-vmmouse-driver.patch b/Input-add-vmmouse-driver.patch new file mode 100644 index 000000000..544fc5a6e --- /dev/null +++ b/Input-add-vmmouse-driver.patch @@ -0,0 +1,685 @@ +From: Thomas Hellstrom +Date: Tue, 14 Apr 2015 10:06:38 -0700 +Subject: [PATCH] Input: add vmmouse driver + +VMMouse enables low-latency mouse-cursor-movements for VMWare and QEMU +guests. By removing the guest cursor and using the host as a guest cursor +the cursor movement appears instant although in reality there is some lag. +To be able to do this, the host's view of the cursor position must exactly +match the guest's view and an absolute pointer device is needed. Enter the +VMMouse. While the VMMouse driver has historically been an Xorg user-space +driver, implementing it as a kernel imput driver enables rootless Xorg and +new compositing display servers for VMware guests. + +Signed-off-by: Thomas Hellstrom +Signed-off-by: Dmitry Torokhov +--- + MAINTAINERS | 8 + + drivers/input/mouse/Kconfig | 12 + + drivers/input/mouse/Makefile | 1 + + drivers/input/mouse/psmouse-base.c | 17 ++ + drivers/input/mouse/psmouse.h | 1 + + drivers/input/mouse/vmmouse.c | 508 +++++++++++++++++++++++++++++++++++++ + drivers/input/mouse/vmmouse.h | 30 +++ + 7 files changed, 577 insertions(+) + create mode 100644 drivers/input/mouse/vmmouse.c + create mode 100644 drivers/input/mouse/vmmouse.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index efbcb50e4969..a7905203974b 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -10523,6 +10523,14 @@ L: linux-kernel@vger.kernel.org + S: Maintained + F: drivers/misc/vmw_balloon.c + ++VMWARE VMMOUSE SUBDRIVER ++M: "VMware Graphics" ++M: "VMware, Inc." ++L: linux-input@vger.kernel.org ++S: Maintained ++F: drivers/input/mouse/vmmouse.c ++F: drivers/input/mouse/vmmouse.h ++ + VMWARE VMXNET3 ETHERNET DRIVER + M: Shreyas Bhatewara + M: "VMware, Inc." +diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig +index 4658b5d41dd7..7462d2fc8cfe 100644 +--- a/drivers/input/mouse/Kconfig ++++ b/drivers/input/mouse/Kconfig +@@ -149,6 +149,18 @@ config MOUSE_PS2_FOCALTECH + + If unsure, say Y. + ++config MOUSE_PS2_VMMOUSE ++ bool "Virtual mouse (vmmouse)" ++ depends on MOUSE_PS2 && X86 && HYPERVISOR_GUEST ++ help ++ Say Y here if you are running under control of VMware hypervisor ++ (ESXi, Workstation or Fusion). Also make sure that when you enable ++ this option, you remove the xf86-input-vmmouse user-space driver ++ or upgrade it to at least xf86-input-vmmouse 13.0.1, which doesn't ++ load in the presence of an in-kernel vmmouse driver. ++ ++ If unsure, say N. ++ + config MOUSE_SERIAL + tristate "Serial mouse" + select SERIO +diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile +index 8a9c98e76d9c..793300bfbddd 100644 +--- a/drivers/input/mouse/Makefile ++++ b/drivers/input/mouse/Makefile +@@ -36,6 +36,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o + psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o + psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o + psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o ++psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE) += vmmouse.o + + elan_i2c-objs := elan_i2c_core.o + elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o +diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c +index 8bc61237bc1b..a279744b3183 100644 +--- a/drivers/input/mouse/psmouse-base.c ++++ b/drivers/input/mouse/psmouse-base.c +@@ -36,6 +36,7 @@ + #include "sentelic.h" + #include "cypress_ps2.h" + #include "focaltech.h" ++#include "vmmouse.h" + + #define DRIVER_DESC "PS/2 mouse driver" + +@@ -764,6 +765,13 @@ static int psmouse_extensions(struct psmouse *psmouse, + } + } + ++ if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) { ++ if (max_proto > PSMOUSE_IMEX) { ++ if (!set_properties || vmmouse_init(psmouse) == 0) ++ return PSMOUSE_VMMOUSE; ++ } ++ } ++ + /* + * Try Kensington ThinkingMouse (we try first, because synaptics probe + * upsets the thinkingmouse). +@@ -1087,6 +1095,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { + .init = focaltech_init, + }, + #endif ++#ifdef CONFIG_MOUSE_PS2_VMMOUSE ++ { ++ .type = PSMOUSE_VMMOUSE, ++ .name = VMMOUSE_PSNAME, ++ .alias = "vmmouse", ++ .detect = vmmouse_detect, ++ .init = vmmouse_init, ++ }, ++#endif + { + .type = PSMOUSE_AUTO, + .name = "auto", +diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h +index d02e1bdc9ae4..ad5a5a1ea872 100644 +--- a/drivers/input/mouse/psmouse.h ++++ b/drivers/input/mouse/psmouse.h +@@ -103,6 +103,7 @@ enum psmouse_type { + PSMOUSE_SYNAPTICS_RELATIVE, + PSMOUSE_CYPRESS, + PSMOUSE_FOCALTECH, ++ PSMOUSE_VMMOUSE, + PSMOUSE_AUTO /* This one should always be last */ + }; + +diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c +new file mode 100644 +index 000000000000..e272f06258ce +--- /dev/null ++++ b/drivers/input/mouse/vmmouse.c +@@ -0,0 +1,508 @@ ++/* ++ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors. ++ * ++ * Copyright (C) 2014, VMware, Inc. All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * Twin device code is hugely inspired by the ALPS driver. ++ * Authors: ++ * Dmitry Torokhov ++ * Thomas Hellstrom ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "psmouse.h" ++#include "vmmouse.h" ++ ++#define VMMOUSE_PROTO_MAGIC 0x564D5868U ++#define VMMOUSE_PROTO_PORT 0x5658 ++ ++/* ++ * Main commands supported by the vmmouse hypervisor port. ++ */ ++#define VMMOUSE_PROTO_CMD_GETVERSION 10 ++#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 ++#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40 ++#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 ++#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 ++ ++/* ++ * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND ++ */ ++#define VMMOUSE_CMD_ENABLE 0x45414552U ++#define VMMOUSE_CMD_DISABLE 0x000000f5U ++#define VMMOUSE_CMD_REQUEST_RELATIVE 0x4c455252U ++#define VMMOUSE_CMD_REQUEST_ABSOLUTE 0x53424152U ++ ++#define VMMOUSE_ERROR 0xffff0000U ++ ++#define VMMOUSE_VERSION_ID 0x3442554aU ++ ++#define VMMOUSE_RELATIVE_PACKET 0x00010000U ++ ++#define VMMOUSE_LEFT_BUTTON 0x20 ++#define VMMOUSE_RIGHT_BUTTON 0x10 ++#define VMMOUSE_MIDDLE_BUTTON 0x08 ++ ++/* ++ * VMMouse Restrict command ++ */ ++#define VMMOUSE_RESTRICT_ANY 0x00 ++#define VMMOUSE_RESTRICT_CPL0 0x01 ++#define VMMOUSE_RESTRICT_IOPL 0x02 ++ ++#define VMMOUSE_MAX_X 0xFFFF ++#define VMMOUSE_MAX_Y 0xFFFF ++ ++#define VMMOUSE_VENDOR "VMware" ++#define VMMOUSE_NAME "VMMouse" ++ ++/** ++ * struct vmmouse_data - private data structure for the vmmouse driver ++ * ++ * @abs_dev: "Absolute" device used to report absolute mouse movement. ++ * @phys: Physical path for the absolute device. ++ * @dev_name: Name attribute name for the absolute device. ++ */ ++struct vmmouse_data { ++ struct input_dev *abs_dev; ++ char phys[32]; ++ char dev_name[128]; ++}; ++ ++/** ++ * Hypervisor-specific bi-directional communication channel ++ * implementing the vmmouse protocol. Should never execute on ++ * bare metal hardware. ++ */ ++#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ ++({ \ ++ unsigned long __dummy1, __dummy2; \ ++ __asm__ __volatile__ ("inl %%dx" : \ ++ "=a"(out1), \ ++ "=b"(out2), \ ++ "=c"(out3), \ ++ "=d"(out4), \ ++ "=S"(__dummy1), \ ++ "=D"(__dummy2) : \ ++ "a"(VMMOUSE_PROTO_MAGIC), \ ++ "b"(in1), \ ++ "c"(VMMOUSE_PROTO_CMD_##cmd), \ ++ "d"(VMMOUSE_PROTO_PORT) : \ ++ "memory"); \ ++}) ++ ++/** ++ * vmmouse_report_button - report button state on the correct input device ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * @abs_dev: The absolute input device ++ * @rel_dev: The relative input device ++ * @pref_dev: The preferred device for reporting ++ * @code: Button code ++ * @value: Button value ++ * ++ * Report @value and @code on @pref_dev, unless the button is already ++ * pressed on the other device, in which case the state is reported on that ++ * device. ++ */ ++static void vmmouse_report_button(struct psmouse *psmouse, ++ struct input_dev *abs_dev, ++ struct input_dev *rel_dev, ++ struct input_dev *pref_dev, ++ unsigned int code, int value) ++{ ++ if (test_bit(code, abs_dev->key)) ++ pref_dev = abs_dev; ++ else if (test_bit(code, rel_dev->key)) ++ pref_dev = rel_dev; ++ ++ input_report_key(pref_dev, code, value); ++} ++ ++/** ++ * vmmouse_report_events - process events on the vmmouse communications channel ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * This function pulls events from the vmmouse communications channel and ++ * reports them on the correct (absolute or relative) input device. When the ++ * communications channel is drained, or if we've processed more than 255 ++ * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a ++ * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in ++ * the hope that the caller will reset the communications channel. ++ */ ++static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) ++{ ++ struct input_dev *rel_dev = psmouse->dev; ++ struct vmmouse_data *priv = psmouse->private; ++ struct input_dev *abs_dev = priv->abs_dev; ++ struct input_dev *pref_dev; ++ u32 status, x, y, z; ++ u32 dummy1, dummy2, dummy3; ++ unsigned int queue_length; ++ unsigned int count = 255; ++ ++ while (count--) { ++ /* See if we have motion data. */ ++ VMMOUSE_CMD(ABSPOINTER_STATUS, 0, ++ status, dummy1, dummy2, dummy3); ++ if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { ++ psmouse_err(psmouse, "failed to fetch status data\n"); ++ /* ++ * After a few attempts this will result in ++ * reconnect. ++ */ ++ return PSMOUSE_BAD_DATA; ++ } ++ ++ queue_length = status & 0xffff; ++ if (queue_length == 0) ++ break; ++ ++ if (queue_length % 4) { ++ psmouse_err(psmouse, "invalid queue length\n"); ++ return PSMOUSE_BAD_DATA; ++ } ++ ++ /* Now get it */ ++ VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); ++ ++ /* ++ * And report what we've got. Prefer to report button ++ * events on the same device where we report motion events. ++ * This doesn't work well with the mouse wheel, though. See ++ * below. Ideally we would want to report that on the ++ * preferred device as well. ++ */ ++ if (status & VMMOUSE_RELATIVE_PACKET) { ++ pref_dev = rel_dev; ++ input_report_rel(rel_dev, REL_X, (s32)x); ++ input_report_rel(rel_dev, REL_Y, -(s32)y); ++ } else { ++ pref_dev = abs_dev; ++ input_report_abs(abs_dev, ABS_X, x); ++ input_report_abs(abs_dev, ABS_Y, y); ++ } ++ ++ /* Xorg seems to ignore wheel events on absolute devices */ ++ input_report_rel(rel_dev, REL_WHEEL, -(s8)((u8) z)); ++ ++ vmmouse_report_button(psmouse, abs_dev, rel_dev, ++ pref_dev, BTN_LEFT, ++ status & VMMOUSE_LEFT_BUTTON); ++ vmmouse_report_button(psmouse, abs_dev, rel_dev, ++ pref_dev, BTN_RIGHT, ++ status & VMMOUSE_RIGHT_BUTTON); ++ vmmouse_report_button(psmouse, abs_dev, rel_dev, ++ pref_dev, BTN_MIDDLE, ++ status & VMMOUSE_MIDDLE_BUTTON); ++ input_sync(abs_dev); ++ input_sync(rel_dev); ++ } ++ ++ return PSMOUSE_FULL_PACKET; ++} ++ ++/** ++ * vmmouse_process_byte - process data on the ps/2 channel ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * When the ps/2 channel indicates that there is vmmouse data available, ++ * call vmmouse channel processing. Otherwise, continue to accept bytes. If ++ * there is a synchronization or communication data error, return ++ * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse. ++ */ ++static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ switch (psmouse->pktcnt) { ++ case 1: ++ return (packet[0] & 0x8) == 0x8 ? ++ PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; ++ ++ case 2: ++ return PSMOUSE_GOOD_DATA; ++ ++ default: ++ return vmmouse_report_events(psmouse); ++ } ++} ++ ++/** ++ * vmmouse_disable - Disable vmmouse ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * Tries to disable vmmouse mode. ++ */ ++static void vmmouse_disable(struct psmouse *psmouse) ++{ ++ u32 status; ++ u32 dummy1, dummy2, dummy3, dummy4; ++ ++ VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, ++ dummy1, dummy2, dummy3, dummy4); ++ ++ VMMOUSE_CMD(ABSPOINTER_STATUS, 0, ++ status, dummy1, dummy2, dummy3); ++ ++ if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) ++ psmouse_warn(psmouse, "failed to disable vmmouse device\n"); ++} ++ ++/** ++ * vmmouse_enable - Enable vmmouse and request absolute mode. ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * Tries to enable vmmouse mode. Performs basic checks and requests ++ * absolute vmmouse mode. ++ * Returns 0 on success, -ENODEV on failure. ++ */ ++static int vmmouse_enable(struct psmouse *psmouse) ++{ ++ u32 status, version; ++ u32 dummy1, dummy2, dummy3, dummy4; ++ ++ /* ++ * Try enabling the device. If successful, we should be able to ++ * read valid version ID back from it. ++ */ ++ VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, ++ dummy1, dummy2, dummy3, dummy4); ++ ++ /* ++ * See if version ID can be retrieved. ++ */ ++ VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3); ++ if ((status & 0x0000ffff) == 0) { ++ psmouse_dbg(psmouse, "empty flags - assuming no device\n"); ++ return -ENXIO; ++ } ++ ++ VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */, ++ version, dummy1, dummy2, dummy3); ++ if (version != VMMOUSE_VERSION_ID) { ++ psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n", ++ (unsigned) version, VMMOUSE_VERSION_ID); ++ vmmouse_disable(psmouse); ++ return -ENXIO; ++ } ++ ++ /* ++ * Restrict ioport access, if possible. ++ */ ++ VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0, ++ dummy1, dummy2, dummy3, dummy4); ++ ++ VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE, ++ dummy1, dummy2, dummy3, dummy4); ++ ++ return 0; ++} ++ ++/* ++ * Array of supported hypervisors. ++ */ ++static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = { ++ &x86_hyper_vmware, ++#ifdef CONFIG_KVM_GUEST ++ &x86_hyper_kvm, ++#endif ++}; ++ ++/** ++ * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor ++ */ ++static bool vmmouse_check_hypervisor(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++) ++ if (vmmouse_supported_hypervisors[i] == x86_hyper) ++ return true; ++ ++ return false; ++} ++ ++/** ++ * vmmouse_detect - Probe whether vmmouse is available ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * @set_properties: Whether to set psmouse name and vendor ++ * ++ * Returns 0 if vmmouse channel is available. Negative error code if not. ++ */ ++int vmmouse_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ u32 response, version, dummy1, dummy2; ++ ++ if (!vmmouse_check_hypervisor()) { ++ psmouse_dbg(psmouse, ++ "VMMouse not running on supported hypervisor.\n"); ++ return -ENXIO; ++ } ++ ++ if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) { ++ psmouse_dbg(psmouse, "VMMouse port in use.\n"); ++ return -EBUSY; ++ } ++ ++ /* Check if the device is present */ ++ response = ~VMMOUSE_PROTO_MAGIC; ++ VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2); ++ if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) { ++ release_region(VMMOUSE_PROTO_PORT, 4); ++ return -ENXIO; ++ } ++ ++ if (set_properties) { ++ psmouse->vendor = VMMOUSE_VENDOR; ++ psmouse->name = VMMOUSE_NAME; ++ psmouse->model = version; ++ } ++ ++ release_region(VMMOUSE_PROTO_PORT, 4); ++ ++ return 0; ++} ++ ++/** ++ * vmmouse_disconnect - Take down vmmouse driver ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * Takes down vmmouse driver and frees resources set up in vmmouse_init(). ++ */ ++static void vmmouse_disconnect(struct psmouse *psmouse) ++{ ++ struct vmmouse_data *priv = psmouse->private; ++ ++ vmmouse_disable(psmouse); ++ psmouse_reset(psmouse); ++ input_unregister_device(priv->abs_dev); ++ kfree(priv); ++ release_region(VMMOUSE_PROTO_PORT, 4); ++} ++ ++/** ++ * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * Attempts to reset the mouse connections. Returns 0 on success and ++ * -1 on failure. ++ */ ++static int vmmouse_reconnect(struct psmouse *psmouse) ++{ ++ int error; ++ ++ psmouse_reset(psmouse); ++ vmmouse_disable(psmouse); ++ error = vmmouse_enable(psmouse); ++ if (error) { ++ psmouse_err(psmouse, ++ "Unable to re-enable mouse when reconnecting, err: %d\n", ++ error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++/** ++ * vmmouse_init - Initialize the vmmouse driver ++ * ++ * @psmouse: Pointer to the psmouse struct ++ * ++ * Requests the device and tries to enable vmmouse mode. ++ * If successful, sets up the input device for relative movement events. ++ * It also allocates another input device and sets it up for absolute motion ++ * events. Returns 0 on success and -1 on failure. ++ */ ++int vmmouse_init(struct psmouse *psmouse) ++{ ++ struct vmmouse_data *priv; ++ struct input_dev *rel_dev = psmouse->dev, *abs_dev; ++ int error; ++ ++ if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) { ++ psmouse_dbg(psmouse, "VMMouse port in use.\n"); ++ return -EBUSY; ++ } ++ ++ psmouse_reset(psmouse); ++ error = vmmouse_enable(psmouse); ++ if (error) ++ goto release_region; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ abs_dev = input_allocate_device(); ++ if (!priv || !abs_dev) { ++ error = -ENOMEM; ++ goto init_fail; ++ } ++ ++ priv->abs_dev = abs_dev; ++ psmouse->private = priv; ++ ++ input_set_capability(rel_dev, EV_REL, REL_WHEEL); ++ ++ /* Set up and register absolute device */ ++ snprintf(priv->phys, sizeof(priv->phys), "%s/input1", ++ psmouse->ps2dev.serio->phys); ++ ++ /* Mimic name setup for relative device in psmouse-base.c */ ++ snprintf(priv->dev_name, sizeof(priv->dev_name), "%s %s %s", ++ VMMOUSE_PSNAME, VMMOUSE_VENDOR, VMMOUSE_NAME); ++ abs_dev->phys = priv->phys; ++ abs_dev->name = priv->dev_name; ++ abs_dev->id.bustype = BUS_I8042; ++ abs_dev->id.vendor = 0x0002; ++ abs_dev->id.product = PSMOUSE_VMMOUSE; ++ abs_dev->id.version = psmouse->model; ++ abs_dev->dev.parent = &psmouse->ps2dev.serio->dev; ++ ++ error = input_register_device(priv->abs_dev); ++ if (error) ++ goto init_fail; ++ ++ /* Set absolute device capabilities */ ++ input_set_capability(abs_dev, EV_KEY, BTN_LEFT); ++ input_set_capability(abs_dev, EV_KEY, BTN_RIGHT); ++ input_set_capability(abs_dev, EV_KEY, BTN_MIDDLE); ++ input_set_capability(abs_dev, EV_ABS, ABS_X); ++ input_set_capability(abs_dev, EV_ABS, ABS_Y); ++ input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0); ++ input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0); ++ ++ psmouse->protocol_handler = vmmouse_process_byte; ++ psmouse->disconnect = vmmouse_disconnect; ++ psmouse->reconnect = vmmouse_reconnect; ++ ++ return 0; ++ ++init_fail: ++ vmmouse_disable(psmouse); ++ psmouse_reset(psmouse); ++ input_free_device(abs_dev); ++ kfree(priv); ++ psmouse->private = NULL; ++ ++release_region: ++ release_region(VMMOUSE_PROTO_PORT, 4); ++ ++ return error; ++} +diff --git a/drivers/input/mouse/vmmouse.h b/drivers/input/mouse/vmmouse.h +new file mode 100644 +index 000000000000..6f126017a24c +--- /dev/null ++++ b/drivers/input/mouse/vmmouse.h +@@ -0,0 +1,30 @@ ++/* ++ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors. ++ * ++ * Copyright (C) 2014, VMware, Inc. All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#ifndef _VMMOUSE_H ++#define _VMMOUSE_H ++ ++#ifdef CONFIG_MOUSE_PS2_VMMOUSE ++#define VMMOUSE_PSNAME "VirtualPS/2" ++ ++int vmmouse_detect(struct psmouse *psmouse, bool set_properties); ++int vmmouse_init(struct psmouse *psmouse); ++#else ++static inline int vmmouse_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ return -ENOSYS; ++} ++static inline int vmmouse_init(struct psmouse *psmouse) ++{ ++ return -ENOSYS; ++} ++#endif ++ ++#endif diff --git a/config-x86-generic b/config-x86-generic index 4889e216c..5a9562a73 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -525,6 +525,7 @@ CONFIG_INTEL_RAPL=m CONFIG_VMWARE_VMCI=m CONFIG_VMWARE_VMCI_VSOCKETS=m +CONFIG_MOUSE_PS2_VMMOUSE=y CONFIG_XZ_DEC_X86=y diff --git a/kernel.spec b/kernel.spec index 8ab4f6a43..f847b9c29 100644 --- a/kernel.spec +++ b/kernel.spec @@ -672,6 +672,9 @@ Patch26208: sched-always-use-blk_schedule_flush_plug-in-io_sched.patch #rhbz 1200353 Patch26209: 0001-ktime-Fix-ktime_divns-to-do-signed-division.patch +#rhbz 1214474 +Patch26210: Input-add-vmmouse-driver.patch + # END OF PATCH DEFINITIONS %endif @@ -696,6 +699,7 @@ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ Requires(pre): linux-firmware >= 20130724-29.git31f6b30\ Requires(preun): systemd >= 200\ +Conflicts: xorg-x11-drv-vmmouse < 13.0.99\ %{expand:%%{?kernel%{?1:_%{1}}_conflicts:Conflicts: %%{kernel%{?1:_%{1}}_conflicts}}}\ %{expand:%%{?kernel%{?1:_%{1}}_obsoletes:Obsoletes: %%{kernel%{?1:_%{1}}_obsoletes}}}\ %{expand:%%{?kernel%{?1:_%{1}}_provides:Provides: %%{kernel%{?1:_%{1}}_provides}}}\ @@ -1458,6 +1462,9 @@ ApplyPatch sched-always-use-blk_schedule_flush_plug-in-io_sched.patch #rhbz 1200353 ApplyPatch 0001-ktime-Fix-ktime_divns-to-do-signed-division.patch +#rhbz 1214474 +ApplyPatch Input-add-vmmouse-driver.patch + # END OF PATCH APPLICATIONS %endif @@ -2308,6 +2315,9 @@ fi # # %changelog +* Wed May 27 2015 Josh Boyer +- Enable in-kernel vmmouse driver (rhbz 1214474) + * Tue May 26 2015 Laura Abbott - Fix signed division error (rhbz 1200353)