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                break;
 312        default:
 313                pr_err("unsupported hid msg type - type %d len %d",
 314                       hid_msg->header.type, hid_msg->header.size);
 315                break;
 316        }
 317
 318}
 319
 320static void mousevsc_on_channel_callback(void *context)
 321{
 322        const int packet_size = 0x100;
 323        int ret;
 324        struct hv_device *device = context;
 325        u32 bytes_recvd;
 326        u64 req_id;
 327        struct vmpacket_descriptor *desc;
 328        unsigned char   *buffer;
 329        int     bufferlen = packet_size;
 330
 331        buffer = kmalloc(bufferlen, GFP_ATOMIC);
 332        if (!buffer)
 333                return;
 334
 335        do {
 336                ret = vmbus_recvpacket_raw(device->channel, buffer,
 337                                        bufferlen, &bytes_recvd, &req_id);
 338
 339                switch (ret) {
 340                case 0:
 341                        if (bytes_recvd <= 0) {
 342                                kfree(buffer);
 343                                return;
 344                        }
 345                        desc = (struct vmpacket_descriptor *)buffer;
 346
 347                        switch (desc->type) {
 348                        case VM_PKT_COMP:
 349                                break;
 350
 351                        case VM_PKT_DATA_INBAND:
 352                                mousevsc_on_receive(device, desc);
 353                                break;
 354
 355                        default:
 356                                pr_err("unhandled packet type %d, tid %llx len %d\n",
 357                                        desc->type, req_id, bytes_recvd);
 358                                break;
 359                        }
 360
 361                        break;
 362
 363                case -ENOBUFS:
 364                        kfree(buffer);
 365                        /* Handle large packet */
 366                        bufferlen = bytes_recvd;
 367                        buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
 368
 369                        if (!buffer)
 370                                return;
 371
 372                        break;
 373                }
 374        } while (1);
 375
 376}
 377
 378static int mousevsc_connect_to_vsp(struct hv_device *device)
 379{
 380        int ret = 0;
 381        int t;
 382        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
 383        struct mousevsc_prt_msg *request;
 384        struct mousevsc_prt_msg *response;
 385
 386        request = &input_dev->protocol_req;
 387        memset(request, 0, sizeof(struct mousevsc_prt_msg));
 388
 389        request->type = PIPE_MESSAGE_DATA;
 390        request->size = sizeof(struct synthhid_protocol_request);
 391        request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
 392        request->request.header.size = sizeof(unsigned int);
 393        request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
 394
 395        ret = vmbus_sendpacket(device->channel, request,
 396                                sizeof(struct pipe_prt_msg) -
 397                                sizeof(unsigned char) +
 398                                sizeof(struct synthhid_protocol_request),
 399                                (unsigned long)request,
 400                                VM_PKT_DATA_INBAND,
 401                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 402        if (ret)
 403                goto cleanup;
 404
 405        t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
 406        if (!t) {
 407                ret = -ETIMEDOUT;
 408                goto cleanup;
 409        }
 410
 411        response = &input_dev->protocol_resp;
 412
 413        if (!response->response.approved) {
 414                pr_err("synthhid protocol request failed (version %d)\n",
 415                       SYNTHHID_INPUT_VERSION);
 416                ret = -ENODEV;
 417                goto cleanup;
 418        }
 419
 420        t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
 421        if (!t) {
 422                ret = -ETIMEDOUT;
 423                goto cleanup;
 424        }
 425
 426        /*
 427         * We should have gotten the device attr, hid desc and report
 428         * desc at this point
 429         */
 430        ret = input_dev->dev_info_status;
 431
 432cleanup:
 433        return ret;
 434}
 435
 436static int mousevsc_hid_parse(struct hid_device *hid)
 437{
 438        struct hv_device *dev = hid_get_drvdata(hid);
 439        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 440
 441        return hid_parse_report(hid, input_dev->report_desc,
 442                                input_dev->report_desc_size);
 443}
 444
 445static int mousevsc_hid_open(struct hid_device *hid)
 446{
 447        return 0;
 448}
 449
 450static int mousevsc_hid_start(struct hid_device *hid)
 451{
 452        return 0;
 453}
 454
 455static void mousevsc_hid_close(struct hid_device *hid)
 456{
 457}
 458
 459static void mousevsc_hid_stop(struct hid_device *hid)
 460{
 461}
 462
 463static int mousevsc_hid_raw_request(struct hid_device *hid,
 464                                    unsigned char report_num,
 465                                    __u8 *buf, size_t len,
 466                                    unsigned char rtype,
 467                                    int reqtype)
 468{
 469        return 0;
 470}
 471
 472static struct hid_ll_driver mousevsc_ll_driver = {
 473        .parse = mousevsc_hid_parse,
 474        .open = mousevsc_hid_open,
 475        .close = mousevsc_hid_close,
 476        .start = mousevsc_hid_start,
 477        .stop = mousevsc_hid_stop,
 478        .raw_request = mousevsc_hid_raw_request,
 479};
 480
 481static struct hid_driver mousevsc_hid_driver;
 482
 483static int mousevsc_probe(struct hv_device *device,
 484                        const struct hv_vmbus_device_id *dev_id)
 485{
 486        int ret;
 487        struct mousevsc_dev *input_dev;
 488        struct hid_device *hid_dev;
 489
 490        input_dev = mousevsc_alloc_device(device);
 491
 492        if (!input_dev)
 493                return -ENOMEM;
 494
 495        ret = vmbus_open(device->channel,
 496                INPUTVSC_SEND_RING_BUFFER_SIZE,
 497                INPUTVSC_RECV_RING_BUFFER_SIZE,
 498                NULL,
 499                0,
 500                mousevsc_on_channel_callback,
 501                device
 502                );
 503
 504        if (ret)
 505                goto probe_err0;
 506
 507        ret = mousevsc_connect_to_vsp(device);
 508
 509        if (ret)
 510                goto probe_err1;
 511
 512        /* workaround SA-167 */
 513        if (input_dev->report_desc[14] == 0x25)
 514                input_dev->report_desc[14] = 0x29;
 515
 516        hid_dev = hid_allocate_device();
 517        if (IS_ERR(hid_dev)) {
 518                ret = PTR_ERR(hid_dev);
 519                goto probe_err1;
 520        }
 521
 522        hid_dev->ll_driver = &mousevsc_ll_driver;
 523        hid_dev->driver = &mousevsc_hid_driver;
 524        hid_dev->bus = BUS_VIRTUAL;
 525        hid_dev->vendor = input_dev->hid_dev_info.vendor;
 526        hid_dev->product = input_dev->hid_dev_info.product;
 527        hid_dev->version = input_dev->hid_dev_info.version;
 528        input_dev->hid_device = hid_dev;
 529
 530        sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
 531
 532        hid_set_drvdata(hid_dev, device);
 533
 534        ret = hid_add_device(hid_dev);
 535        if (ret)
 536                goto probe_err1;
 537
 538
 539        ret = hid_parse(hid_dev);
 540        if (ret) {
 541                hid_err(hid_dev, "parse failed\n");
 542                goto probe_err2;
 543        }
 544
 545        ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
 546
 547        if (ret) {
 548                hid_err(hid_dev, "hw start failed\n");
 549                goto probe_err2;
 550        }
 551
 552        input_dev->connected = true;
 553        input_dev->init_complete = true;
 554
 555        return ret;
 556
 557probe_err2:
 558        hid_destroy_device(hid_dev);
 559
 560probe_err1:
 561        vmbus_close(device->channel);
 562
 563probe_err0:
 564        mousevsc_free_device(input_dev);
 565
 566        return ret;
 567}
 568
 569
 570static int mousevsc_remove(struct hv_device *dev)
 571{
 572        struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 573
 574        vmbus_close(dev->channel);
 575        hid_hw_stop(input_dev->hid_device);
 576        hid_destroy_device(input_dev->hid_device);
 577        mousevsc_free_device(input_dev);
 578
 579        return 0;
 580}
 581
 582static const struct hv_vmbus_device_id id_table[] = {
 583        /* Mouse guid */
 584        { HV_MOUSE_GUID, },
 585        { },
 586};
 587
 588MODULE_DEVICE_TABLE(vmbus, id_table);
 589
 590static struct  hv_driver mousevsc_drv = {
 591        .name = KBUILD_MODNAME,
 592        .id_table = id_table,
 593        .probe = mousevsc_probe,
 594        .remove = mousevsc_remove,
 595};
 596
 597static int __init mousevsc_init(void)
 598{
 599        return vmbus_driver_register(&mousevsc_drv);
 600}
 601
 602static void __exit mousevsc_exit(void)
 603{
 604        vmbus_driver_unregister(&mousevsc_drv);
 605}
 606
 607MODULE_LICENSE("GPL");
 608module_init(mousevsc_init);
 609module_exit(mousevsc_exit);
 610