Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (c) 2009, Citrix Systems, Inc.
0004  *  Copyright (c) 2010, Microsoft Corporation.
0005  *  Copyright (c) 2011, Novell Inc.
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 /* The maximum size of a synthetic input message. */
0026 #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
0027 
0028 /*
0029  * Current version
0030  *
0031  * History:
0032  * Beta, RC < 2008/1/22        1,0
0033  * RC > 2008/1/22              2,0
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  * Message types in the synthetic input protocol
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  * Basic message structures.
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]; /* Enclosed message */
0065 };
0066 
0067 union synthhid_version {
0068     struct {
0069         u16 minor_version;
0070         u16 major_version;
0071     };
0072     u32 version;
0073 };
0074 
0075 /*
0076  * Protocol messages
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  * Represents an mousevsc device
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     /* Synchronize the request/response if needed */
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     /* The pointer is not NULL when we resume from hibernation */
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     /* The pointer is not NULL when we resume from hibernation */
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     /* Send the ack */
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          * While it will be impossible for us to protect against
0271          * malicious/buggy hypervisor/host, add a check here to
0272          * ensure we don't corrupt memory.
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          * Parse out the device info into device attr,
0292          * hid desc and report desc
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      * We should have gotten the device attr, hid desc and report
0394      * desc at this point
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     /* workaround SA-167 */
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     /* Mouse guid */
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);