X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fstaging%2Fhv%2Fhv_mouse.c;h=ea9e1f30c144f8f5368e08315d706ba934fafa23;hb=622a50dce08bd817d2f10c1bcf806ccb35643653;hp=d7e24bce4c0d2e2b1b96ad320df6c7ca3411cef4;hpb=3d5cad97c4be2bfc5cb4e52a0972c6e3bf8c278d;p=pandora-kernel.git diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index d7e24bce4c0d..ea9e1f30c144 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include "hyperv.h" @@ -32,10 +30,11 @@ * Data types */ struct hv_input_dev_info { + unsigned int size; unsigned short vendor; unsigned short product; unsigned short version; - char name[128]; + unsigned short reserved[11]; }; /* The maximum size of a synthetic input message. */ @@ -163,23 +162,18 @@ struct mousevsc_dev { struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; /* Synchronize the request/response if needed */ - wait_queue_head_t protocol_wait_event; - wait_queue_head_t dev_info_wait_event; - int protocol_wait_condition; - int device_wait_condition; + struct completion wait_event; int dev_info_status; struct hid_descriptor *hid_desc; unsigned char *report_desc; u32 report_desc_size; struct hv_input_dev_info hid_dev_info; + int connected; + struct hid_device *hid_device; }; -static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info); -static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); -static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); - static struct mousevsc_dev *alloc_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; @@ -196,14 +190,15 @@ static struct mousevsc_dev *alloc_input_device(struct hv_device *device) atomic_cmpxchg(&input_dev->ref_count, 0, 2); input_dev->device = device; - device->ext = input_dev; + hv_set_drvdata(device, input_dev); + init_completion(&input_dev->wait_event); return input_dev; } static void free_input_device(struct mousevsc_dev *device) { - WARN_ON(atomic_read(&device->ref_count) == 0); + WARN_ON(atomic_read(&device->ref_count) != 0); kfree(device); } @@ -214,7 +209,7 @@ static struct mousevsc_dev *get_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* * FIXME @@ -240,7 +235,7 @@ static struct mousevsc_dev *must_get_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); if (input_dev && atomic_read(&input_dev->ref_count)) atomic_inc(&input_dev->ref_count); @@ -254,7 +249,7 @@ static void put_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); atomic_dec(&input_dev->ref_count); } @@ -266,7 +261,7 @@ static struct mousevsc_dev *release_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* Busy wait until the ref drop to 2, then set it to 1 */ while (atomic_cmpxchg(&input_dev->ref_count, 2, 1) != 2) @@ -282,13 +277,13 @@ static struct mousevsc_dev *final_release_input_device(struct hv_device *device) { struct mousevsc_dev *input_dev; - input_dev = (struct mousevsc_dev *)device->ext; + input_dev = hv_get_drvdata(device); /* Busy wait until the ref drop to 1, then set it to 0 */ while (atomic_cmpxchg(&input_dev->ref_count, 1, 0) != 1) udelay(100); - device->ext = NULL; + hv_set_drvdata(device, NULL); return input_dev; } @@ -330,26 +325,29 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, /* Save the hid desc */ desc = &device_info->hid_descriptor; - WARN_ON(desc->bLength > 0); + WARN_ON(desc->bLength == 0); - input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL); + input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); if (!input_device->hid_desc) { - pr_err("unable to allocate hid descriptor - size %d", desc->bLength); - goto Cleanup; + pr_err("unable to allocate hid descriptor - size %d", + desc->bLength); + goto cleanup; } memcpy(input_device->hid_desc, desc, desc->bLength); /* Save the report desc */ input_device->report_desc_size = desc->desc[0].wDescriptorLength; + if (input_device->report_desc_size == 0) + goto cleanup; input_device->report_desc = kzalloc(input_device->report_desc_size, - GFP_KERNEL); + GFP_ATOMIC); if (!input_device->report_desc) { pr_err("unable to allocate report descriptor - size %d", input_device->report_desc_size); - goto Cleanup; + goto cleanup; } memcpy(input_device->report_desc, @@ -376,15 +374,14 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, if (ret != 0) { pr_err("unable to send synthhid device info ack - ret %d", ret); - goto Cleanup; + goto cleanup; } - input_device->device_wait_condition = 1; - wake_up(&input_device->dev_info_wait_event); + complete(&input_device->wait_event); return; -Cleanup: +cleanup: kfree(input_device->hid_desc); input_device->hid_desc = NULL; @@ -392,8 +389,7 @@ Cleanup: input_device->report_desc = NULL; input_device->dev_info_status = -1; - input_device->device_wait_condition = 1; - wake_up(&input_device->dev_info_wait_event); + complete(&input_device->wait_event); } static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, @@ -408,9 +404,10 @@ static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device, input_drv = drv_to_hv_drv(input_device->device->device.driver); - inputreport_callback(input_device->device, - input_report->buffer, - input_report->header.size); + + hid_input_report(input_device->hid_device, + HID_INPUT_REPORT, input_report->buffer, input_report->header.size, 1); + } static void mousevsc_on_receive(struct hv_device *device, @@ -443,12 +440,11 @@ static void mousevsc_on_receive(struct hv_device *device, memcpy(&input_dev->protocol_resp, pipe_msg, pipe_msg->size + sizeof(struct pipe_prt_msg) - sizeof(unsigned char)); - input_dev->protocol_wait_condition = 1; - wake_up(&input_dev->protocol_wait_event); + complete(&input_dev->wait_event); break; case SynthHidInitialDeviceInfo: - WARN_ON(pipe_msg->size >= sizeof(struct hv_input_dev_info)); + WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); /* * Parse out the device info into device attr, @@ -542,7 +538,7 @@ static void mousevsc_on_channel_callback(void *context) } else if (ret == -ENOBUFS) { /* Handle large packet */ bufferlen = bytes_recvd; - buffer = kzalloc(bytes_recvd, GFP_KERNEL); + buffer = kzalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { buffer = packet; @@ -564,6 +560,7 @@ static void mousevsc_on_channel_callback(void *context) static int mousevsc_connect_to_vsp(struct hv_device *device) { int ret = 0; + int t; struct mousevsc_dev *input_dev; struct mousevsc_prt_msg *request; struct mousevsc_prt_msg *response; @@ -575,8 +572,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) return -1; } - init_waitqueue_head(&input_dev->protocol_wait_event); - init_waitqueue_head(&input_dev->dev_info_wait_event); request = &input_dev->protocol_req; @@ -589,29 +584,27 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) request->size = sizeof(struct synthhid_protocol_request); request->request.header.type = SynthHidProtocolRequest; - request->request.header.size = sizeof(unsigned long); + request->request.header.size = sizeof(unsigned int); request->request.version_requested.version = SYNTHHID_INPUT_VERSION; pr_info("synthhid protocol request..."); ret = vmbus_sendpacket(device->channel, request, - sizeof(struct pipe_prt_msg) - - sizeof(unsigned char) + - sizeof(struct synthhid_protocol_request), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + sizeof(struct pipe_prt_msg) - + sizeof(unsigned char) + + sizeof(struct synthhid_protocol_request), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) { pr_err("unable to send synthhid protocol request."); - goto Cleanup; + goto cleanup; } - input_dev->protocol_wait_condition = 0; - wait_event_timeout(input_dev->protocol_wait_event, - input_dev->protocol_wait_condition, msecs_to_jiffies(1000)); - if (input_dev->protocol_wait_condition == 0) { + t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); + if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } response = &input_dev->protocol_resp; @@ -620,15 +613,13 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) pr_err("synthhid protocol request failed (version %d)", SYNTHHID_INPUT_VERSION); ret = -1; - goto Cleanup; + goto cleanup; } - input_dev->device_wait_condition = 0; - wait_event_timeout(input_dev->dev_info_wait_event, - input_dev->device_wait_condition, msecs_to_jiffies(1000)); - if (input_dev->device_wait_condition == 0) { + t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); + if (t == 0) { ret = -ETIMEDOUT; - goto Cleanup; + goto cleanup; } /* @@ -640,25 +631,85 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) else ret = -1; -Cleanup: +cleanup: put_input_device(device); return ret; } +static int mousevsc_hid_open(struct hid_device *hid) +{ + return 0; +} + +static void mousevsc_hid_close(struct hid_device *hid) +{ +} + +static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) +{ + struct hid_device *hid_dev; + struct mousevsc_dev *input_device = hv_get_drvdata(dev); + + /* hid_debug = -1; */ + hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); + + if (hid_parse_report(hid_dev, packet, len)) { + DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); + return; + } + + if (hid_dev) { + DPRINT_INFO(INPUTVSC_DRV, "hid_device created"); + + hid_dev->ll_driver->open = mousevsc_hid_open; + hid_dev->ll_driver->close = mousevsc_hid_close; + + hid_dev->bus = BUS_VIRTUAL; + hid_dev->vendor = input_device->hid_dev_info.vendor; + hid_dev->product = input_device->hid_dev_info.product; + hid_dev->version = input_device->hid_dev_info.version; + hid_dev->dev = dev->device; + + sprintf(hid_dev->name, "%s", + "Microsoft Vmbus HID-compliant Mouse"); + + /* + * HJ Do we want to call it with a 0 + */ + if (!hidinput_connect(hid_dev, 0)) { + hid_dev->claimed |= HID_CLAIMED_INPUT; + + input_device->connected = 1; + + DPRINT_INFO(INPUTVSC_DRV, + "HID device claimed by input\n"); + } + + if (!hid_dev->claimed) { + DPRINT_ERR(INPUTVSC_DRV, + "HID device not claimed by " + "input or hiddev\n"); + } + + input_device->hid_device = hid_dev; + } + + kfree(hid_dev); +} + static int mousevsc_on_device_add(struct hv_device *device, void *additional_info) { int ret = 0; struct mousevsc_dev *input_dev; struct hv_driver *input_drv; - struct hv_input_dev_info dev_info; input_dev = alloc_input_device(device); if (!input_dev) { ret = -1; - goto Cleanup; + goto cleanup; } input_dev->init_complete = false; @@ -693,13 +744,7 @@ static int mousevsc_on_device_add(struct hv_device *device, input_drv = drv_to_hv_drv(input_dev->device->device.driver); - dev_info.vendor = input_dev->hid_dev_info.vendor; - dev_info.product = input_dev->hid_dev_info.product; - dev_info.version = input_dev->hid_dev_info.version; - strcpy(dev_info.name, "Microsoft Vmbus HID-compliant Mouse"); - /* Send the device info back up */ - deviceinfo_callback(device, &dev_info); /* Send the report desc back up */ /* workaround SA-167 */ @@ -711,7 +756,7 @@ static int mousevsc_on_device_add(struct hv_device *device, input_dev->init_complete = true; -Cleanup: +cleanup: return ret; } @@ -721,7 +766,7 @@ static int mousevsc_on_device_remove(struct hv_device *device) int ret = 0; pr_info("disabling input device (%p)...", - device->ext); + hv_get_drvdata(device)); input_dev = release_input_device(device); @@ -739,7 +784,7 @@ static int mousevsc_on_device_remove(struct hv_device *device) udelay(100); } - pr_info("removing input device (%p)...", device->ext); + pr_info("removing input device (%p)...", hv_get_drvdata(device)); input_dev = final_release_input_device(device); @@ -754,60 +799,11 @@ static int mousevsc_on_device_remove(struct hv_device *device) } -/* - * Data types - */ -struct input_device_context { - struct hv_device *device_ctx; - struct hid_device *hid_device; - struct hv_input_dev_info device_info; - int connected; -}; - - -static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info) -{ - struct input_device_context *input_device_ctx = - dev_get_drvdata(&dev->device); - - memcpy(&input_device_ctx->device_info, info, - sizeof(struct hv_input_dev_info)); - - DPRINT_INFO(INPUTVSC_DRV, "%s", __func__); -} - -static void inputreport_callback(struct hv_device *dev, void *packet, u32 len) -{ - int ret = 0; - - struct input_device_context *input_dev_ctx = - dev_get_drvdata(&dev->device); - - ret = hid_input_report(input_dev_ctx->hid_device, - HID_INPUT_REPORT, packet, len, 1); - - DPRINT_DBG(INPUTVSC_DRV, "hid_input_report (ret %d)", ret); -} - -static int mousevsc_hid_open(struct hid_device *hid) -{ - return 0; -} - -static void mousevsc_hid_close(struct hid_device *hid) -{ -} - -static int mousevsc_probe(struct hv_device *dev) +static int mousevsc_probe(struct hv_device *dev, + const struct hv_vmbus_device_id *dev_id) { int ret = 0; - struct input_device_context *input_dev_ctx; - - input_dev_ctx = kmalloc(sizeof(struct input_device_context), - GFP_KERNEL); - - dev_set_drvdata(&dev->device, input_dev_ctx); /* Call to the vsc driver to add the device */ ret = mousevsc_on_device_add(dev, NULL); @@ -823,18 +819,12 @@ static int mousevsc_probe(struct hv_device *dev) static int mousevsc_remove(struct hv_device *dev) { - int ret = 0; - - struct input_device_context *input_dev_ctx; - - input_dev_ctx = kmalloc(sizeof(struct input_device_context), - GFP_KERNEL); - - dev_set_drvdata(&dev->device, input_dev_ctx); + struct mousevsc_dev *input_dev = hv_get_drvdata(dev); + int ret; - if (input_dev_ctx->connected) { - hidinput_disconnect(input_dev_ctx->hid_device); - input_dev_ctx->connected = 0; + if (input_dev->connected) { + hidinput_disconnect(input_dev->hid_device); + input_dev->connected = 0; } /* @@ -842,70 +832,14 @@ static int mousevsc_remove(struct hv_device *dev) * is being removed */ ret = mousevsc_on_device_remove(dev); - if (ret != 0) { DPRINT_ERR(INPUTVSC_DRV, "unable to remove vsc device (ret %d)", ret); } - kfree(input_dev_ctx); - return ret; } -static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) -{ - struct input_device_context *input_device_ctx = - dev_get_drvdata(&dev->device); - struct hid_device *hid_dev; - - /* hid_debug = -1; */ - hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL); - - if (hid_parse_report(hid_dev, packet, len)) { - DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report"); - return; - } - - if (hid_dev) { - DPRINT_INFO(INPUTVSC_DRV, "hid_device created"); - - hid_dev->ll_driver->open = mousevsc_hid_open; - hid_dev->ll_driver->close = mousevsc_hid_close; - - hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_device_ctx->device_info.vendor; - hid_dev->product = input_device_ctx->device_info.product; - hid_dev->version = input_device_ctx->device_info.version; - hid_dev->dev = dev->device; - - sprintf(hid_dev->name, "%s", - input_device_ctx->device_info.name); - - /* - * HJ Do we want to call it with a 0 - */ - if (!hidinput_connect(hid_dev, 0)) { - hid_dev->claimed |= HID_CLAIMED_INPUT; - - input_device_ctx->connected = 1; - - DPRINT_INFO(INPUTVSC_DRV, - "HID device claimed by input\n"); - } - - if (!hid_dev->claimed) { - DPRINT_ERR(INPUTVSC_DRV, - "HID device not claimed by " - "input or hiddev\n"); - } - - input_device_ctx->hid_device = hid_dev; - } - - kfree(hid_dev); -} - static const struct hv_vmbus_device_id id_table[] = { /* Mouse guid */ { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, @@ -935,26 +869,6 @@ static void __exit mousevsc_exit(void) vmbus_driver_unregister(&mousevsc_drv); } -/* - * We don't want to automatically load this driver just yet, it's quite - * broken. It's safe if you want to load it yourself manually, but - * don't inflict it on unsuspecting users, that's just mean. - */ -#if 0 - -/* - * We use a PCI table to determine if we should autoload this driver This is - * needed by distro tools to determine if the hyperv drivers should be - * installed and/or configured. We don't do anything else with the table, but - * it needs to be present. - */ -static const struct pci_device_id microsoft_hv_pci_table[] = { - { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); -#endif - MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); module_init(mousevsc_init);