2 * Copyright (c) 2009, Citrix Systems, Inc.
3 * Copyright (c) 2010, Microsoft Corporation.
4 * Copyright (c) 2011, Novell Inc.
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.
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
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>
25 struct hv_input_dev_info
{
27 unsigned short vendor
;
28 unsigned short product
;
29 unsigned short version
;
30 unsigned short reserved
[11];
33 /* The maximum size of a synthetic input message. */
34 #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
40 * Beta, RC < 2008/1/22 1,0
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))
51 * Message types in the synthetic input protocol
53 enum 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
,
63 * Basic message structures.
65 struct synthhid_msg_hdr
{
66 enum synthhid_msg_type type
;
71 struct synthhid_msg_hdr header
;
72 char data
[1]; /* Enclosed message */
75 union synthhid_version
{
86 struct synthhid_protocol_request
{
87 struct synthhid_msg_hdr header
;
88 union synthhid_version version_requested
;
91 struct synthhid_protocol_response
{
92 struct synthhid_msg_hdr header
;
93 union synthhid_version version_requested
;
94 unsigned char approved
;
97 struct synthhid_device_info
{
98 struct synthhid_msg_hdr header
;
99 struct hv_input_dev_info hid_dev_info
;
100 struct hid_descriptor hid_descriptor
;
103 struct synthhid_device_info_ack
{
104 struct synthhid_msg_hdr header
;
105 unsigned char reserved
;
108 struct synthhid_input_report
{
109 struct synthhid_msg_hdr header
;
115 #define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE)
116 #define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE)
119 enum pipe_prot_msg_type
{
120 PIPE_MESSAGE_INVALID
,
126 struct pipe_prt_msg
{
127 enum pipe_prot_msg_type type
;
132 struct mousevsc_prt_msg
{
133 enum pipe_prot_msg_type type
;
136 struct synthhid_protocol_request request
;
137 struct synthhid_protocol_response response
;
138 struct synthhid_device_info_ack ack
;
143 * Represents an mousevsc device
145 struct mousevsc_dev
{
146 struct hv_device
*device
;
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
;
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
;
163 static struct mousevsc_dev
*mousevsc_alloc_device(struct hv_device
*device
)
165 struct mousevsc_dev
*input_dev
;
167 input_dev
= kzalloc(sizeof(struct mousevsc_dev
), GFP_KERNEL
);
172 input_dev
->device
= device
;
173 hv_set_drvdata(device
, input_dev
);
174 init_completion(&input_dev
->wait_event
);
175 input_dev
->init_complete
= false;
180 static void mousevsc_free_device(struct mousevsc_dev
*device
)
182 kfree(device
->hid_desc
);
183 kfree(device
->report_desc
);
184 hv_set_drvdata(device
->device
, NULL
);
188 static void mousevsc_on_receive_device_info(struct mousevsc_dev
*input_device
,
189 struct synthhid_device_info
*device_info
)
192 struct hid_descriptor
*desc
;
193 struct mousevsc_prt_msg ack
;
195 input_device
->dev_info_status
= -ENOMEM
;
197 input_device
->hid_dev_info
= device_info
->hid_dev_info
;
198 desc
= &device_info
->hid_descriptor
;
199 if (desc
->bLength
== 0)
202 input_device
->hid_desc
= kzalloc(desc
->bLength
, GFP_ATOMIC
);
204 if (!input_device
->hid_desc
)
207 memcpy(input_device
->hid_desc
, desc
, desc
->bLength
);
209 input_device
->report_desc_size
= desc
->desc
[0].wDescriptorLength
;
210 if (input_device
->report_desc_size
== 0) {
211 input_device
->dev_info_status
= -EINVAL
;
215 input_device
->report_desc
= kzalloc(input_device
->report_desc_size
,
218 if (!input_device
->report_desc
) {
219 input_device
->dev_info_status
= -ENOMEM
;
223 memcpy(input_device
->report_desc
,
224 ((unsigned char *)desc
) + desc
->bLength
,
225 desc
->desc
[0].wDescriptorLength
);
228 memset(&ack
, 0, sizeof(struct mousevsc_prt_msg
));
230 ack
.type
= PIPE_MESSAGE_DATA
;
231 ack
.size
= sizeof(struct synthhid_device_info_ack
);
233 ack
.ack
.header
.type
= SYNTH_HID_INITIAL_DEVICE_INFO_ACK
;
234 ack
.ack
.header
.size
= 1;
235 ack
.ack
.reserved
= 0;
237 ret
= vmbus_sendpacket(input_device
->device
->channel
,
239 sizeof(struct pipe_prt_msg
) - sizeof(unsigned char) +
240 sizeof(struct synthhid_device_info_ack
),
243 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
246 input_device
->dev_info_status
= 0;
249 complete(&input_device
->wait_event
);
254 static void mousevsc_on_receive(struct hv_device
*device
,
255 struct vmpacket_descriptor
*packet
)
257 struct pipe_prt_msg
*pipe_msg
;
258 struct synthhid_msg
*hid_msg
;
259 struct mousevsc_dev
*input_dev
= hv_get_drvdata(device
);
260 struct synthhid_input_report
*input_report
;
262 pipe_msg
= (struct pipe_prt_msg
*)((unsigned long)packet
+
263 (packet
->offset8
<< 3));
265 if (pipe_msg
->type
!= PIPE_MESSAGE_DATA
)
268 hid_msg
= (struct synthhid_msg
*)pipe_msg
->data
;
270 switch (hid_msg
->header
.type
) {
271 case SYNTH_HID_PROTOCOL_RESPONSE
:
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.
277 if ((pipe_msg
->size
+ sizeof(struct pipe_prt_msg
)
278 - sizeof(unsigned char))
279 > sizeof(struct mousevsc_prt_msg
)) {
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
);
290 case SYNTH_HID_INITIAL_DEVICE_INFO
:
291 WARN_ON(pipe_msg
->size
< sizeof(struct hv_input_dev_info
));
294 * Parse out the device info into device attr,
295 * hid desc and report desc
297 mousevsc_on_receive_device_info(input_dev
,
298 (struct synthhid_device_info
*)pipe_msg
->data
);
300 case SYNTH_HID_INPUT_REPORT
:
302 (struct synthhid_input_report
*)pipe_msg
->data
;
303 if (!input_dev
->init_complete
)
305 hid_input_report(input_dev
->hid_device
,
306 HID_INPUT_REPORT
, input_report
->buffer
,
307 input_report
->header
.size
, 1);
310 pr_err("unsupported hid msg type - type %d len %d",
311 hid_msg
->header
.type
, hid_msg
->header
.size
);
317 static void mousevsc_on_channel_callback(void *context
)
319 const int packet_size
= 0x100;
321 struct hv_device
*device
= context
;
324 struct vmpacket_descriptor
*desc
;
325 unsigned char *buffer
;
326 int bufferlen
= packet_size
;
328 buffer
= kmalloc(bufferlen
, GFP_ATOMIC
);
333 ret
= vmbus_recvpacket_raw(device
->channel
, buffer
,
334 bufferlen
, &bytes_recvd
, &req_id
);
338 if (bytes_recvd
<= 0) {
342 desc
= (struct vmpacket_descriptor
*)buffer
;
344 switch (desc
->type
) {
348 case VM_PKT_DATA_INBAND
:
349 mousevsc_on_receive(device
, desc
);
353 pr_err("unhandled packet type %d, tid %llx len %d\n",
354 desc
->type
, req_id
, bytes_recvd
);
362 /* Handle large packet */
363 bufferlen
= bytes_recvd
;
364 buffer
= kmalloc(bytes_recvd
, GFP_ATOMIC
);
375 static int mousevsc_connect_to_vsp(struct hv_device
*device
)
379 struct mousevsc_dev
*input_dev
= hv_get_drvdata(device
);
380 struct mousevsc_prt_msg
*request
;
381 struct mousevsc_prt_msg
*response
;
383 request
= &input_dev
->protocol_req
;
384 memset(request
, 0, sizeof(struct mousevsc_prt_msg
));
386 request
->type
= PIPE_MESSAGE_DATA
;
387 request
->size
= sizeof(struct synthhid_protocol_request
);
388 request
->request
.header
.type
= SYNTH_HID_PROTOCOL_REQUEST
;
389 request
->request
.header
.size
= sizeof(unsigned int);
390 request
->request
.version_requested
.version
= SYNTHHID_INPUT_VERSION
;
392 ret
= vmbus_sendpacket(device
->channel
, request
,
393 sizeof(struct pipe_prt_msg
) -
394 sizeof(unsigned char) +
395 sizeof(struct synthhid_protocol_request
),
396 (unsigned long)request
,
398 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
402 t
= wait_for_completion_timeout(&input_dev
->wait_event
, 5*HZ
);
408 response
= &input_dev
->protocol_resp
;
410 if (!response
->response
.approved
) {
411 pr_err("synthhid protocol request failed (version %d)\n",
412 SYNTHHID_INPUT_VERSION
);
417 t
= wait_for_completion_timeout(&input_dev
->wait_event
, 5*HZ
);
424 * We should have gotten the device attr, hid desc and report
427 ret
= input_dev
->dev_info_status
;
433 static int mousevsc_hid_open(struct hid_device
*hid
)
438 static int mousevsc_hid_start(struct hid_device
*hid
)
443 static void mousevsc_hid_close(struct hid_device
*hid
)
447 static void mousevsc_hid_stop(struct hid_device
*hid
)
451 static struct hid_ll_driver mousevsc_ll_driver
= {
452 .open
= mousevsc_hid_open
,
453 .close
= mousevsc_hid_close
,
454 .start
= mousevsc_hid_start
,
455 .stop
= mousevsc_hid_stop
,
458 static struct hid_driver mousevsc_hid_driver
;
460 static int mousevsc_probe(struct hv_device
*device
,
461 const struct hv_vmbus_device_id
*dev_id
)
464 struct mousevsc_dev
*input_dev
;
465 struct hid_device
*hid_dev
;
467 input_dev
= mousevsc_alloc_device(device
);
472 ret
= vmbus_open(device
->channel
,
473 INPUTVSC_SEND_RING_BUFFER_SIZE
,
474 INPUTVSC_RECV_RING_BUFFER_SIZE
,
477 mousevsc_on_channel_callback
,
484 ret
= mousevsc_connect_to_vsp(device
);
489 /* workaround SA-167 */
490 if (input_dev
->report_desc
[14] == 0x25)
491 input_dev
->report_desc
[14] = 0x29;
493 hid_dev
= hid_allocate_device();
494 if (IS_ERR(hid_dev
)) {
495 ret
= PTR_ERR(hid_dev
);
499 hid_dev
->ll_driver
= &mousevsc_ll_driver
;
500 hid_dev
->driver
= &mousevsc_hid_driver
;
501 hid_dev
->bus
= BUS_VIRTUAL
;
502 hid_dev
->vendor
= input_dev
->hid_dev_info
.vendor
;
503 hid_dev
->product
= input_dev
->hid_dev_info
.product
;
504 hid_dev
->version
= input_dev
->hid_dev_info
.version
;
505 input_dev
->hid_device
= hid_dev
;
507 sprintf(hid_dev
->name
, "%s", "Microsoft Vmbus HID-compliant Mouse");
509 ret
= hid_add_device(hid_dev
);
513 ret
= hid_parse_report(hid_dev
, input_dev
->report_desc
,
514 input_dev
->report_desc_size
);
517 hid_err(hid_dev
, "parse failed\n");
521 ret
= hid_hw_start(hid_dev
, HID_CONNECT_HIDINPUT
| HID_CONNECT_HIDDEV
);
524 hid_err(hid_dev
, "hw start failed\n");
528 input_dev
->connected
= true;
529 input_dev
->init_complete
= true;
534 hid_destroy_device(hid_dev
);
537 vmbus_close(device
->channel
);
540 mousevsc_free_device(input_dev
);
546 static int mousevsc_remove(struct hv_device
*dev
)
548 struct mousevsc_dev
*input_dev
= hv_get_drvdata(dev
);
550 vmbus_close(dev
->channel
);
551 hid_hw_stop(input_dev
->hid_device
);
552 hid_destroy_device(input_dev
->hid_device
);
553 mousevsc_free_device(input_dev
);
558 static const struct hv_vmbus_device_id id_table
[] = {
560 { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
561 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) },
565 MODULE_DEVICE_TABLE(vmbus
, id_table
);
567 static struct hv_driver mousevsc_drv
= {
568 .name
= KBUILD_MODNAME
,
569 .id_table
= id_table
,
570 .probe
= mousevsc_probe
,
571 .remove
= mousevsc_remove
,
574 static int __init
mousevsc_init(void)
576 return vmbus_driver_register(&mousevsc_drv
);
579 static void __exit
mousevsc_exit(void)
581 vmbus_driver_unregister(&mousevsc_drv
);
584 MODULE_LICENSE("GPL");
585 MODULE_VERSION(HV_DRV_VERSION
);
586 module_init(mousevsc_init
);
587 module_exit(mousevsc_exit
);