Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
0004  *
0005  * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
0006  *
0007  * Twin device code is hugely inspired by the ALPS driver.
0008  * Authors:
0009  *   Dmitry Torokhov <dmitry.torokhov@gmail.com>
0010  *   Thomas Hellstrom <thellstrom@vmware.com>
0011  */
0012 
0013 #include <linux/input.h>
0014 #include <linux/serio.h>
0015 #include <linux/libps2.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018 #include <asm/hypervisor.h>
0019 #include <asm/vmware.h>
0020 
0021 #include "psmouse.h"
0022 #include "vmmouse.h"
0023 
0024 #define VMMOUSE_PROTO_MAGIC         0x564D5868U
0025 
0026 /*
0027  * Main commands supported by the vmmouse hypervisor port.
0028  */
0029 #define VMMOUSE_PROTO_CMD_GETVERSION        10
0030 #define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA   39
0031 #define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40
0032 #define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND    41
0033 #define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT   86
0034 
0035 /*
0036  * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND
0037  */
0038 #define VMMOUSE_CMD_ENABLE          0x45414552U
0039 #define VMMOUSE_CMD_DISABLE         0x000000f5U
0040 #define VMMOUSE_CMD_REQUEST_RELATIVE        0x4c455252U
0041 #define VMMOUSE_CMD_REQUEST_ABSOLUTE        0x53424152U
0042 
0043 #define VMMOUSE_ERROR               0xffff0000U
0044 
0045 #define VMMOUSE_VERSION_ID          0x3442554aU
0046 
0047 #define VMMOUSE_RELATIVE_PACKET         0x00010000U
0048 
0049 #define VMMOUSE_LEFT_BUTTON         0x20
0050 #define VMMOUSE_RIGHT_BUTTON            0x10
0051 #define VMMOUSE_MIDDLE_BUTTON           0x08
0052 
0053 /*
0054  * VMMouse Restrict command
0055  */
0056 #define VMMOUSE_RESTRICT_ANY                    0x00
0057 #define VMMOUSE_RESTRICT_CPL0                   0x01
0058 #define VMMOUSE_RESTRICT_IOPL                   0x02
0059 
0060 #define VMMOUSE_MAX_X                           0xFFFF
0061 #define VMMOUSE_MAX_Y                           0xFFFF
0062 
0063 #define VMMOUSE_VENDOR "VMware"
0064 #define VMMOUSE_NAME   "VMMouse"
0065 
0066 /**
0067  * struct vmmouse_data - private data structure for the vmmouse driver
0068  *
0069  * @abs_dev: "Absolute" device used to report absolute mouse movement.
0070  * @phys: Physical path for the absolute device.
0071  * @dev_name: Name attribute name for the absolute device.
0072  */
0073 struct vmmouse_data {
0074     struct input_dev *abs_dev;
0075     char phys[32];
0076     char dev_name[128];
0077 };
0078 
0079 /*
0080  * Hypervisor-specific bi-directional communication channel
0081  * implementing the vmmouse protocol. Should never execute on
0082  * bare metal hardware.
0083  */
0084 #define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4)   \
0085 ({                          \
0086     unsigned long __dummy1, __dummy2;       \
0087     __asm__ __volatile__ (VMWARE_HYPERCALL :    \
0088         "=a"(out1),             \
0089         "=b"(out2),             \
0090         "=c"(out3),             \
0091         "=d"(out4),             \
0092         "=S"(__dummy1),             \
0093         "=D"(__dummy2) :            \
0094         "a"(VMMOUSE_PROTO_MAGIC),       \
0095         "b"(in1),               \
0096         "c"(VMMOUSE_PROTO_CMD_##cmd),       \
0097         "d"(0) :                    \
0098         "memory");                      \
0099 })
0100 
0101 /**
0102  * vmmouse_report_button - report button state on the correct input device
0103  *
0104  * @psmouse:  Pointer to the psmouse struct
0105  * @abs_dev:  The absolute input device
0106  * @rel_dev:  The relative input device
0107  * @pref_dev: The preferred device for reporting
0108  * @code:     Button code
0109  * @value:    Button value
0110  *
0111  * Report @value and @code on @pref_dev, unless the button is already
0112  * pressed on the other device, in which case the state is reported on that
0113  * device.
0114  */
0115 static void vmmouse_report_button(struct psmouse *psmouse,
0116                   struct input_dev *abs_dev,
0117                   struct input_dev *rel_dev,
0118                   struct input_dev *pref_dev,
0119                   unsigned int code, int value)
0120 {
0121     if (test_bit(code, abs_dev->key))
0122         pref_dev = abs_dev;
0123     else if (test_bit(code, rel_dev->key))
0124         pref_dev = rel_dev;
0125 
0126     input_report_key(pref_dev, code, value);
0127 }
0128 
0129 /**
0130  * vmmouse_report_events - process events on the vmmouse communications channel
0131  *
0132  * @psmouse: Pointer to the psmouse struct
0133  *
0134  * This function pulls events from the vmmouse communications channel and
0135  * reports them on the correct (absolute or relative) input device. When the
0136  * communications channel is drained, or if we've processed more than 255
0137  * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a
0138  * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in
0139  * the hope that the caller will reset the communications channel.
0140  */
0141 static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
0142 {
0143     struct input_dev *rel_dev = psmouse->dev;
0144     struct vmmouse_data *priv = psmouse->private;
0145     struct input_dev *abs_dev = priv->abs_dev;
0146     struct input_dev *pref_dev;
0147     u32 status, x, y, z;
0148     u32 dummy1, dummy2, dummy3;
0149     unsigned int queue_length;
0150     unsigned int count = 255;
0151 
0152     while (count--) {
0153         /* See if we have motion data. */
0154         VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
0155                 status, dummy1, dummy2, dummy3);
0156         if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
0157             psmouse_err(psmouse, "failed to fetch status data\n");
0158             /*
0159              * After a few attempts this will result in
0160              * reconnect.
0161              */
0162             return PSMOUSE_BAD_DATA;
0163         }
0164 
0165         queue_length = status & 0xffff;
0166         if (queue_length == 0)
0167             break;
0168 
0169         if (queue_length % 4) {
0170             psmouse_err(psmouse, "invalid queue length\n");
0171             return PSMOUSE_BAD_DATA;
0172         }
0173 
0174         /* Now get it */
0175         VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z);
0176 
0177         /*
0178          * And report what we've got. Prefer to report button
0179          * events on the same device where we report motion events.
0180          * This doesn't work well with the mouse wheel, though. See
0181          * below. Ideally we would want to report that on the
0182          * preferred device as well.
0183          */
0184         if (status & VMMOUSE_RELATIVE_PACKET) {
0185             pref_dev = rel_dev;
0186             input_report_rel(rel_dev, REL_X, (s32)x);
0187             input_report_rel(rel_dev, REL_Y, -(s32)y);
0188         } else {
0189             pref_dev = abs_dev;
0190             input_report_abs(abs_dev, ABS_X, x);
0191             input_report_abs(abs_dev, ABS_Y, y);
0192         }
0193 
0194         /* Xorg seems to ignore wheel events on absolute devices */
0195         input_report_rel(rel_dev, REL_WHEEL, -(s8)((u8) z));
0196 
0197         vmmouse_report_button(psmouse, abs_dev, rel_dev,
0198                       pref_dev, BTN_LEFT,
0199                       status & VMMOUSE_LEFT_BUTTON);
0200         vmmouse_report_button(psmouse, abs_dev, rel_dev,
0201                       pref_dev, BTN_RIGHT,
0202                       status & VMMOUSE_RIGHT_BUTTON);
0203         vmmouse_report_button(psmouse, abs_dev, rel_dev,
0204                       pref_dev, BTN_MIDDLE,
0205                       status & VMMOUSE_MIDDLE_BUTTON);
0206         input_sync(abs_dev);
0207         input_sync(rel_dev);
0208     }
0209 
0210     return PSMOUSE_FULL_PACKET;
0211 }
0212 
0213 /**
0214  * vmmouse_process_byte - process data on the ps/2 channel
0215  *
0216  * @psmouse: Pointer to the psmouse struct
0217  *
0218  * When the ps/2 channel indicates that there is vmmouse data available,
0219  * call vmmouse channel processing. Otherwise, continue to accept bytes. If
0220  * there is a synchronization or communication data error, return
0221  * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse.
0222  */
0223 static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse)
0224 {
0225     unsigned char *packet = psmouse->packet;
0226 
0227     switch (psmouse->pktcnt) {
0228     case 1:
0229         return (packet[0] & 0x8) == 0x8 ?
0230             PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
0231 
0232     case 2:
0233         return PSMOUSE_GOOD_DATA;
0234 
0235     default:
0236         return vmmouse_report_events(psmouse);
0237     }
0238 }
0239 
0240 /**
0241  * vmmouse_disable - Disable vmmouse
0242  *
0243  * @psmouse: Pointer to the psmouse struct
0244  *
0245  * Tries to disable vmmouse mode.
0246  */
0247 static void vmmouse_disable(struct psmouse *psmouse)
0248 {
0249     u32 status;
0250     u32 dummy1, dummy2, dummy3, dummy4;
0251 
0252     VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE,
0253             dummy1, dummy2, dummy3, dummy4);
0254 
0255     VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
0256             status, dummy1, dummy2, dummy3);
0257 
0258     if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
0259         psmouse_warn(psmouse, "failed to disable vmmouse device\n");
0260 }
0261 
0262 /**
0263  * vmmouse_enable - Enable vmmouse and request absolute mode.
0264  *
0265  * @psmouse: Pointer to the psmouse struct
0266  *
0267  * Tries to enable vmmouse mode. Performs basic checks and requests
0268  * absolute vmmouse mode.
0269  * Returns 0 on success, -ENODEV on failure.
0270  */
0271 static int vmmouse_enable(struct psmouse *psmouse)
0272 {
0273     u32 status, version;
0274     u32 dummy1, dummy2, dummy3, dummy4;
0275 
0276     /*
0277      * Try enabling the device. If successful, we should be able to
0278      * read valid version ID back from it.
0279      */
0280     VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE,
0281             dummy1, dummy2, dummy3, dummy4);
0282 
0283     /*
0284      * See if version ID can be retrieved.
0285      */
0286     VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3);
0287     if ((status & 0x0000ffff) == 0) {
0288         psmouse_dbg(psmouse, "empty flags - assuming no device\n");
0289         return -ENXIO;
0290     }
0291 
0292     VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */,
0293             version, dummy1, dummy2, dummy3);
0294     if (version != VMMOUSE_VERSION_ID) {
0295         psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
0296                 (unsigned) version, VMMOUSE_VERSION_ID);
0297         vmmouse_disable(psmouse);
0298         return -ENXIO;
0299     }
0300 
0301     /*
0302      * Restrict ioport access, if possible.
0303      */
0304     VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0,
0305             dummy1, dummy2, dummy3, dummy4);
0306 
0307     VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE,
0308             dummy1, dummy2, dummy3, dummy4);
0309 
0310     return 0;
0311 }
0312 
0313 /*
0314  * Array of supported hypervisors.
0315  */
0316 static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
0317     X86_HYPER_VMWARE,
0318     X86_HYPER_KVM,
0319 };
0320 
0321 /**
0322  * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor
0323  */
0324 static bool vmmouse_check_hypervisor(void)
0325 {
0326     int i;
0327 
0328     for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
0329         if (vmmouse_supported_hypervisors[i] == x86_hyper_type)
0330             return true;
0331 
0332     return false;
0333 }
0334 
0335 /**
0336  * vmmouse_detect - Probe whether vmmouse is available
0337  *
0338  * @psmouse: Pointer to the psmouse struct
0339  * @set_properties: Whether to set psmouse name and vendor
0340  *
0341  * Returns 0 if vmmouse channel is available. Negative error code if not.
0342  */
0343 int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
0344 {
0345     u32 response, version, dummy1, dummy2;
0346 
0347     if (!vmmouse_check_hypervisor()) {
0348         psmouse_dbg(psmouse,
0349                 "VMMouse not running on supported hypervisor.\n");
0350         return -ENXIO;
0351     }
0352 
0353     /* Check if the device is present */
0354     response = ~VMMOUSE_PROTO_MAGIC;
0355     VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2);
0356     if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU)
0357         return -ENXIO;
0358 
0359     if (set_properties) {
0360         psmouse->vendor = VMMOUSE_VENDOR;
0361         psmouse->name = VMMOUSE_NAME;
0362         psmouse->model = version;
0363     }
0364 
0365     return 0;
0366 }
0367 
0368 /**
0369  * vmmouse_reset - Disable vmmouse and reset
0370  *
0371  * @psmouse: Pointer to the psmouse struct
0372  *
0373  * Tries to disable vmmouse mode before enter suspend.
0374  */
0375 static void vmmouse_reset(struct psmouse *psmouse)
0376 {
0377     vmmouse_disable(psmouse);
0378     psmouse_reset(psmouse);
0379 }
0380 
0381 /**
0382  * vmmouse_disconnect - Take down vmmouse driver
0383  *
0384  * @psmouse: Pointer to the psmouse struct
0385  *
0386  * Takes down vmmouse driver and frees resources set up in vmmouse_init().
0387  */
0388 static void vmmouse_disconnect(struct psmouse *psmouse)
0389 {
0390     struct vmmouse_data *priv = psmouse->private;
0391 
0392     vmmouse_disable(psmouse);
0393     psmouse_reset(psmouse);
0394     input_unregister_device(priv->abs_dev);
0395     kfree(priv);
0396 }
0397 
0398 /**
0399  * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections
0400  *
0401  * @psmouse: Pointer to the psmouse struct
0402  *
0403  * Attempts to reset the mouse connections. Returns 0 on success and
0404  * -1 on failure.
0405  */
0406 static int vmmouse_reconnect(struct psmouse *psmouse)
0407 {
0408     int error;
0409 
0410     psmouse_reset(psmouse);
0411     vmmouse_disable(psmouse);
0412     error = vmmouse_enable(psmouse);
0413     if (error) {
0414         psmouse_err(psmouse,
0415                 "Unable to re-enable mouse when reconnecting, err: %d\n",
0416                 error);
0417         return error;
0418     }
0419 
0420     return 0;
0421 }
0422 
0423 /**
0424  * vmmouse_init - Initialize the vmmouse driver
0425  *
0426  * @psmouse: Pointer to the psmouse struct
0427  *
0428  * Requests the device and tries to enable vmmouse mode.
0429  * If successful, sets up the input device for relative movement events.
0430  * It also allocates another input device and sets it up for absolute motion
0431  * events. Returns 0 on success and -1 on failure.
0432  */
0433 int vmmouse_init(struct psmouse *psmouse)
0434 {
0435     struct vmmouse_data *priv;
0436     struct input_dev *rel_dev = psmouse->dev, *abs_dev;
0437     int error;
0438 
0439     psmouse_reset(psmouse);
0440     error = vmmouse_enable(psmouse);
0441     if (error)
0442         return error;
0443 
0444     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0445     abs_dev = input_allocate_device();
0446     if (!priv || !abs_dev) {
0447         error = -ENOMEM;
0448         goto init_fail;
0449     }
0450 
0451     priv->abs_dev = abs_dev;
0452     psmouse->private = priv;
0453 
0454     /* Set up and register absolute device */
0455     snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
0456          psmouse->ps2dev.serio->phys);
0457 
0458     /* Mimic name setup for relative device in psmouse-base.c */
0459     snprintf(priv->dev_name, sizeof(priv->dev_name), "%s %s %s",
0460          VMMOUSE_PSNAME, VMMOUSE_VENDOR, VMMOUSE_NAME);
0461     abs_dev->phys = priv->phys;
0462     abs_dev->name = priv->dev_name;
0463     abs_dev->id.bustype = BUS_I8042;
0464     abs_dev->id.vendor = 0x0002;
0465     abs_dev->id.product = PSMOUSE_VMMOUSE;
0466     abs_dev->id.version = psmouse->model;
0467     abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
0468 
0469     /* Set absolute device capabilities */
0470     input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
0471     input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
0472     input_set_capability(abs_dev, EV_KEY, BTN_MIDDLE);
0473     input_set_capability(abs_dev, EV_ABS, ABS_X);
0474     input_set_capability(abs_dev, EV_ABS, ABS_Y);
0475     input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
0476     input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
0477 
0478     error = input_register_device(priv->abs_dev);
0479     if (error)
0480         goto init_fail;
0481 
0482     /* Add wheel capability to the relative device */
0483     input_set_capability(rel_dev, EV_REL, REL_WHEEL);
0484 
0485     psmouse->protocol_handler = vmmouse_process_byte;
0486     psmouse->disconnect = vmmouse_disconnect;
0487     psmouse->reconnect = vmmouse_reconnect;
0488     psmouse->cleanup = vmmouse_reset;
0489 
0490     return 0;
0491 
0492 init_fail:
0493     vmmouse_disable(psmouse);
0494     psmouse_reset(psmouse);
0495     input_free_device(abs_dev);
0496     kfree(priv);
0497     psmouse->private = NULL;
0498 
0499     return error;
0500 }