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