0001
0002
0003
0004
0005
0006
0007 #include <linux/init.h>
0008 #include <linux/module.h>
0009 #include <linux/device.h>
0010 #include <linux/completion.h>
0011 #include <linux/input.h>
0012 #include <linux/hid.h>
0013 #include <linux/hiddev.h>
0014 #include <linux/hyperv.h>
0015
0016
0017 struct hv_input_dev_info {
0018 unsigned int size;
0019 unsigned short vendor;
0020 unsigned short product;
0021 unsigned short version;
0022 unsigned short reserved[11];
0023 };
0024
0025
0026 #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
0027
0028
0029
0030
0031
0032
0033
0034
0035 #define SYNTHHID_INPUT_VERSION_MAJOR 2
0036 #define SYNTHHID_INPUT_VERSION_MINOR 0
0037 #define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \
0038 (SYNTHHID_INPUT_VERSION_MAJOR << 16))
0039
0040
0041 #pragma pack(push, 1)
0042
0043
0044
0045 enum synthhid_msg_type {
0046 SYNTH_HID_PROTOCOL_REQUEST,
0047 SYNTH_HID_PROTOCOL_RESPONSE,
0048 SYNTH_HID_INITIAL_DEVICE_INFO,
0049 SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
0050 SYNTH_HID_INPUT_REPORT,
0051 SYNTH_HID_MAX
0052 };
0053
0054
0055
0056
0057 struct synthhid_msg_hdr {
0058 enum synthhid_msg_type type;
0059 u32 size;
0060 };
0061
0062 struct synthhid_msg {
0063 struct synthhid_msg_hdr header;
0064 char data[1];
0065 };
0066
0067 union synthhid_version {
0068 struct {
0069 u16 minor_version;
0070 u16 major_version;
0071 };
0072 u32 version;
0073 };
0074
0075
0076
0077
0078 struct synthhid_protocol_request {
0079 struct synthhid_msg_hdr header;
0080 union synthhid_version version_requested;
0081 };
0082
0083 struct synthhid_protocol_response {
0084 struct synthhid_msg_hdr header;
0085 union synthhid_version version_requested;
0086 unsigned char approved;
0087 };
0088
0089 struct synthhid_device_info {
0090 struct synthhid_msg_hdr header;
0091 struct hv_input_dev_info hid_dev_info;
0092 struct hid_descriptor hid_descriptor;
0093 };
0094
0095 struct synthhid_device_info_ack {
0096 struct synthhid_msg_hdr header;
0097 unsigned char reserved;
0098 };
0099
0100 struct synthhid_input_report {
0101 struct synthhid_msg_hdr header;
0102 char buffer[1];
0103 };
0104
0105 #pragma pack(pop)
0106
0107 #define INPUTVSC_SEND_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024)
0108 #define INPUTVSC_RECV_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024)
0109
0110
0111 enum pipe_prot_msg_type {
0112 PIPE_MESSAGE_INVALID,
0113 PIPE_MESSAGE_DATA,
0114 PIPE_MESSAGE_MAXIMUM
0115 };
0116
0117
0118 struct pipe_prt_msg {
0119 enum pipe_prot_msg_type type;
0120 u32 size;
0121 char data[1];
0122 };
0123
0124 struct mousevsc_prt_msg {
0125 enum pipe_prot_msg_type type;
0126 u32 size;
0127 union {
0128 struct synthhid_protocol_request request;
0129 struct synthhid_protocol_response response;
0130 struct synthhid_device_info_ack ack;
0131 };
0132 };
0133
0134
0135
0136
0137 struct mousevsc_dev {
0138 struct hv_device *device;
0139 bool init_complete;
0140 bool connected;
0141 struct mousevsc_prt_msg protocol_req;
0142 struct mousevsc_prt_msg protocol_resp;
0143
0144 struct completion wait_event;
0145 int dev_info_status;
0146
0147 struct hid_descriptor *hid_desc;
0148 unsigned char *report_desc;
0149 u32 report_desc_size;
0150 struct hv_input_dev_info hid_dev_info;
0151 struct hid_device *hid_device;
0152 u8 input_buf[HID_MAX_BUFFER_SIZE];
0153 };
0154
0155
0156 static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device)
0157 {
0158 struct mousevsc_dev *input_dev;
0159
0160 input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
0161
0162 if (!input_dev)
0163 return NULL;
0164
0165 input_dev->device = device;
0166 hv_set_drvdata(device, input_dev);
0167 init_completion(&input_dev->wait_event);
0168 input_dev->init_complete = false;
0169
0170 return input_dev;
0171 }
0172
0173 static void mousevsc_free_device(struct mousevsc_dev *device)
0174 {
0175 kfree(device->hid_desc);
0176 kfree(device->report_desc);
0177 hv_set_drvdata(device->device, NULL);
0178 kfree(device);
0179 }
0180
0181 static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
0182 struct synthhid_device_info *device_info)
0183 {
0184 int ret = 0;
0185 struct hid_descriptor *desc;
0186 struct mousevsc_prt_msg ack;
0187
0188 input_device->dev_info_status = -ENOMEM;
0189
0190 input_device->hid_dev_info = device_info->hid_dev_info;
0191 desc = &device_info->hid_descriptor;
0192 if (desc->bLength == 0)
0193 goto cleanup;
0194
0195
0196 kfree(input_device->hid_desc);
0197 input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
0198
0199 if (!input_device->hid_desc)
0200 goto cleanup;
0201
0202 input_device->report_desc_size = le16_to_cpu(
0203 desc->desc[0].wDescriptorLength);
0204 if (input_device->report_desc_size == 0) {
0205 input_device->dev_info_status = -EINVAL;
0206 goto cleanup;
0207 }
0208
0209
0210 kfree(input_device->report_desc);
0211 input_device->report_desc = kzalloc(input_device->report_desc_size,
0212 GFP_ATOMIC);
0213
0214 if (!input_device->report_desc) {
0215 input_device->dev_info_status = -ENOMEM;
0216 goto cleanup;
0217 }
0218
0219 memcpy(input_device->report_desc,
0220 ((unsigned char *)desc) + desc->bLength,
0221 le16_to_cpu(desc->desc[0].wDescriptorLength));
0222
0223
0224 memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
0225
0226 ack.type = PIPE_MESSAGE_DATA;
0227 ack.size = sizeof(struct synthhid_device_info_ack);
0228
0229 ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
0230 ack.ack.header.size = 1;
0231 ack.ack.reserved = 0;
0232
0233 ret = vmbus_sendpacket(input_device->device->channel,
0234 &ack,
0235 sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
0236 sizeof(struct synthhid_device_info_ack),
0237 (unsigned long)&ack,
0238 VM_PKT_DATA_INBAND,
0239 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
0240
0241 if (!ret)
0242 input_device->dev_info_status = 0;
0243
0244 cleanup:
0245 complete(&input_device->wait_event);
0246
0247 return;
0248 }
0249
0250 static void mousevsc_on_receive(struct hv_device *device,
0251 struct vmpacket_descriptor *packet)
0252 {
0253 struct pipe_prt_msg *pipe_msg;
0254 struct synthhid_msg *hid_msg;
0255 struct mousevsc_dev *input_dev = hv_get_drvdata(device);
0256 struct synthhid_input_report *input_report;
0257 size_t len;
0258
0259 pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
0260 (packet->offset8 << 3));
0261
0262 if (pipe_msg->type != PIPE_MESSAGE_DATA)
0263 return;
0264
0265 hid_msg = (struct synthhid_msg *)pipe_msg->data;
0266
0267 switch (hid_msg->header.type) {
0268 case SYNTH_HID_PROTOCOL_RESPONSE:
0269
0270
0271
0272
0273
0274 if ((pipe_msg->size + sizeof(struct pipe_prt_msg)
0275 - sizeof(unsigned char))
0276 > sizeof(struct mousevsc_prt_msg)) {
0277 WARN_ON(1);
0278 break;
0279 }
0280
0281 memcpy(&input_dev->protocol_resp, pipe_msg,
0282 pipe_msg->size + sizeof(struct pipe_prt_msg) -
0283 sizeof(unsigned char));
0284 complete(&input_dev->wait_event);
0285 break;
0286
0287 case SYNTH_HID_INITIAL_DEVICE_INFO:
0288 WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
0289
0290
0291
0292
0293
0294 mousevsc_on_receive_device_info(input_dev,
0295 (struct synthhid_device_info *)pipe_msg->data);
0296 break;
0297 case SYNTH_HID_INPUT_REPORT:
0298 input_report =
0299 (struct synthhid_input_report *)pipe_msg->data;
0300 if (!input_dev->init_complete)
0301 break;
0302
0303 len = min(input_report->header.size,
0304 (u32)sizeof(input_dev->input_buf));
0305 memcpy(input_dev->input_buf, input_report->buffer, len);
0306 hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
0307 input_dev->input_buf, len, 1);
0308
0309 pm_wakeup_hard_event(&input_dev->device->device);
0310
0311 break;
0312 default:
0313 pr_err("unsupported hid msg type - type %d len %d\n",
0314 hid_msg->header.type, hid_msg->header.size);
0315 break;
0316 }
0317
0318 }
0319
0320 static void mousevsc_on_channel_callback(void *context)
0321 {
0322 struct hv_device *device = context;
0323 struct vmpacket_descriptor *desc;
0324
0325 foreach_vmbus_pkt(desc, device->channel) {
0326 switch (desc->type) {
0327 case VM_PKT_COMP:
0328 break;
0329
0330 case VM_PKT_DATA_INBAND:
0331 mousevsc_on_receive(device, desc);
0332 break;
0333
0334 default:
0335 pr_err("Unhandled packet type %d, tid %llx len %d\n",
0336 desc->type, desc->trans_id, desc->len8 * 8);
0337 break;
0338 }
0339 }
0340 }
0341
0342 static int mousevsc_connect_to_vsp(struct hv_device *device)
0343 {
0344 int ret = 0;
0345 unsigned long t;
0346 struct mousevsc_dev *input_dev = hv_get_drvdata(device);
0347 struct mousevsc_prt_msg *request;
0348 struct mousevsc_prt_msg *response;
0349
0350 reinit_completion(&input_dev->wait_event);
0351
0352 request = &input_dev->protocol_req;
0353 memset(request, 0, sizeof(struct mousevsc_prt_msg));
0354
0355 request->type = PIPE_MESSAGE_DATA;
0356 request->size = sizeof(struct synthhid_protocol_request);
0357 request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
0358 request->request.header.size = sizeof(unsigned int);
0359 request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
0360
0361 ret = vmbus_sendpacket(device->channel, request,
0362 sizeof(struct pipe_prt_msg) -
0363 sizeof(unsigned char) +
0364 sizeof(struct synthhid_protocol_request),
0365 (unsigned long)request,
0366 VM_PKT_DATA_INBAND,
0367 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
0368 if (ret)
0369 goto cleanup;
0370
0371 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
0372 if (!t) {
0373 ret = -ETIMEDOUT;
0374 goto cleanup;
0375 }
0376
0377 response = &input_dev->protocol_resp;
0378
0379 if (!response->response.approved) {
0380 pr_err("synthhid protocol request failed (version %d)\n",
0381 SYNTHHID_INPUT_VERSION);
0382 ret = -ENODEV;
0383 goto cleanup;
0384 }
0385
0386 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
0387 if (!t) {
0388 ret = -ETIMEDOUT;
0389 goto cleanup;
0390 }
0391
0392
0393
0394
0395
0396 ret = input_dev->dev_info_status;
0397
0398 cleanup:
0399 return ret;
0400 }
0401
0402 static int mousevsc_hid_parse(struct hid_device *hid)
0403 {
0404 struct hv_device *dev = hid_get_drvdata(hid);
0405 struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
0406
0407 return hid_parse_report(hid, input_dev->report_desc,
0408 input_dev->report_desc_size);
0409 }
0410
0411 static int mousevsc_hid_open(struct hid_device *hid)
0412 {
0413 return 0;
0414 }
0415
0416 static int mousevsc_hid_start(struct hid_device *hid)
0417 {
0418 return 0;
0419 }
0420
0421 static void mousevsc_hid_close(struct hid_device *hid)
0422 {
0423 }
0424
0425 static void mousevsc_hid_stop(struct hid_device *hid)
0426 {
0427 }
0428
0429 static int mousevsc_hid_raw_request(struct hid_device *hid,
0430 unsigned char report_num,
0431 __u8 *buf, size_t len,
0432 unsigned char rtype,
0433 int reqtype)
0434 {
0435 return 0;
0436 }
0437
0438 static struct hid_ll_driver mousevsc_ll_driver = {
0439 .parse = mousevsc_hid_parse,
0440 .open = mousevsc_hid_open,
0441 .close = mousevsc_hid_close,
0442 .start = mousevsc_hid_start,
0443 .stop = mousevsc_hid_stop,
0444 .raw_request = mousevsc_hid_raw_request,
0445 };
0446
0447 static struct hid_driver mousevsc_hid_driver;
0448
0449 static int mousevsc_probe(struct hv_device *device,
0450 const struct hv_vmbus_device_id *dev_id)
0451 {
0452 int ret;
0453 struct mousevsc_dev *input_dev;
0454 struct hid_device *hid_dev;
0455
0456 input_dev = mousevsc_alloc_device(device);
0457
0458 if (!input_dev)
0459 return -ENOMEM;
0460
0461 ret = vmbus_open(device->channel,
0462 INPUTVSC_SEND_RING_BUFFER_SIZE,
0463 INPUTVSC_RECV_RING_BUFFER_SIZE,
0464 NULL,
0465 0,
0466 mousevsc_on_channel_callback,
0467 device
0468 );
0469
0470 if (ret)
0471 goto probe_err0;
0472
0473 ret = mousevsc_connect_to_vsp(device);
0474
0475 if (ret)
0476 goto probe_err1;
0477
0478
0479 if (input_dev->report_desc[14] == 0x25)
0480 input_dev->report_desc[14] = 0x29;
0481
0482 hid_dev = hid_allocate_device();
0483 if (IS_ERR(hid_dev)) {
0484 ret = PTR_ERR(hid_dev);
0485 goto probe_err1;
0486 }
0487
0488 hid_dev->ll_driver = &mousevsc_ll_driver;
0489 hid_dev->driver = &mousevsc_hid_driver;
0490 hid_dev->bus = BUS_VIRTUAL;
0491 hid_dev->vendor = input_dev->hid_dev_info.vendor;
0492 hid_dev->product = input_dev->hid_dev_info.product;
0493 hid_dev->version = input_dev->hid_dev_info.version;
0494 input_dev->hid_device = hid_dev;
0495
0496 sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
0497
0498 hid_set_drvdata(hid_dev, device);
0499
0500 ret = hid_add_device(hid_dev);
0501 if (ret)
0502 goto probe_err1;
0503
0504
0505 ret = hid_parse(hid_dev);
0506 if (ret) {
0507 hid_err(hid_dev, "parse failed\n");
0508 goto probe_err2;
0509 }
0510
0511 ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
0512
0513 if (ret) {
0514 hid_err(hid_dev, "hw start failed\n");
0515 goto probe_err2;
0516 }
0517
0518 device_init_wakeup(&device->device, true);
0519
0520 input_dev->connected = true;
0521 input_dev->init_complete = true;
0522
0523 return ret;
0524
0525 probe_err2:
0526 hid_destroy_device(hid_dev);
0527
0528 probe_err1:
0529 vmbus_close(device->channel);
0530
0531 probe_err0:
0532 mousevsc_free_device(input_dev);
0533
0534 return ret;
0535 }
0536
0537
0538 static int mousevsc_remove(struct hv_device *dev)
0539 {
0540 struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
0541
0542 device_init_wakeup(&dev->device, false);
0543 vmbus_close(dev->channel);
0544 hid_hw_stop(input_dev->hid_device);
0545 hid_destroy_device(input_dev->hid_device);
0546 mousevsc_free_device(input_dev);
0547
0548 return 0;
0549 }
0550
0551 static int mousevsc_suspend(struct hv_device *dev)
0552 {
0553 vmbus_close(dev->channel);
0554
0555 return 0;
0556 }
0557
0558 static int mousevsc_resume(struct hv_device *dev)
0559 {
0560 int ret;
0561
0562 ret = vmbus_open(dev->channel,
0563 INPUTVSC_SEND_RING_BUFFER_SIZE,
0564 INPUTVSC_RECV_RING_BUFFER_SIZE,
0565 NULL, 0,
0566 mousevsc_on_channel_callback,
0567 dev);
0568 if (ret)
0569 return ret;
0570
0571 ret = mousevsc_connect_to_vsp(dev);
0572 return ret;
0573 }
0574
0575 static const struct hv_vmbus_device_id id_table[] = {
0576
0577 { HV_MOUSE_GUID, },
0578 { },
0579 };
0580
0581 MODULE_DEVICE_TABLE(vmbus, id_table);
0582
0583 static struct hv_driver mousevsc_drv = {
0584 .name = KBUILD_MODNAME,
0585 .id_table = id_table,
0586 .probe = mousevsc_probe,
0587 .remove = mousevsc_remove,
0588 .suspend = mousevsc_suspend,
0589 .resume = mousevsc_resume,
0590 .driver = {
0591 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0592 },
0593 };
0594
0595 static int __init mousevsc_init(void)
0596 {
0597 return vmbus_driver_register(&mousevsc_drv);
0598 }
0599
0600 static void __exit mousevsc_exit(void)
0601 {
0602 vmbus_driver_unregister(&mousevsc_drv);
0603 }
0604
0605 MODULE_LICENSE("GPL");
0606 MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic HID Driver");
0607
0608 module_init(mousevsc_init);
0609 module_exit(mousevsc_exit);