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