0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
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
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
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
0068
0069
0070
0071
0072
0073 struct vmmouse_data {
0074 struct input_dev *abs_dev;
0075 char phys[32];
0076 char dev_name[128];
0077 };
0078
0079
0080
0081
0082
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
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
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
0131
0132
0133
0134
0135
0136
0137
0138
0139
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
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
0160
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
0175 VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z);
0176
0177
0178
0179
0180
0181
0182
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
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
0215
0216
0217
0218
0219
0220
0221
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
0242
0243
0244
0245
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
0264
0265
0266
0267
0268
0269
0270
0271 static int vmmouse_enable(struct psmouse *psmouse)
0272 {
0273 u32 status, version;
0274 u32 dummy1, dummy2, dummy3, dummy4;
0275
0276
0277
0278
0279
0280 VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE,
0281 dummy1, dummy2, dummy3, dummy4);
0282
0283
0284
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 ,
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
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
0315
0316 static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
0317 X86_HYPER_VMWARE,
0318 X86_HYPER_KVM,
0319 };
0320
0321
0322
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
0337
0338
0339
0340
0341
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
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
0370
0371
0372
0373
0374
0375 static void vmmouse_reset(struct psmouse *psmouse)
0376 {
0377 vmmouse_disable(psmouse);
0378 psmouse_reset(psmouse);
0379 }
0380
0381
0382
0383
0384
0385
0386
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
0400
0401
0402
0403
0404
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
0425
0426
0427
0428
0429
0430
0431
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
0455 snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
0456 psmouse->ps2dev.serio->phys);
0457
0458
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
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
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 }