at v6.3-rc6 596 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2009, Citrix Systems, Inc. 4 * Copyright (c) 2010, Microsoft Corporation. 5 * Copyright (c) 2011, Novell Inc. 6 */ 7#include <linux/init.h> 8#include <linux/module.h> 9#include <linux/device.h> 10#include <linux/completion.h> 11#include <linux/input.h> 12#include <linux/hid.h> 13#include <linux/hiddev.h> 14#include <linux/hyperv.h> 15 16 17struct hv_input_dev_info { 18 unsigned int size; 19 unsigned short vendor; 20 unsigned short product; 21 unsigned short version; 22 unsigned short reserved[11]; 23}; 24 25/* 26 * Current version 27 * 28 * History: 29 * Beta, RC < 2008/1/22 1,0 30 * RC > 2008/1/22 2,0 31 */ 32#define SYNTHHID_INPUT_VERSION_MAJOR 2 33#define SYNTHHID_INPUT_VERSION_MINOR 0 34#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ 35 (SYNTHHID_INPUT_VERSION_MAJOR << 16)) 36 37 38#pragma pack(push, 1) 39/* 40 * Message types in the synthetic input protocol 41 */ 42enum synthhid_msg_type { 43 SYNTH_HID_PROTOCOL_REQUEST, 44 SYNTH_HID_PROTOCOL_RESPONSE, 45 SYNTH_HID_INITIAL_DEVICE_INFO, 46 SYNTH_HID_INITIAL_DEVICE_INFO_ACK, 47 SYNTH_HID_INPUT_REPORT, 48 SYNTH_HID_MAX 49}; 50 51/* 52 * Basic message structures. 53 */ 54struct synthhid_msg_hdr { 55 enum synthhid_msg_type type; 56 u32 size; 57}; 58 59union synthhid_version { 60 struct { 61 u16 minor_version; 62 u16 major_version; 63 }; 64 u32 version; 65}; 66 67/* 68 * Protocol messages 69 */ 70struct synthhid_protocol_request { 71 struct synthhid_msg_hdr header; 72 union synthhid_version version_requested; 73}; 74 75struct synthhid_protocol_response { 76 struct synthhid_msg_hdr header; 77 union synthhid_version version_requested; 78 unsigned char approved; 79}; 80 81struct synthhid_device_info { 82 struct synthhid_msg_hdr header; 83 struct hv_input_dev_info hid_dev_info; 84 struct hid_descriptor hid_descriptor; 85}; 86 87struct synthhid_device_info_ack { 88 struct synthhid_msg_hdr header; 89 unsigned char reserved; 90}; 91 92struct synthhid_input_report { 93 struct synthhid_msg_hdr header; 94 char buffer[]; 95}; 96 97#pragma pack(pop) 98 99#define INPUTVSC_SEND_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024) 100#define INPUTVSC_RECV_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024) 101 102 103enum pipe_prot_msg_type { 104 PIPE_MESSAGE_INVALID, 105 PIPE_MESSAGE_DATA, 106 PIPE_MESSAGE_MAXIMUM 107}; 108 109 110struct pipe_prt_msg { 111 enum pipe_prot_msg_type type; 112 u32 size; 113 char data[]; 114}; 115 116struct mousevsc_prt_msg { 117 enum pipe_prot_msg_type type; 118 u32 size; 119 union { 120 struct synthhid_protocol_request request; 121 struct synthhid_protocol_response response; 122 struct synthhid_device_info_ack ack; 123 }; 124}; 125 126/* 127 * Represents an mousevsc device 128 */ 129struct mousevsc_dev { 130 struct hv_device *device; 131 bool init_complete; 132 bool connected; 133 struct mousevsc_prt_msg protocol_req; 134 struct mousevsc_prt_msg protocol_resp; 135 /* Synchronize the request/response if needed */ 136 struct completion wait_event; 137 int dev_info_status; 138 139 struct hid_descriptor *hid_desc; 140 unsigned char *report_desc; 141 u32 report_desc_size; 142 struct hv_input_dev_info hid_dev_info; 143 struct hid_device *hid_device; 144 u8 input_buf[HID_MAX_BUFFER_SIZE]; 145}; 146 147 148static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device) 149{ 150 struct mousevsc_dev *input_dev; 151 152 input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); 153 154 if (!input_dev) 155 return NULL; 156 157 input_dev->device = device; 158 hv_set_drvdata(device, input_dev); 159 init_completion(&input_dev->wait_event); 160 input_dev->init_complete = false; 161 162 return input_dev; 163} 164 165static void mousevsc_free_device(struct mousevsc_dev *device) 166{ 167 kfree(device->hid_desc); 168 kfree(device->report_desc); 169 hv_set_drvdata(device->device, NULL); 170 kfree(device); 171} 172 173static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, 174 struct synthhid_device_info *device_info) 175{ 176 int ret = 0; 177 struct hid_descriptor *desc; 178 struct mousevsc_prt_msg ack; 179 180 input_device->dev_info_status = -ENOMEM; 181 182 input_device->hid_dev_info = device_info->hid_dev_info; 183 desc = &device_info->hid_descriptor; 184 if (desc->bLength == 0) 185 goto cleanup; 186 187 /* The pointer is not NULL when we resume from hibernation */ 188 kfree(input_device->hid_desc); 189 input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC); 190 191 if (!input_device->hid_desc) 192 goto cleanup; 193 194 input_device->report_desc_size = le16_to_cpu( 195 desc->desc[0].wDescriptorLength); 196 if (input_device->report_desc_size == 0) { 197 input_device->dev_info_status = -EINVAL; 198 goto cleanup; 199 } 200 201 /* The pointer is not NULL when we resume from hibernation */ 202 kfree(input_device->report_desc); 203 input_device->report_desc = kzalloc(input_device->report_desc_size, 204 GFP_ATOMIC); 205 206 if (!input_device->report_desc) { 207 input_device->dev_info_status = -ENOMEM; 208 goto cleanup; 209 } 210 211 memcpy(input_device->report_desc, 212 ((unsigned char *)desc) + desc->bLength, 213 le16_to_cpu(desc->desc[0].wDescriptorLength)); 214 215 /* Send the ack */ 216 memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); 217 218 ack.type = PIPE_MESSAGE_DATA; 219 ack.size = sizeof(struct synthhid_device_info_ack); 220 221 ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; 222 ack.ack.header.size = 1; 223 ack.ack.reserved = 0; 224 225 ret = vmbus_sendpacket(input_device->device->channel, 226 &ack, 227 sizeof(struct pipe_prt_msg) + 228 sizeof(struct synthhid_device_info_ack), 229 (unsigned long)&ack, 230 VM_PKT_DATA_INBAND, 231 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 232 233 if (!ret) 234 input_device->dev_info_status = 0; 235 236cleanup: 237 complete(&input_device->wait_event); 238 239 return; 240} 241 242static void mousevsc_on_receive(struct hv_device *device, 243 struct vmpacket_descriptor *packet) 244{ 245 struct pipe_prt_msg *pipe_msg; 246 struct synthhid_msg_hdr *hid_msg_hdr; 247 struct mousevsc_dev *input_dev = hv_get_drvdata(device); 248 struct synthhid_input_report *input_report; 249 size_t len; 250 251 pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + 252 (packet->offset8 << 3)); 253 254 if (pipe_msg->type != PIPE_MESSAGE_DATA) 255 return; 256 257 hid_msg_hdr = (struct synthhid_msg_hdr *)pipe_msg->data; 258 259 switch (hid_msg_hdr->type) { 260 case SYNTH_HID_PROTOCOL_RESPONSE: 261 /* 262 * While it will be impossible for us to protect against 263 * malicious/buggy hypervisor/host, add a check here to 264 * ensure we don't corrupt memory. 265 */ 266 if (struct_size(pipe_msg, data, pipe_msg->size) 267 > sizeof(struct mousevsc_prt_msg)) { 268 WARN_ON(1); 269 break; 270 } 271 272 memcpy(&input_dev->protocol_resp, pipe_msg, 273 struct_size(pipe_msg, data, pipe_msg->size)); 274 complete(&input_dev->wait_event); 275 break; 276 277 case SYNTH_HID_INITIAL_DEVICE_INFO: 278 WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); 279 280 /* 281 * Parse out the device info into device attr, 282 * hid desc and report desc 283 */ 284 mousevsc_on_receive_device_info(input_dev, 285 (struct synthhid_device_info *)pipe_msg->data); 286 break; 287 case SYNTH_HID_INPUT_REPORT: 288 input_report = 289 (struct synthhid_input_report *)pipe_msg->data; 290 if (!input_dev->init_complete) 291 break; 292 293 len = min(input_report->header.size, 294 (u32)sizeof(input_dev->input_buf)); 295 memcpy(input_dev->input_buf, input_report->buffer, len); 296 hid_input_report(input_dev->hid_device, HID_INPUT_REPORT, 297 input_dev->input_buf, len, 1); 298 299 pm_wakeup_hard_event(&input_dev->device->device); 300 301 break; 302 default: 303 pr_err("unsupported hid msg type - type %d len %d\n", 304 hid_msg_hdr->type, hid_msg_hdr->size); 305 break; 306 } 307 308} 309 310static void mousevsc_on_channel_callback(void *context) 311{ 312 struct hv_device *device = context; 313 struct vmpacket_descriptor *desc; 314 315 foreach_vmbus_pkt(desc, device->channel) { 316 switch (desc->type) { 317 case VM_PKT_COMP: 318 break; 319 320 case VM_PKT_DATA_INBAND: 321 mousevsc_on_receive(device, desc); 322 break; 323 324 default: 325 pr_err("Unhandled packet type %d, tid %llx len %d\n", 326 desc->type, desc->trans_id, desc->len8 * 8); 327 break; 328 } 329 } 330} 331 332static int mousevsc_connect_to_vsp(struct hv_device *device) 333{ 334 int ret = 0; 335 unsigned long t; 336 struct mousevsc_dev *input_dev = hv_get_drvdata(device); 337 struct mousevsc_prt_msg *request; 338 struct mousevsc_prt_msg *response; 339 340 reinit_completion(&input_dev->wait_event); 341 342 request = &input_dev->protocol_req; 343 memset(request, 0, sizeof(struct mousevsc_prt_msg)); 344 345 request->type = PIPE_MESSAGE_DATA; 346 request->size = sizeof(struct synthhid_protocol_request); 347 request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; 348 request->request.header.size = sizeof(unsigned int); 349 request->request.version_requested.version = SYNTHHID_INPUT_VERSION; 350 351 ret = vmbus_sendpacket(device->channel, request, 352 sizeof(struct pipe_prt_msg) + 353 sizeof(struct synthhid_protocol_request), 354 (unsigned long)request, 355 VM_PKT_DATA_INBAND, 356 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 357 if (ret) 358 goto cleanup; 359 360 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); 361 if (!t) { 362 ret = -ETIMEDOUT; 363 goto cleanup; 364 } 365 366 response = &input_dev->protocol_resp; 367 368 if (!response->response.approved) { 369 pr_err("synthhid protocol request failed (version %d)\n", 370 SYNTHHID_INPUT_VERSION); 371 ret = -ENODEV; 372 goto cleanup; 373 } 374 375 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); 376 if (!t) { 377 ret = -ETIMEDOUT; 378 goto cleanup; 379 } 380 381 /* 382 * We should have gotten the device attr, hid desc and report 383 * desc at this point 384 */ 385 ret = input_dev->dev_info_status; 386 387cleanup: 388 return ret; 389} 390 391static int mousevsc_hid_parse(struct hid_device *hid) 392{ 393 struct hv_device *dev = hid_get_drvdata(hid); 394 struct mousevsc_dev *input_dev = hv_get_drvdata(dev); 395 396 return hid_parse_report(hid, input_dev->report_desc, 397 input_dev->report_desc_size); 398} 399 400static int mousevsc_hid_open(struct hid_device *hid) 401{ 402 return 0; 403} 404 405static int mousevsc_hid_start(struct hid_device *hid) 406{ 407 return 0; 408} 409 410static void mousevsc_hid_close(struct hid_device *hid) 411{ 412} 413 414static void mousevsc_hid_stop(struct hid_device *hid) 415{ 416} 417 418static int mousevsc_hid_raw_request(struct hid_device *hid, 419 unsigned char report_num, 420 __u8 *buf, size_t len, 421 unsigned char rtype, 422 int reqtype) 423{ 424 return 0; 425} 426 427static const struct hid_ll_driver mousevsc_ll_driver = { 428 .parse = mousevsc_hid_parse, 429 .open = mousevsc_hid_open, 430 .close = mousevsc_hid_close, 431 .start = mousevsc_hid_start, 432 .stop = mousevsc_hid_stop, 433 .raw_request = mousevsc_hid_raw_request, 434}; 435 436static struct hid_driver mousevsc_hid_driver; 437 438static int mousevsc_probe(struct hv_device *device, 439 const struct hv_vmbus_device_id *dev_id) 440{ 441 int ret; 442 struct mousevsc_dev *input_dev; 443 struct hid_device *hid_dev; 444 445 input_dev = mousevsc_alloc_device(device); 446 447 if (!input_dev) 448 return -ENOMEM; 449 450 ret = vmbus_open(device->channel, 451 INPUTVSC_SEND_RING_BUFFER_SIZE, 452 INPUTVSC_RECV_RING_BUFFER_SIZE, 453 NULL, 454 0, 455 mousevsc_on_channel_callback, 456 device 457 ); 458 459 if (ret) 460 goto probe_err0; 461 462 ret = mousevsc_connect_to_vsp(device); 463 464 if (ret) 465 goto probe_err1; 466 467 /* workaround SA-167 */ 468 if (input_dev->report_desc[14] == 0x25) 469 input_dev->report_desc[14] = 0x29; 470 471 hid_dev = hid_allocate_device(); 472 if (IS_ERR(hid_dev)) { 473 ret = PTR_ERR(hid_dev); 474 goto probe_err1; 475 } 476 477 hid_dev->ll_driver = &mousevsc_ll_driver; 478 hid_dev->driver = &mousevsc_hid_driver; 479 hid_dev->bus = BUS_VIRTUAL; 480 hid_dev->vendor = input_dev->hid_dev_info.vendor; 481 hid_dev->product = input_dev->hid_dev_info.product; 482 hid_dev->version = input_dev->hid_dev_info.version; 483 input_dev->hid_device = hid_dev; 484 485 sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); 486 487 hid_set_drvdata(hid_dev, device); 488 489 ret = hid_add_device(hid_dev); 490 if (ret) 491 goto probe_err2; 492 493 494 ret = hid_parse(hid_dev); 495 if (ret) { 496 hid_err(hid_dev, "parse failed\n"); 497 goto probe_err2; 498 } 499 500 ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); 501 502 if (ret) { 503 hid_err(hid_dev, "hw start failed\n"); 504 goto probe_err2; 505 } 506 507 device_init_wakeup(&device->device, true); 508 509 input_dev->connected = true; 510 input_dev->init_complete = true; 511 512 return ret; 513 514probe_err2: 515 hid_destroy_device(hid_dev); 516 517probe_err1: 518 vmbus_close(device->channel); 519 520probe_err0: 521 mousevsc_free_device(input_dev); 522 523 return ret; 524} 525 526 527static void mousevsc_remove(struct hv_device *dev) 528{ 529 struct mousevsc_dev *input_dev = hv_get_drvdata(dev); 530 531 device_init_wakeup(&dev->device, false); 532 vmbus_close(dev->channel); 533 hid_hw_stop(input_dev->hid_device); 534 hid_destroy_device(input_dev->hid_device); 535 mousevsc_free_device(input_dev); 536} 537 538static int mousevsc_suspend(struct hv_device *dev) 539{ 540 vmbus_close(dev->channel); 541 542 return 0; 543} 544 545static int mousevsc_resume(struct hv_device *dev) 546{ 547 int ret; 548 549 ret = vmbus_open(dev->channel, 550 INPUTVSC_SEND_RING_BUFFER_SIZE, 551 INPUTVSC_RECV_RING_BUFFER_SIZE, 552 NULL, 0, 553 mousevsc_on_channel_callback, 554 dev); 555 if (ret) 556 return ret; 557 558 ret = mousevsc_connect_to_vsp(dev); 559 return ret; 560} 561 562static const struct hv_vmbus_device_id id_table[] = { 563 /* Mouse guid */ 564 { HV_MOUSE_GUID, }, 565 { }, 566}; 567 568MODULE_DEVICE_TABLE(vmbus, id_table); 569 570static struct hv_driver mousevsc_drv = { 571 .name = KBUILD_MODNAME, 572 .id_table = id_table, 573 .probe = mousevsc_probe, 574 .remove = mousevsc_remove, 575 .suspend = mousevsc_suspend, 576 .resume = mousevsc_resume, 577 .driver = { 578 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 579 }, 580}; 581 582static int __init mousevsc_init(void) 583{ 584 return vmbus_driver_register(&mousevsc_drv); 585} 586 587static void __exit mousevsc_exit(void) 588{ 589 vmbus_driver_unregister(&mousevsc_drv); 590} 591 592MODULE_LICENSE("GPL"); 593MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic HID Driver"); 594 595module_init(mousevsc_init); 596module_exit(mousevsc_exit);