linux/drivers/hid/hid-hyperv.c
<<
>>
Prefs
   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/* 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 */
  45enum 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 */
  57struct synthhid_msg_hdr {
  58        enum synthhid_msg_type type;
  59        u32 size;
  60};
  61
  62struct synthhid_msg {
  63        struct synthhid_msg_hdr header;
  64        char data[1]; /* Enclosed message */
  65};
  66
  67union synthhid_version {
  68        struct {
  69                u16 minor_version;
  70                u16 major_version;
  71        };
  72        u32 version;
  73};
  74
  75/*
  76 * Protocol messages
  77 */
  78struct synthhid_protocol_request {
  79        struct synthhid_msg_hdr header;
  80        union synthhid_version version_requested;
  81};
  82
  83struct synthhid_protocol_response {
  84        struct synthhid_msg_hdr header;
  85        union synthhid_version version_requested;
  86        unsigned char approved;
  87};
  88
  89struct 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
  95struct synthhid_device_info_ack {
  96        struct synthhid_msg_hdr header;
  97        unsigned char reserved;
  98};
  99
 100struct 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  VMBUS_RING_SIZE(36 * 1024)
 108#define INPUTVSC_RECV_RING_BUFFER_SIZE  VMBUS_RING_SIZE(36 * 1024)
 109
 110
 111enum pipe_prot_msg_type {
 112        PIPE_MESSAGE_INVALID,
 113        PIPE_MESSAGE_DATA,
 114        PIPE_MESSAGE_MAXIMUM
 115};
 116
 117
 118struct pipe_prt_msg {
 119        enum pipe_prot_msg_type type;
 120        u32 size;
 121        char data[1];
 122};
 123
 124struct  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 */
 137struct 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
 156static 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
 173static 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
 181static 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        /* The pointer is not NULL when we resume from hibernation */
 196        kfree(input_device->hid_desc);
 197        input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
 198
 199        if (!input_device->hid_desc)
 200                goto cleanup;
 201
 202        input_device->report_desc_size = desc->desc[0].wDescriptorLength;
 203        if (input_device->report_desc_size == 0) {
 204                input_device->dev_info_status = -EINVAL;
 205                goto cleanup;
 206        }
 207
 208        /* The pointer is not NULL when we resume from hibernation */
 209        kfree(input_device->report_desc);
 210        input_device->report_desc = kzalloc(input_device->report_desc_size,
 211                                          GFP_ATOMIC);
 212
 213        if (!input_device->report_desc) {
 214                input_device->dev_info_status = -ENOMEM;
 215                goto cleanup;
 216        }
 217
 218        memcpy(input_device->report_desc,
 219               ((unsigned char *)desc) + desc->bLength,
 220               desc->desc[0].wDescriptorLength);
 221
 222        /* Send the ack */
 223        memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
 224
 225        ack.type = PIPE_MESSAGE_DATA;
 226        ack.size = sizeof(struct synthhid_device_info_ack);
 227
 228        ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
 229        ack.ack.header.size = 1;
 230        ack.ack.reserved = 0;
 231
 232        ret = vmbus_sendpacket(input_device->device->channel,
 233                        &ack,
 234                        sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
 235                        sizeof(struct synthhid_device_info_ack),
 236                        (unsigned long)&ack,
 237                        VM_PKT_DATA_INBAND,
 238                        VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 239
 240        if (!ret)
 241                input_device->dev_info_status = 0;
 242
 243cleanup:
 244        complete(&input_device->wait_event);
 245
 246        return;
 247}
 248
 249static void mousevsc_on_receive(struct hv_device *device,
 250                                struct vmpacket_descriptor *packet)
 251{
 252        struct pipe_prt_msg *pipe_msg;
 253        struct synthhid_msg *hid_msg;
 254        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
 255        struct synthhid_input_report *input_report;
 256        size_t len;
 257
 258        pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
 259                                                (packet->offset8 << 3));
 260
 261        if (pipe_msg->type != PIPE_MESSAGE_DATA)
 262                return;
 263
 264        hid_msg = (struct synthhid_msg *)pipe_msg->data;
 265
 266        switch (hid_msg->header.type) {
 267        case SYNTH_HID_PROTOCOL_RESPONSE:
 268                /*
 269                 * While it will be impossible for us to protect against
 270                 * malicious/buggy hypervisor/host, add a check here to
 271                 * ensure we don't corrupt memory.
 272                 */
 273                if ((pipe_msg->size + sizeof(struct pipe_prt_msg)
 274                        - sizeof(unsigned char))
 275                        > sizeof(struct mousevsc_prt_msg)) {
 276                        WARN_ON(1);
 277                        break;
 278                }
 279
 280                memcpy(&input_dev->protocol_resp, pipe_msg,
 281                       pipe_msg->size + sizeof(struct pipe_prt_msg) -
 282                       sizeof(unsigned char));
 283                complete(&input_dev->wait_event);
 284                break;
 285
 286        case SYNTH_HID_INITIAL_DEVICE_INFO:
 287                WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
 288
 289                /*
 290                 * Parse out the device info into device attr,
 291                 * hid desc and report desc
 292                 */
 293                mousevsc_on_receive_device_info(input_dev,
 294                        (struct synthhid_device_info *)pipe_msg->data);
 295                break;
 296        case SYNTH_HID_INPUT_REPORT:
 297                input_report =
 298                        (struct synthhid_input_report *)pipe_msg->data;
 299                if (!input_dev->init_complete)
 300                        break;
 301
 302                len = min(input_report->header.size,
 303                          (u32)sizeof(input_dev->input_buf));
 304                memcpy(input_dev->input_buf, input_report->buffer, len);
 305                hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
 306                                 input_dev->input_buf, len, 1);
 307
 308                pm_wakeup_hard_event(&input_dev->device->device);
 309
 310                break;
 311        default:
 312                pr_err("unsupported hid msg type - type %d len %d\n",
 313                       hid_msg->header.type, hid_msg->header.size);
 314                break;
 315        }
 316
 317}
 318
 319static void mousevsc_on_channel_callback(void *context)
 320{
 321        struct hv_device *device = context;
 322        struct vmpacket_descriptor *desc;
 323
 324        foreach_vmbus_pkt(desc, device->channel) {
 325                switch (desc->type) {
 326                case VM_PKT_COMP:
 327                        break;
 328
 329                case VM_PKT_DATA_INBAND:
 330                        mousevsc_on_receive(device, desc);
 331                        break;
 332
 333                default:
 334                        pr_err("Unhandled packet type %d, tid %llx len %d\n",
 335                               desc->type, desc->trans_id, desc->len8 * 8);
 336                        break;
 337                }
 338        }
 339}
 340
 341static int mousevsc_connect_to_vsp(struct hv_device *device)
 342{
 343        int ret = 0;
 344        unsigned long t;
 345        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
 346        struct mousevsc_prt_msg *request;
 347        struct mousevsc_prt_msg *response;
 348
 349        reinit_completion(&input_dev->wait_event);
 350
 351        request = &input_dev->protocol_req;
 352        memset(request, 0, sizeof(struct mousevsc_prt_msg));
 353
 354        request->type = PIPE_MESSAGE_DATA;
 355        request->size = sizeof(struct synthhid_protocol_request);
 356        request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
 357        request->request.header.size = sizeof(unsigned int);
 358        request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
 359
 360        ret = vmbus_sendpacket(device->channel, request,
 361                                sizeof(struct pipe_prt_msg) -
 362                                sizeof(unsigned char) +
 363                                sizeof(struct synthhid_protocol_request),
 364                                (unsigned long)request,
 365                                VM_PKT_DATA_INBAND,
 366                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 367        if (ret)
 368                goto cleanup;
 369
 370        t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
 371        if (!t) {
 372                ret = -ETIMEDOUT;
 373                goto cleanup;
 374        }
 375
 376        response = &input_dev->protocol_resp;
 377
 378        if (!response->response.approved) {
 379                pr_err("synthhid protocol request failed (version %d)\n",
 380                       SYNTHHID_INPUT_VERSION);
 381                ret = -ENODEV;
 382                goto cleanup;
 383        }
 384
 385        t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
 386        if (!t) {
 387                ret = -ETIMEDOUT;
 388                goto cleanup;
 389        }
 390
 391        /*
 392         * We should have gotten the device attr, hid desc and report
 393         * desc at this point
 394         */
 395        ret = input_dev->dev_info_status;
 396
 397cleanup:
 398        return ret;
 399}
 400
 401static int mousevsc_hid_parse(struct hid_device *hid)
 402{
 403        struct hv_device *dev = hid_get_drvdata(hid);
 404        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 405
 406        return hid_parse_report(hid, input_dev->report_desc,
 407                                input_dev->report_desc_size);
 408}
 409
 410static int mousevsc_hid_open(struct hid_device *hid)
 411{
 412        return 0;
 413}
 414
 415static int mousevsc_hid_start(struct hid_device *hid)
 416{
 417        return 0;
 418}
 419
 420static void mousevsc_hid_close(struct hid_device *hid)
 421{
 422}
 423
 424static void mousevsc_hid_stop(struct hid_device *hid)
 425{
 426}
 427
 428static int mousevsc_hid_raw_request(struct hid_device *hid,
 429                                    unsigned char report_num,
 430                                    __u8 *buf, size_t len,
 431                                    unsigned char rtype,
 432                                    int reqtype)
 433{
 434        return 0;
 435}
 436
 437static struct hid_ll_driver mousevsc_ll_driver = {
 438        .parse = mousevsc_hid_parse,
 439        .open = mousevsc_hid_open,
 440        .close = mousevsc_hid_close,
 441        .start = mousevsc_hid_start,
 442        .stop = mousevsc_hid_stop,
 443        .raw_request = mousevsc_hid_raw_request,
 444};
 445
 446static struct hid_driver mousevsc_hid_driver;
 447
 448static int mousevsc_probe(struct hv_device *device,
 449                        const struct hv_vmbus_device_id *dev_id)
 450{
 451        int ret;
 452        struct mousevsc_dev *input_dev;
 453        struct hid_device *hid_dev;
 454
 455        input_dev = mousevsc_alloc_device(device);
 456
 457        if (!input_dev)
 458                return -ENOMEM;
 459
 460        ret = vmbus_open(device->channel,
 461                INPUTVSC_SEND_RING_BUFFER_SIZE,
 462                INPUTVSC_RECV_RING_BUFFER_SIZE,
 463                NULL,
 464                0,
 465                mousevsc_on_channel_callback,
 466                device
 467                );
 468
 469        if (ret)
 470                goto probe_err0;
 471
 472        ret = mousevsc_connect_to_vsp(device);
 473
 474        if (ret)
 475                goto probe_err1;
 476
 477        /* workaround SA-167 */
 478        if (input_dev->report_desc[14] == 0x25)
 479                input_dev->report_desc[14] = 0x29;
 480
 481        hid_dev = hid_allocate_device();
 482        if (IS_ERR(hid_dev)) {
 483                ret = PTR_ERR(hid_dev);
 484                goto probe_err1;
 485        }
 486
 487        hid_dev->ll_driver = &mousevsc_ll_driver;
 488        hid_dev->driver = &mousevsc_hid_driver;
 489        hid_dev->bus = BUS_VIRTUAL;
 490        hid_dev->vendor = input_dev->hid_dev_info.vendor;
 491        hid_dev->product = input_dev->hid_dev_info.product;
 492        hid_dev->version = input_dev->hid_dev_info.version;
 493        input_dev->hid_device = hid_dev;
 494
 495        sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
 496
 497        hid_set_drvdata(hid_dev, device);
 498
 499        ret = hid_add_device(hid_dev);
 500        if (ret)
 501                goto probe_err1;
 502
 503
 504        ret = hid_parse(hid_dev);
 505        if (ret) {
 506                hid_err(hid_dev, "parse failed\n");
 507                goto probe_err2;
 508        }
 509
 510        ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
 511
 512        if (ret) {
 513                hid_err(hid_dev, "hw start failed\n");
 514                goto probe_err2;
 515        }
 516
 517        device_init_wakeup(&device->device, true);
 518
 519        input_dev->connected = true;
 520        input_dev->init_complete = true;
 521
 522        return ret;
 523
 524probe_err2:
 525        hid_destroy_device(hid_dev);
 526
 527probe_err1:
 528        vmbus_close(device->channel);
 529
 530probe_err0:
 531        mousevsc_free_device(input_dev);
 532
 533        return ret;
 534}
 535
 536
 537static int mousevsc_remove(struct hv_device *dev)
 538{
 539        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 540
 541        device_init_wakeup(&dev->device, false);
 542        vmbus_close(dev->channel);
 543        hid_hw_stop(input_dev->hid_device);
 544        hid_destroy_device(input_dev->hid_device);
 545        mousevsc_free_device(input_dev);
 546
 547        return 0;
 548}
 549
 550static int mousevsc_suspend(struct hv_device *dev)
 551{
 552        vmbus_close(dev->channel);
 553
 554        return 0;
 555}
 556
 557static int mousevsc_resume(struct hv_device *dev)
 558{
 559        int ret;
 560
 561        ret = vmbus_open(dev->channel,
 562                         INPUTVSC_SEND_RING_BUFFER_SIZE,
 563                         INPUTVSC_RECV_RING_BUFFER_SIZE,
 564                         NULL, 0,
 565                         mousevsc_on_channel_callback,
 566                         dev);
 567        if (ret)
 568                return ret;
 569
 570        ret = mousevsc_connect_to_vsp(dev);
 571        return ret;
 572}
 573
 574static const struct hv_vmbus_device_id id_table[] = {
 575        /* Mouse guid */
 576        { HV_MOUSE_GUID, },
 577        { },
 578};
 579
 580MODULE_DEVICE_TABLE(vmbus, id_table);
 581
 582static struct  hv_driver mousevsc_drv = {
 583        .name = KBUILD_MODNAME,
 584        .id_table = id_table,
 585        .probe = mousevsc_probe,
 586        .remove = mousevsc_remove,
 587        .suspend = mousevsc_suspend,
 588        .resume = mousevsc_resume,
 589        .driver = {
 590                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
 591        },
 592};
 593
 594static int __init mousevsc_init(void)
 595{
 596        return vmbus_driver_register(&mousevsc_drv);
 597}
 598
 599static void __exit mousevsc_exit(void)
 600{
 601        vmbus_driver_unregister(&mousevsc_drv);
 602}
 603
 604MODULE_LICENSE("GPL");
 605MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic HID Driver");
 606
 607module_init(mousevsc_init);
 608module_exit(mousevsc_exit);
 609