1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
5 * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
7 * Twin device code is hugely inspired by the ALPS driver.
9 * Dmitry Torokhov <dmitry.torokhov@gmail.com>
10 * Thomas Hellstrom <thellstrom@vmware.com>
13 #include <linux/input.h>
14 #include <linux/serio.h>
15 #include <linux/libps2.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
18 #include <asm/hypervisor.h>
19 #include <asm/vmware.h>
24 #define VMMOUSE_PROTO_MAGIC 0x564D5868U
27 * Main commands supported by the vmmouse hypervisor port.
29 #define VMMOUSE_PROTO_CMD_GETVERSION 10
30 #define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39
31 #define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40
32 #define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41
33 #define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86
36 * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND
38 #define VMMOUSE_CMD_ENABLE 0x45414552U
39 #define VMMOUSE_CMD_DISABLE 0x000000f5U
40 #define VMMOUSE_CMD_REQUEST_RELATIVE 0x4c455252U
41 #define VMMOUSE_CMD_REQUEST_ABSOLUTE 0x53424152U
43 #define VMMOUSE_ERROR 0xffff0000U
45 #define VMMOUSE_VERSION_ID 0x3442554aU
47 #define VMMOUSE_RELATIVE_PACKET 0x00010000U
49 #define VMMOUSE_LEFT_BUTTON 0x20
50 #define VMMOUSE_RIGHT_BUTTON 0x10
51 #define VMMOUSE_MIDDLE_BUTTON 0x08
54 * VMMouse Restrict command
56 #define VMMOUSE_RESTRICT_ANY 0x00
57 #define VMMOUSE_RESTRICT_CPL0 0x01
58 #define VMMOUSE_RESTRICT_IOPL 0x02
60 #define VMMOUSE_MAX_X 0xFFFF
61 #define VMMOUSE_MAX_Y 0xFFFF
63 #define VMMOUSE_VENDOR "VMware"
64 #define VMMOUSE_NAME "VMMouse"
67 * struct vmmouse_data - private data structure for the vmmouse driver
69 * @abs_dev: "Absolute" device used to report absolute mouse movement.
70 * @phys: Physical path for the absolute device.
71 * @dev_name: Name attribute name for the absolute device.
74 struct input_dev
*abs_dev
;
80 * Hypervisor-specific bi-directional communication channel
81 * implementing the vmmouse protocol. Should never execute on
82 * bare metal hardware.
84 #define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \
86 unsigned long __dummy1, __dummy2; \
87 __asm__ __volatile__ (VMWARE_HYPERCALL : \
94 "a"(VMMOUSE_PROTO_MAGIC), \
96 "c"(VMMOUSE_PROTO_CMD_##cmd), \
102 * vmmouse_report_button - report button state on the correct input device
104 * @psmouse: Pointer to the psmouse struct
105 * @abs_dev: The absolute input device
106 * @rel_dev: The relative input device
107 * @pref_dev: The preferred device for reporting
109 * @value: Button value
111 * Report @value and @code on @pref_dev, unless the button is already
112 * pressed on the other device, in which case the state is reported on that
115 static void vmmouse_report_button(struct psmouse
*psmouse
,
116 struct input_dev
*abs_dev
,
117 struct input_dev
*rel_dev
,
118 struct input_dev
*pref_dev
,
119 unsigned int code
, int value
)
121 if (test_bit(code
, abs_dev
->key
))
123 else if (test_bit(code
, rel_dev
->key
))
126 input_report_key(pref_dev
, code
, value
);
130 * vmmouse_report_events - process events on the vmmouse communications channel
132 * @psmouse: Pointer to the psmouse struct
134 * This function pulls events from the vmmouse communications channel and
135 * reports them on the correct (absolute or relative) input device. When the
136 * communications channel is drained, or if we've processed more than 255
137 * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a
138 * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in
139 * the hope that the caller will reset the communications channel.
141 static psmouse_ret_t
vmmouse_report_events(struct psmouse
*psmouse
)
143 struct input_dev
*rel_dev
= psmouse
->dev
;
144 struct vmmouse_data
*priv
= psmouse
->private;
145 struct input_dev
*abs_dev
= priv
->abs_dev
;
146 struct input_dev
*pref_dev
;
148 u32 dummy1
, dummy2
, dummy3
;
149 unsigned int queue_length
;
150 unsigned int count
= 255;
153 /* See if we have motion data. */
154 VMMOUSE_CMD(ABSPOINTER_STATUS
, 0,
155 status
, dummy1
, dummy2
, dummy3
);
156 if ((status
& VMMOUSE_ERROR
) == VMMOUSE_ERROR
) {
157 psmouse_err(psmouse
, "failed to fetch status data\n");
159 * After a few attempts this will result in
162 return PSMOUSE_BAD_DATA
;
165 queue_length
= status
& 0xffff;
166 if (queue_length
== 0)
169 if (queue_length
% 4) {
170 psmouse_err(psmouse
, "invalid queue length\n");
171 return PSMOUSE_BAD_DATA
;
175 VMMOUSE_CMD(ABSPOINTER_DATA
, 4, status
, x
, y
, z
);
178 * And report what we've got. Prefer to report button
179 * events on the same device where we report motion events.
180 * This doesn't work well with the mouse wheel, though. See
181 * below. Ideally we would want to report that on the
182 * preferred device as well.
184 if (status
& VMMOUSE_RELATIVE_PACKET
) {
186 input_report_rel(rel_dev
, REL_X
, (s32
)x
);
187 input_report_rel(rel_dev
, REL_Y
, -(s32
)y
);
190 input_report_abs(abs_dev
, ABS_X
, x
);
191 input_report_abs(abs_dev
, ABS_Y
, y
);
194 /* Xorg seems to ignore wheel events on absolute devices */
195 input_report_rel(rel_dev
, REL_WHEEL
, -(s8
)((u8
) z
));
197 vmmouse_report_button(psmouse
, abs_dev
, rel_dev
,
199 status
& VMMOUSE_LEFT_BUTTON
);
200 vmmouse_report_button(psmouse
, abs_dev
, rel_dev
,
202 status
& VMMOUSE_RIGHT_BUTTON
);
203 vmmouse_report_button(psmouse
, abs_dev
, rel_dev
,
204 pref_dev
, BTN_MIDDLE
,
205 status
& VMMOUSE_MIDDLE_BUTTON
);
210 return PSMOUSE_FULL_PACKET
;
214 * vmmouse_process_byte - process data on the ps/2 channel
216 * @psmouse: Pointer to the psmouse struct
218 * When the ps/2 channel indicates that there is vmmouse data available,
219 * call vmmouse channel processing. Otherwise, continue to accept bytes. If
220 * there is a synchronization or communication data error, return
221 * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse.
223 static psmouse_ret_t
vmmouse_process_byte(struct psmouse
*psmouse
)
225 unsigned char *packet
= psmouse
->packet
;
227 switch (psmouse
->pktcnt
) {
229 return (packet
[0] & 0x8) == 0x8 ?
230 PSMOUSE_GOOD_DATA
: PSMOUSE_BAD_DATA
;
233 return PSMOUSE_GOOD_DATA
;
236 return vmmouse_report_events(psmouse
);
241 * vmmouse_disable - Disable vmmouse
243 * @psmouse: Pointer to the psmouse struct
245 * Tries to disable vmmouse mode.
247 static void vmmouse_disable(struct psmouse
*psmouse
)
250 u32 dummy1
, dummy2
, dummy3
, dummy4
;
252 VMMOUSE_CMD(ABSPOINTER_COMMAND
, VMMOUSE_CMD_DISABLE
,
253 dummy1
, dummy2
, dummy3
, dummy4
);
255 VMMOUSE_CMD(ABSPOINTER_STATUS
, 0,
256 status
, dummy1
, dummy2
, dummy3
);
258 if ((status
& VMMOUSE_ERROR
) != VMMOUSE_ERROR
)
259 psmouse_warn(psmouse
, "failed to disable vmmouse device\n");
263 * vmmouse_enable - Enable vmmouse and request absolute mode.
265 * @psmouse: Pointer to the psmouse struct
267 * Tries to enable vmmouse mode. Performs basic checks and requests
268 * absolute vmmouse mode.
269 * Returns 0 on success, -ENODEV on failure.
271 static int vmmouse_enable(struct psmouse
*psmouse
)
274 u32 dummy1
, dummy2
, dummy3
, dummy4
;
277 * Try enabling the device. If successful, we should be able to
278 * read valid version ID back from it.
280 VMMOUSE_CMD(ABSPOINTER_COMMAND
, VMMOUSE_CMD_ENABLE
,
281 dummy1
, dummy2
, dummy3
, dummy4
);
284 * See if version ID can be retrieved.
286 VMMOUSE_CMD(ABSPOINTER_STATUS
, 0, status
, dummy1
, dummy2
, dummy3
);
287 if ((status
& 0x0000ffff) == 0) {
288 psmouse_dbg(psmouse
, "empty flags - assuming no device\n");
292 VMMOUSE_CMD(ABSPOINTER_DATA
, 1 /* single item */,
293 version
, dummy1
, dummy2
, dummy3
);
294 if (version
!= VMMOUSE_VERSION_ID
) {
295 psmouse_dbg(psmouse
, "Unexpected version value: %u vs %u\n",
296 (unsigned) version
, VMMOUSE_VERSION_ID
);
297 vmmouse_disable(psmouse
);
302 * Restrict ioport access, if possible.
304 VMMOUSE_CMD(ABSPOINTER_RESTRICT
, VMMOUSE_RESTRICT_CPL0
,
305 dummy1
, dummy2
, dummy3
, dummy4
);
307 VMMOUSE_CMD(ABSPOINTER_COMMAND
, VMMOUSE_CMD_REQUEST_ABSOLUTE
,
308 dummy1
, dummy2
, dummy3
, dummy4
);
314 * Array of supported hypervisors.
316 static enum x86_hypervisor_type vmmouse_supported_hypervisors
[] = {
322 * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor
324 static bool vmmouse_check_hypervisor(void)
328 for (i
= 0; i
< ARRAY_SIZE(vmmouse_supported_hypervisors
); i
++)
329 if (vmmouse_supported_hypervisors
[i
] == x86_hyper_type
)
336 * vmmouse_detect - Probe whether vmmouse is available
338 * @psmouse: Pointer to the psmouse struct
339 * @set_properties: Whether to set psmouse name and vendor
341 * Returns 0 if vmmouse channel is available. Negative error code if not.
343 int vmmouse_detect(struct psmouse
*psmouse
, bool set_properties
)
345 u32 response
, version
, dummy1
, dummy2
;
347 if (!vmmouse_check_hypervisor()) {
349 "VMMouse not running on supported hypervisor.\n");
353 /* Check if the device is present */
354 response
= ~VMMOUSE_PROTO_MAGIC
;
355 VMMOUSE_CMD(GETVERSION
, 0, version
, response
, dummy1
, dummy2
);
356 if (response
!= VMMOUSE_PROTO_MAGIC
|| version
== 0xffffffffU
)
359 if (set_properties
) {
360 psmouse
->vendor
= VMMOUSE_VENDOR
;
361 psmouse
->name
= VMMOUSE_NAME
;
362 psmouse
->model
= version
;
369 * vmmouse_disconnect - Take down vmmouse driver
371 * @psmouse: Pointer to the psmouse struct
373 * Takes down vmmouse driver and frees resources set up in vmmouse_init().
375 static void vmmouse_disconnect(struct psmouse
*psmouse
)
377 struct vmmouse_data
*priv
= psmouse
->private;
379 vmmouse_disable(psmouse
);
380 psmouse_reset(psmouse
);
381 input_unregister_device(priv
->abs_dev
);
386 * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections
388 * @psmouse: Pointer to the psmouse struct
390 * Attempts to reset the mouse connections. Returns 0 on success and
393 static int vmmouse_reconnect(struct psmouse
*psmouse
)
397 psmouse_reset(psmouse
);
398 vmmouse_disable(psmouse
);
399 error
= vmmouse_enable(psmouse
);
402 "Unable to re-enable mouse when reconnecting, err: %d\n",
411 * vmmouse_init - Initialize the vmmouse driver
413 * @psmouse: Pointer to the psmouse struct
415 * Requests the device and tries to enable vmmouse mode.
416 * If successful, sets up the input device for relative movement events.
417 * It also allocates another input device and sets it up for absolute motion
418 * events. Returns 0 on success and -1 on failure.
420 int vmmouse_init(struct psmouse
*psmouse
)
422 struct vmmouse_data
*priv
;
423 struct input_dev
*rel_dev
= psmouse
->dev
, *abs_dev
;
426 psmouse_reset(psmouse
);
427 error
= vmmouse_enable(psmouse
);
431 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
432 abs_dev
= input_allocate_device();
433 if (!priv
|| !abs_dev
) {
438 priv
->abs_dev
= abs_dev
;
439 psmouse
->private = priv
;
441 /* Set up and register absolute device */
442 snprintf(priv
->phys
, sizeof(priv
->phys
), "%s/input1",
443 psmouse
->ps2dev
.serio
->phys
);
445 /* Mimic name setup for relative device in psmouse-base.c */
446 snprintf(priv
->dev_name
, sizeof(priv
->dev_name
), "%s %s %s",
447 VMMOUSE_PSNAME
, VMMOUSE_VENDOR
, VMMOUSE_NAME
);
448 abs_dev
->phys
= priv
->phys
;
449 abs_dev
->name
= priv
->dev_name
;
450 abs_dev
->id
.bustype
= BUS_I8042
;
451 abs_dev
->id
.vendor
= 0x0002;
452 abs_dev
->id
.product
= PSMOUSE_VMMOUSE
;
453 abs_dev
->id
.version
= psmouse
->model
;
454 abs_dev
->dev
.parent
= &psmouse
->ps2dev
.serio
->dev
;
456 /* Set absolute device capabilities */
457 input_set_capability(abs_dev
, EV_KEY
, BTN_LEFT
);
458 input_set_capability(abs_dev
, EV_KEY
, BTN_RIGHT
);
459 input_set_capability(abs_dev
, EV_KEY
, BTN_MIDDLE
);
460 input_set_capability(abs_dev
, EV_ABS
, ABS_X
);
461 input_set_capability(abs_dev
, EV_ABS
, ABS_Y
);
462 input_set_abs_params(abs_dev
, ABS_X
, 0, VMMOUSE_MAX_X
, 0, 0);
463 input_set_abs_params(abs_dev
, ABS_Y
, 0, VMMOUSE_MAX_Y
, 0, 0);
465 error
= input_register_device(priv
->abs_dev
);
469 /* Add wheel capability to the relative device */
470 input_set_capability(rel_dev
, EV_REL
, REL_WHEEL
);
472 psmouse
->protocol_handler
= vmmouse_process_byte
;
473 psmouse
->disconnect
= vmmouse_disconnect
;
474 psmouse
->reconnect
= vmmouse_reconnect
;
479 vmmouse_disable(psmouse
);
480 psmouse_reset(psmouse
);
481 input_free_device(abs_dev
);
483 psmouse
->private = NULL
;