/*
- * 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)
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;
};
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;
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;
}
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;
void
MousevscOnReceiveDeviceInfo(
struct mousevsc_dev *InputDevice,
- SYNTHHID_DEVICE_INFO *DeviceInfo)
+ struct synthhid_device_info *DeviceInfo)
{
int ret = 0;
struct hid_descriptor *desc;
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;
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;
}
void
MousevscOnReceiveInputReport(
struct mousevsc_dev *InputDevice,
- SYNTHHID_INPUT_REPORT *InputReport)
+ struct synthhid_input_report *InputReport)
{
struct mousevsc_drv_obj *inputDriver;
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);
return ;
}
- hidMsg = (SYNTHHID_MESSAGE *)&pipeMsg->Data[0];
+ hidMsg = (struct synthhid_msg *)&pipeMsg->Data[0];
switch (hidMsg->Header.Type) {
case SynthHidProtocolResponse:
* 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:
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;
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)