staging: brcm80211: remove brcms_b_dotxstatus wrapper function
[zen-stable.git] / drivers / staging / hv / hv_mouse.c
blobedbb4797db758c46f192b833811652a3df64e6ce
1 /*
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
13 * more details.
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>
26 #include "hyperv.h"
29 struct hv_input_dev_info {
30 unsigned int size;
31 unsigned short vendor;
32 unsigned short product;
33 unsigned short version;
34 unsigned short reserved[11];
37 /* The maximum size of a synthetic input message. */
38 #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
41 * Current version
43 * History:
44 * Beta, RC < 2008/1/22 1,0
45 * RC > 2008/1/22 2,0
47 #define SYNTHHID_INPUT_VERSION_MAJOR 2
48 #define SYNTHHID_INPUT_VERSION_MINOR 0
49 #define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \
50 (SYNTHHID_INPUT_VERSION_MAJOR << 16))
53 #pragma pack(push, 1)
55 * Message types in the synthetic input protocol
57 enum synthhid_msg_type {
58 SYNTH_HID_PROTOCOL_REQUEST,
59 SYNTH_HID_PROTOCOL_RESPONSE,
60 SYNTH_HID_INITIAL_DEVICE_INFO,
61 SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
62 SYNTH_HID_INPUT_REPORT,
63 SYNTH_HID_MAX
67 * Basic message structures.
69 struct synthhid_msg_hdr {
70 enum synthhid_msg_type type;
71 u32 size;
74 struct synthhid_msg {
75 struct synthhid_msg_hdr header;
76 char data[1]; /* Enclosed message */
79 union synthhid_version {
80 struct {
81 u16 minor_version;
82 u16 major_version;
84 u32 version;
88 * Protocol messages
90 struct synthhid_protocol_request {
91 struct synthhid_msg_hdr header;
92 union synthhid_version version_requested;
95 struct synthhid_protocol_response {
96 struct synthhid_msg_hdr header;
97 union synthhid_version version_requested;
98 unsigned char approved;
101 struct synthhid_device_info {
102 struct synthhid_msg_hdr header;
103 struct hv_input_dev_info hid_dev_info;
104 struct hid_descriptor hid_descriptor;
107 struct synthhid_device_info_ack {
108 struct synthhid_msg_hdr header;
109 unsigned char reserved;
112 struct synthhid_input_report {
113 struct synthhid_msg_hdr header;
114 char buffer[1];
117 #pragma pack(pop)
119 #define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE)
120 #define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE)
122 #define NBITS(x) (((x)/BITS_PER_LONG)+1)
124 enum pipe_prot_msg_type {
125 PIPE_MESSAGE_INVALID,
126 PIPE_MESSAGE_DATA,
127 PIPE_MESSAGE_MAXIMUM
131 struct pipe_prt_msg {
132 enum pipe_prot_msg_type type;
133 u32 size;
134 char data[1];
137 struct mousevsc_prt_msg {
138 enum pipe_prot_msg_type type;
139 u32 size;
140 union {
141 struct synthhid_protocol_request request;
142 struct synthhid_protocol_response response;
143 struct synthhid_device_info_ack ack;
148 * Represents an mousevsc device
150 struct mousevsc_dev {
151 struct hv_device *device;
152 unsigned char init_complete;
153 struct mousevsc_prt_msg protocol_req;
154 struct mousevsc_prt_msg protocol_resp;
155 /* Synchronize the request/response if needed */
156 struct completion wait_event;
157 int dev_info_status;
159 struct hid_descriptor *hid_desc;
160 unsigned char *report_desc;
161 u32 report_desc_size;
162 struct hv_input_dev_info hid_dev_info;
163 int connected;
164 struct hid_device *hid_device;
168 static struct mousevsc_dev *alloc_input_device(struct hv_device *device)
170 struct mousevsc_dev *input_dev;
172 input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
174 if (!input_dev)
175 return NULL;
177 input_dev->device = device;
178 hv_set_drvdata(device, input_dev);
179 init_completion(&input_dev->wait_event);
181 return input_dev;
184 static void free_input_device(struct mousevsc_dev *device)
186 kfree(device->hid_desc);
187 kfree(device->report_desc);
188 hv_set_drvdata(device->device, NULL);
189 kfree(device);
193 static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
194 struct synthhid_device_info *device_info)
196 int ret = 0;
197 struct hid_descriptor *desc;
198 struct mousevsc_prt_msg ack;
200 /* Assume success for now */
201 input_device->dev_info_status = 0;
203 memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info,
204 sizeof(struct hv_input_dev_info));
206 desc = &device_info->hid_descriptor;
207 WARN_ON(desc->bLength == 0);
209 input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC);
211 if (!input_device->hid_desc)
212 goto cleanup;
214 memcpy(input_device->hid_desc, desc, desc->bLength);
216 input_device->report_desc_size = desc->desc[0].wDescriptorLength;
217 if (input_device->report_desc_size == 0)
218 goto cleanup;
219 input_device->report_desc = kzalloc(input_device->report_desc_size,
220 GFP_ATOMIC);
222 if (!input_device->report_desc)
223 goto cleanup;
225 memcpy(input_device->report_desc,
226 ((unsigned char *)desc) + desc->bLength,
227 desc->desc[0].wDescriptorLength);
229 /* Send the ack */
230 memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
232 ack.type = PIPE_MESSAGE_DATA;
233 ack.size = sizeof(struct synthhid_device_info_ack);
235 ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
236 ack.ack.header.size = 1;
237 ack.ack.reserved = 0;
239 ret = vmbus_sendpacket(input_device->device->channel,
240 &ack,
241 sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
242 sizeof(struct synthhid_device_info_ack),
243 (unsigned long)&ack,
244 VM_PKT_DATA_INBAND,
245 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
246 if (ret != 0)
247 goto cleanup;
249 complete(&input_device->wait_event);
251 return;
253 cleanup:
254 kfree(input_device->hid_desc);
255 input_device->hid_desc = NULL;
257 kfree(input_device->report_desc);
258 input_device->report_desc = NULL;
260 input_device->dev_info_status = -1;
261 complete(&input_device->wait_event);
264 static void mousevsc_on_receive(struct hv_device *device,
265 struct vmpacket_descriptor *packet)
267 struct pipe_prt_msg *pipe_msg;
268 struct synthhid_msg *hid_msg;
269 struct mousevsc_dev *input_dev = hv_get_drvdata(device);
270 struct synthhid_input_report *input_report;
272 pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
273 (packet->offset8 << 3));
275 if (pipe_msg->type != PIPE_MESSAGE_DATA)
276 return;
278 hid_msg = (struct synthhid_msg *)&pipe_msg->data[0];
280 switch (hid_msg->header.type) {
281 case SYNTH_HID_PROTOCOL_RESPONSE:
282 memcpy(&input_dev->protocol_resp, pipe_msg,
283 pipe_msg->size + sizeof(struct pipe_prt_msg) -
284 sizeof(unsigned char));
285 complete(&input_dev->wait_event);
286 break;
288 case SYNTH_HID_INITIAL_DEVICE_INFO:
289 WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
292 * Parse out the device info into device attr,
293 * hid desc and report desc
295 mousevsc_on_receive_device_info(input_dev,
296 (struct synthhid_device_info *)&pipe_msg->data[0]);
297 break;
298 case SYNTH_HID_INPUT_REPORT:
299 input_report =
300 (struct synthhid_input_report *)&pipe_msg->data[0];
301 if (!input_dev->init_complete)
302 break;
303 hid_input_report(input_dev->hid_device,
304 HID_INPUT_REPORT, input_report->buffer,
305 input_report->header.size, 1);
306 break;
307 default:
308 pr_err("unsupported hid msg type - type %d len %d",
309 hid_msg->header.type, hid_msg->header.size);
310 break;
315 static void mousevsc_on_channel_callback(void *context)
317 const int packetSize = 0x100;
318 int ret = 0;
319 struct hv_device *device = (struct hv_device *)context;
321 u32 bytes_recvd;
322 u64 req_id;
323 unsigned char packet[0x100];
324 struct vmpacket_descriptor *desc;
325 unsigned char *buffer = packet;
326 int bufferlen = packetSize;
329 do {
330 ret = vmbus_recvpacket_raw(device->channel, buffer,
331 bufferlen, &bytes_recvd, &req_id);
333 if (ret == 0) {
334 if (bytes_recvd > 0) {
335 desc = (struct vmpacket_descriptor *)buffer;
337 switch (desc->type) {
338 case VM_PKT_COMP:
339 break;
341 case VM_PKT_DATA_INBAND:
342 mousevsc_on_receive(
343 device, desc);
344 break;
346 default:
347 pr_err("unhandled packet type %d, tid %llx len %d\n",
348 desc->type,
349 req_id,
350 bytes_recvd);
351 break;
354 /* reset */
355 if (bufferlen > packetSize) {
356 kfree(buffer);
358 buffer = packet;
359 bufferlen = packetSize;
361 } else {
362 if (bufferlen > packetSize) {
363 kfree(buffer);
365 buffer = packet;
366 bufferlen = packetSize;
368 break;
370 } else if (ret == -ENOBUFS) {
371 /* Handle large packet */
372 bufferlen = bytes_recvd;
373 buffer = kzalloc(bytes_recvd, GFP_ATOMIC);
375 if (buffer == NULL) {
376 buffer = packet;
377 bufferlen = packetSize;
378 break;
381 } while (1);
383 return;
386 static int mousevsc_connect_to_vsp(struct hv_device *device)
388 int ret = 0;
389 int t;
390 struct mousevsc_dev *input_dev = hv_get_drvdata(device);
391 struct mousevsc_prt_msg *request;
392 struct mousevsc_prt_msg *response;
395 request = &input_dev->protocol_req;
397 memset(request, 0, sizeof(struct mousevsc_prt_msg));
399 request->type = PIPE_MESSAGE_DATA;
400 request->size = sizeof(struct synthhid_protocol_request);
402 request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
403 request->request.header.size = sizeof(unsigned int);
404 request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
407 ret = vmbus_sendpacket(device->channel, request,
408 sizeof(struct pipe_prt_msg) -
409 sizeof(unsigned char) +
410 sizeof(struct synthhid_protocol_request),
411 (unsigned long)request,
412 VM_PKT_DATA_INBAND,
413 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
414 if (ret != 0)
415 goto cleanup;
417 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
418 if (t == 0) {
419 ret = -ETIMEDOUT;
420 goto cleanup;
423 response = &input_dev->protocol_resp;
425 if (!response->response.approved) {
426 pr_err("synthhid protocol request failed (version %d)",
427 SYNTHHID_INPUT_VERSION);
428 ret = -ENODEV;
429 goto cleanup;
432 t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
433 if (t == 0) {
434 ret = -ETIMEDOUT;
435 goto cleanup;
439 * We should have gotten the device attr, hid desc and report
440 * desc at this point
442 if (input_dev->dev_info_status)
443 ret = -ENOMEM;
445 cleanup:
447 return ret;
450 static int mousevsc_hid_open(struct hid_device *hid)
452 return 0;
455 static void mousevsc_hid_close(struct hid_device *hid)
459 static struct hid_ll_driver mousevsc_ll_driver = {
460 .open = mousevsc_hid_open,
461 .close = mousevsc_hid_close,
464 static struct hid_driver mousevsc_hid_driver;
466 static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
468 struct hid_device *hid_dev;
469 struct mousevsc_dev *input_device = hv_get_drvdata(dev);
471 hid_dev = hid_allocate_device();
472 if (IS_ERR(hid_dev))
473 return;
475 hid_dev->ll_driver = &mousevsc_ll_driver;
476 hid_dev->driver = &mousevsc_hid_driver;
478 if (hid_parse_report(hid_dev, packet, len))
479 return;
481 hid_dev->bus = BUS_VIRTUAL;
482 hid_dev->vendor = input_device->hid_dev_info.vendor;
483 hid_dev->product = input_device->hid_dev_info.product;
484 hid_dev->version = input_device->hid_dev_info.version;
486 sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
488 if (!hidinput_connect(hid_dev, 0)) {
489 hid_dev->claimed |= HID_CLAIMED_INPUT;
491 input_device->connected = 1;
495 input_device->hid_device = hid_dev;
498 static int mousevsc_on_device_add(struct hv_device *device)
500 int ret = 0;
501 struct mousevsc_dev *input_dev;
503 input_dev = alloc_input_device(device);
505 if (!input_dev)
506 return -ENOMEM;
508 input_dev->init_complete = false;
510 ret = vmbus_open(device->channel,
511 INPUTVSC_SEND_RING_BUFFER_SIZE,
512 INPUTVSC_RECV_RING_BUFFER_SIZE,
513 NULL,
515 mousevsc_on_channel_callback,
516 device
519 if (ret != 0) {
520 free_input_device(input_dev);
521 return ret;
525 ret = mousevsc_connect_to_vsp(device);
527 if (ret != 0) {
528 vmbus_close(device->channel);
529 free_input_device(input_dev);
530 return ret;
534 /* workaround SA-167 */
535 if (input_dev->report_desc[14] == 0x25)
536 input_dev->report_desc[14] = 0x29;
538 reportdesc_callback(device, input_dev->report_desc,
539 input_dev->report_desc_size);
541 input_dev->init_complete = true;
543 return ret;
546 static int mousevsc_probe(struct hv_device *dev,
547 const struct hv_vmbus_device_id *dev_id)
550 return mousevsc_on_device_add(dev);
554 static int mousevsc_remove(struct hv_device *dev)
556 struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
558 vmbus_close(dev->channel);
560 if (input_dev->connected) {
561 hidinput_disconnect(input_dev->hid_device);
562 input_dev->connected = 0;
563 hid_destroy_device(input_dev->hid_device);
566 free_input_device(input_dev);
568 return 0;
571 static const struct hv_vmbus_device_id id_table[] = {
572 /* Mouse guid */
573 { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
574 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) },
575 { },
578 MODULE_DEVICE_TABLE(vmbus, id_table);
580 static struct hv_driver mousevsc_drv = {
581 .name = "mousevsc",
582 .id_table = id_table,
583 .probe = mousevsc_probe,
584 .remove = mousevsc_remove,
587 static int __init mousevsc_init(void)
589 return vmbus_driver_register(&mousevsc_drv);
592 static void __exit mousevsc_exit(void)
594 vmbus_driver_unregister(&mousevsc_drv);
597 MODULE_LICENSE("GPL");
598 MODULE_VERSION(HV_DRV_VERSION);
599 module_init(mousevsc_init);
600 module_exit(mousevsc_exit);