// SPDX-License-Identifier: GPL-2.0-only /* * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors. * * Copyright (C) 2014, VMware, Inc. All Rights Reserved. * * Twin device code is hugely inspired by the ALPS driver. * Authors: * Dmitry Torokhov <[email protected]> * Thomas Hellstrom <[email protected]> */ #include <linux/input.h> #include <linux/serio.h> #include <linux/libps2.h> #include <linux/slab.h> #include <linux/module.h> #include <asm/hypervisor.h> #include <asm/vmware.h> #include "psmouse.h" #include "vmmouse.h" /* * Main commands supported by the vmmouse hypervisor port. */ #define VMWARE_CMD_ABSPOINTER_DATA … #define VMWARE_CMD_ABSPOINTER_STATUS … #define VMWARE_CMD_ABSPOINTER_COMMAND … #define VMWARE_CMD_ABSPOINTER_RESTRICT … /* * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND */ #define VMMOUSE_CMD_ENABLE … #define VMMOUSE_CMD_DISABLE … #define VMMOUSE_CMD_REQUEST_RELATIVE … #define VMMOUSE_CMD_REQUEST_ABSOLUTE … #define VMMOUSE_ERROR … #define VMMOUSE_VERSION_ID … #define VMMOUSE_RELATIVE_PACKET … #define VMMOUSE_LEFT_BUTTON … #define VMMOUSE_RIGHT_BUTTON … #define VMMOUSE_MIDDLE_BUTTON … /* * VMMouse Restrict command */ #define VMMOUSE_RESTRICT_ANY … #define VMMOUSE_RESTRICT_CPL0 … #define VMMOUSE_RESTRICT_IOPL … #define VMMOUSE_MAX_X … #define VMMOUSE_MAX_Y … #define VMMOUSE_VENDOR … #define VMMOUSE_NAME … /** * 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 { … }; /** * 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) { … } /** * 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) { … } /** * 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) { … } /** * vmmouse_disable - Disable vmmouse * * @psmouse: Pointer to the psmouse struct * * Tries to disable vmmouse mode. */ static void vmmouse_disable(struct psmouse *psmouse) { … } /** * 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) { … } /* * Array of supported hypervisors. */ static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = …; /** * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor */ static bool vmmouse_check_hypervisor(void) { … } /** * 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) { … } /** * vmmouse_reset - Disable vmmouse and reset * * @psmouse: Pointer to the psmouse struct * * Tries to disable vmmouse mode before enter suspend. */ static void vmmouse_reset(struct psmouse *psmouse) { … } /** * 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) { … } /** * 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) { … } /** * 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) { … }