Staging: hv: hv_mouse: unwind the initialization process a bit
[pandora-kernel.git] / drivers / staging / hv / hv_mouse.c
index fb3299a..5fc14a2 100644 (file)
@@ -1,27 +1,16 @@
 /*
- *  Copyright 2009 Citrix Systems, Inc.
+ *  Copyright (c) 2009, Citrix Systems, Inc.
+ *  Copyright (c) 2010, Microsoft Corporation.
+ *  Copyright (c) 2011, Novell Inc.
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *  For clarity, the licensor of this program does not intend that a
- *  "derivative work" include code which compiles header information from
- *  this program.
- *
- *  This code has been modified from its original by
- *  Hank Janssen <hjanssen@microsoft.com>
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
  *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
  */
 #include <linux/init.h>
 #include <linux/module.h>
 #include "version_info.h"
 #include "vmbus.h"
 #include "vmbus_api.h"
-#include "mousevsc_api.h"
 #include "channel.h"
 #include "vmbus_packet_format.h"
-#include "vmbus_hid_protocol.h"
+
+
+/*
+ * Data types
+ */
+struct input_dev_info {
+       unsigned short VendorID;
+       unsigned short ProductID;
+       unsigned short VersionNumber;
+       char           Name[128];
+};
+
+/* Represents the input vsc driver */
+struct mousevsc_drv_obj {
+       struct hv_driver Base; // Must be the first field
+       /*
+        * This is set by the caller to allow us to callback when
+        * we receive a packet from the "wire"
+        */
+       void (*OnDeviceInfo)(struct hv_device *dev,
+                            struct input_dev_info* info);
+       void (*OnInputReport)(struct hv_device *dev, void* packet, u32 len);
+       void (*OnReportDescriptor)(struct hv_device *dev,
+                                  void* packet, u32 len);
+       /* Specific to this driver */
+       int (*OnOpen)(struct hv_device *Device);
+       int (*OnClose)(struct hv_device *Device);
+       void *Context;
+};
+
+
+/* The maximum size of a synthetic input message. */
+#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
+
+/*
+ * Current version
+ *
+ * History:
+ * Beta, RC < 2008/1/22        1,0
+ * RC > 2008/1/22              2,0
+ */
+#define SYNTHHID_INPUT_VERSION_MAJOR 2
+#define SYNTHHID_INPUT_VERSION_MINOR 0
+#define SYNTHHID_INPUT_VERSION_DWORD (SYNTHHID_INPUT_VERSION_MINOR | \
+    (SYNTHHID_INPUT_VERSION_MAJOR << 16))
+
+
+#pragma pack(push,1)
+/*
+ * Message types in the synthetic input protocol
+ */
+enum synthhid_msg_type {
+       SynthHidProtocolRequest,
+       SynthHidProtocolResponse,
+       SynthHidInitialDeviceInfo,
+       SynthHidInitialDeviceInfoAck,
+       SynthHidInputReport,
+       SynthHidMax
+};
+
+/*
+ * Basic message structures.
+ */
+struct synthhid_msg_hdr {
+       enum synthhid_msg_type  Type;    /* Type of the enclosed message */
+       u32                     Size;    /* Size of the enclosed message
+                                         *  (size of the data payload)
+                                         */
+};
+
+struct synthhid_msg {
+       struct synthhid_msg_hdr Header;
+       char                    Data[1]; /* Enclosed message */
+};
+
+union synthhid_version {
+       struct {
+               u16  Minor;
+               u16  Major;
+       };
+
+       u32 AsDWord;
+};
+
+/*
+ * Protocol messages
+ */
+struct synthhid_protocol_request {
+       struct synthhid_msg_hdr Header;
+       union synthhid_version VersionRequested;
+};
+
+struct synthhid_protocol_response {
+       struct synthhid_msg_hdr Header;
+       union synthhid_version VersionRequested;
+       unsigned char Approved;
+};
+
+struct synthhid_device_info {
+       struct synthhid_msg_hdr     Header;
+       struct input_dev_info       HidDeviceAttributes;
+       unsigned char               HidDescriptorInformation[1];
+};
+
+struct synthhid_device_info_ack {
+       struct synthhid_msg_hdr Header;
+       unsigned char           Reserved;
+};
+
+struct synthhid_input_report {
+       struct synthhid_msg_hdr Header;
+       char                    ReportBuffer[1];
+};
+
+#pragma pack(pop)
+
+#define INPUTVSC_SEND_RING_BUFFER_SIZE         10*PAGE_SIZE
+#define INPUTVSC_RECV_RING_BUFFER_SIZE         10*PAGE_SIZE
 
 #define NBITS(x) (((x)/BITS_PER_LONG)+1)
 
@@ -67,9 +172,9 @@ struct  mousevsc_prt_msg {
        enum pipe_prot_msg_type   PacketType;
        u32                  DataSize;
        union {
-               SYNTHHID_PROTOCOL_REQUEST       Request;
-               SYNTHHID_PROTOCOL_RESPONSE      Response;
-               SYNTHHID_DEVICE_INFO_ACK        Ack;
+               struct synthhid_protocol_request Request;
+               struct synthhid_protocol_response Response;
+               struct synthhid_device_info_ack Ack;
        } u;
 };
 
@@ -237,16 +342,7 @@ static inline struct mousevsc_dev *FinalReleaseInputDevice(struct hv_device *Dev
        return inputDevice;
 }
 
-/*
- *
- * Name:
- *     MousevscInitialize()
- *
- * Description:
- *     Main entry point
- *
- */
-int mouse_vsc_initialize(struct hv_driver *Driver)
+static int mouse_vsc_initialize(struct hv_driver *Driver)
 {
        struct mousevsc_drv_obj *inputDriver =
                (struct mousevsc_drv_obj *)Driver;
@@ -368,24 +464,24 @@ MousevscConnectToVsp(struct hv_device *Device)
        memset(request, sizeof(struct mousevsc_prt_msg), 0);
 
        request->PacketType = PipeMessageData;
-       request->DataSize = sizeof(SYNTHHID_PROTOCOL_REQUEST);
+       request->DataSize = sizeof(struct synthhid_protocol_request);
 
        request->u.Request.Header.Type = SynthHidProtocolRequest;
        request->u.Request.Header.Size = sizeof(unsigned long);
        request->u.Request.VersionRequested.AsDWord =
                SYNTHHID_INPUT_VERSION_DWORD;
 
-       pr_info("SYNTHHID_PROTOCOL_REQUEST...");
+       pr_info("synthhid protocol request...");
 
        ret = vmbus_sendpacket(Device->channel, request,
                                        sizeof(struct pipe_prt_msg) -
                                        sizeof(unsigned char) +
-                                       sizeof(SYNTHHID_PROTOCOL_REQUEST),
+                                       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");
+               pr_err("unable to send synthhid protocol request.");
                goto Cleanup;
        }
 
@@ -399,7 +495,7 @@ MousevscConnectToVsp(struct hv_device *Device)
        response = &inputDevice->ProtocolResp;
 
        if (!response->u.Response.Approved) {
-               pr_err("SYNTHHID_PROTOCOL_REQUEST failed (version %d)",
+               pr_err("synthhid protocol request failed (version %d)",
                       SYNTHHID_INPUT_VERSION_DWORD);
                ret = -1;
                goto Cleanup;
@@ -515,7 +611,7 @@ MousevscOnSendCompletion(struct hv_device *Device,
 void
 MousevscOnReceiveDeviceInfo(
        struct mousevsc_dev *InputDevice,
-       SYNTHHID_DEVICE_INFO *DeviceInfo)
+       struct synthhid_device_info *DeviceInfo)
 {
        int ret = 0;
        struct hid_descriptor *desc;
@@ -559,7 +655,7 @@ MousevscOnReceiveDeviceInfo(
        memset(&ack, sizeof(struct mousevsc_prt_msg), 0);
 
        ack.PacketType = PipeMessageData;
-       ack.DataSize = sizeof(SYNTHHID_DEVICE_INFO_ACK);
+       ack.DataSize = sizeof(struct synthhid_device_info_ack);
 
        ack.u.Ack.Header.Type = SynthHidInitialDeviceInfoAck;
        ack.u.Ack.Header.Size = 1;
@@ -567,12 +663,13 @@ MousevscOnReceiveDeviceInfo(
 
        ret = vmbus_sendpacket(InputDevice->Device->channel,
                        &ack,
-                       sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + sizeof(SYNTHHID_DEVICE_INFO_ACK),
+                       sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
+                       sizeof(struct synthhid_device_info_ack),
                        (unsigned long)&ack,
                        VM_PKT_DATA_INBAND,
                        VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
        if (ret != 0) {
-               pr_err("unable to send SYNTHHID_DEVICE_INFO_ACK - ret %d",
+               pr_err("unable to send synthhid device info ack - ret %d",
                           ret);
                goto Cleanup;
        }
@@ -602,7 +699,7 @@ Cleanup:
 void
 MousevscOnReceiveInputReport(
        struct mousevsc_dev *InputDevice,
-       SYNTHHID_INPUT_REPORT *InputReport)
+       struct synthhid_input_report *InputReport)
 {
        struct mousevsc_drv_obj *inputDriver;
 
@@ -622,7 +719,7 @@ void
 MousevscOnReceive(struct hv_device *Device, struct vmpacket_descriptor *Packet)
 {
        struct pipe_prt_msg *pipeMsg;
-       SYNTHHID_MESSAGE *hidMsg;
+       struct synthhid_msg *hidMsg;
        struct mousevsc_dev *inputDevice;
 
        inputDevice = MustGetInputDevice(Device);
@@ -640,7 +737,7 @@ MousevscOnReceive(struct hv_device *Device, struct vmpacket_descriptor *Packet)
                return ;
        }
 
-       hidMsg = (SYNTHHID_MESSAGE *)&pipeMsg->Data[0];
+       hidMsg = (struct synthhid_msg *)&pipeMsg->Data[0];
 
        switch (hidMsg->Header.Type) {
        case SynthHidProtocolResponse:
@@ -657,11 +754,11 @@ MousevscOnReceive(struct hv_device *Device, struct vmpacket_descriptor *Packet)
                 * hid desc and report desc
                 */
                MousevscOnReceiveDeviceInfo(inputDevice,
-                                           (SYNTHHID_DEVICE_INFO *)&pipeMsg->Data[0]);
+                                           (struct synthhid_device_info *)&pipeMsg->Data[0]);
                break;
        case SynthHidInputReport:
                MousevscOnReceiveInputReport(inputDevice,
-                                            (SYNTHHID_INPUT_REPORT *)&pipeMsg->Data[0]);
+                                            (struct synthhid_input_report *)&pipeMsg->Data[0]);
 
                break;
        default:
@@ -943,39 +1040,6 @@ void mousevsc_reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
        kfree(hid_dev);
 }
 
-/*
- *
- * Name:       mousevsc_drv_init()
- *
- * Desc:       Driver initialization.
- */
-int mousevsc_drv_init(int (*pfn_drv_init)(struct hv_driver *pfn_drv_init))
-{
-       int ret = 0;
-       struct mousevsc_drv_obj *input_drv_obj = &g_mousevsc_drv.drv_obj;
-       struct driver_context *drv_ctx = &g_mousevsc_drv.drv_ctx;
-
-       input_drv_obj->OnDeviceInfo = mousevsc_deviceinfo_callback;
-       input_drv_obj->OnInputReport = mousevsc_inputreport_callback;
-       input_drv_obj->OnReportDescriptor = mousevsc_reportdesc_callback;
-
-       /* Callback to client driver to complete the initialization */
-       pfn_drv_init(&input_drv_obj->Base);
-
-       drv_ctx->driver.name = input_drv_obj->Base.name;
-       memcpy(&drv_ctx->class_id, &input_drv_obj->Base.dev_type,
-              sizeof(struct hv_guid));
-
-       drv_ctx->probe = mousevsc_probe;
-       drv_ctx->remove = mousevsc_remove;
-
-       /* The driver belongs to vmbus */
-       vmbus_child_driver_register(drv_ctx);
-
-       return ret;
-}
-
-
 int mousevsc_drv_exit_cb(struct device *dev, void *data)
 {
        struct device **curr = (struct device **)data;
@@ -1019,13 +1083,29 @@ void mousevsc_drv_exit(void)
 
 static int __init mousevsc_init(void)
 {
-       int ret;
+       struct mousevsc_drv_obj *input_drv_obj = &g_mousevsc_drv.drv_obj;
+       struct driver_context *drv_ctx = &g_mousevsc_drv.drv_ctx;
 
        DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing.");
 
-       ret = mousevsc_drv_init(mouse_vsc_initialize);
+       input_drv_obj->OnDeviceInfo = mousevsc_deviceinfo_callback;
+       input_drv_obj->OnInputReport = mousevsc_inputreport_callback;
+       input_drv_obj->OnReportDescriptor = mousevsc_reportdesc_callback;
 
-       return ret;
+       /* Callback to client driver to complete the initialization */
+       mouse_vsc_initialize(&input_drv_obj->Base);
+
+       drv_ctx->driver.name = input_drv_obj->Base.name;
+       memcpy(&drv_ctx->class_id, &input_drv_obj->Base.dev_type,
+              sizeof(struct hv_guid));
+
+       drv_ctx->probe = mousevsc_probe;
+       drv_ctx->remove = mousevsc_remove;
+
+       /* The driver belongs to vmbus */
+       vmbus_child_driver_register(drv_ctx);
+
+       return 0;
 }
 
 static void __exit mousevsc_exit(void)