root/drivers/hid/hid-hyperv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mousevsc_alloc_device
  2. mousevsc_free_device
  3. mousevsc_on_receive_device_info
  4. mousevsc_on_receive
  5. mousevsc_on_channel_callback
  6. mousevsc_connect_to_vsp
  7. mousevsc_hid_parse
  8. mousevsc_hid_open
  9. mousevsc_hid_start
  10. mousevsc_hid_close
  11. mousevsc_hid_stop
  12. mousevsc_hid_raw_request
  13. mousevsc_probe
  14. mousevsc_remove
  15. mousevsc_init
  16. mousevsc_exit

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

/* [<][>][^][v][top][bottom][index][help] */