staging: unisys: visorhid: rename to visorinput
authorTim Sell <Timothy.Sell@unisys.com>
Fri, 2 Oct 2015 17:19:15 +0000 (13:19 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 4 Oct 2015 08:53:34 +0000 (09:53 +0100)
This visorhid driver provides a Human Interface Device, but is not at all
using HID, the protocol.  It's a plain input driver, so for clarity, it is
being renamed to visorinput.

Signed-off-by: Tim Sell <Timothy.Sell@unisys.com>
Signed-off-by: Benjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
15 files changed:
drivers/staging/unisys/Documentation/overview.txt
drivers/staging/unisys/Kconfig
drivers/staging/unisys/Makefile
drivers/staging/unisys/visorhid/Kconfig [deleted file]
drivers/staging/unisys/visorhid/Makefile [deleted file]
drivers/staging/unisys/visorhid/keyboardchannel.h [deleted file]
drivers/staging/unisys/visorhid/mousechannel.h [deleted file]
drivers/staging/unisys/visorhid/ultrainputreport.h [deleted file]
drivers/staging/unisys/visorhid/visorhid.c [deleted file]
drivers/staging/unisys/visorinput/Kconfig [new file with mode: 0644]
drivers/staging/unisys/visorinput/Makefile [new file with mode: 0644]
drivers/staging/unisys/visorinput/keyboardchannel.h [new file with mode: 0644]
drivers/staging/unisys/visorinput/mousechannel.h [new file with mode: 0644]
drivers/staging/unisys/visorinput/ultrainputreport.h [new file with mode: 0644]
drivers/staging/unisys/visorinput/visorinput.c [new file with mode: 0644]

index 25f93f2a1e33daa41e5297d588c8ba66db6d73a4..c2d8dd4a2e41a8ac1040acb1b090a66ff3305c75 100644 (file)
@@ -12,7 +12,7 @@ normally be unsharable, specifically:
 
 * visornic - network interface
 * visorhba - scsi disk adapter
-* visorhid - keyboard and mouse
+* visorinput - keyboard and mouse
 
 These drivers conform to the standard Linux bus/device model described
 within Documentation/driver-model/, and utilize a driver named visorbus to
@@ -44,7 +44,7 @@ NOT covered in this document:
 * Because the s-Par back-end provides a standard EFI framebuffer to each
   guest, the already-existing efifb Linux driver is used to provide guest
   video access. Thus, the only s-Par-unique support that is necessary to
-  provide a guest graphics console are for keyboard and mouse (via visorhid).
+  provide a guest graphics console are for keyboard and mouse (via visorinput).
 
 
 2. Driver Descriptions
@@ -296,13 +296,13 @@ i.e.:
     alias visorbus:8cd5994d-c58e-11da-95a9-00e08161165f visornic
 
 
-2.4. visorhid
--------------
+2.4. visorinput
+---------------
 
-The visorhid driver registers with visorbus as the function driver to
+The visorinput driver registers with visorbus as the function driver to
 handle human input devices, specified using the
 SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID and SPAR_MOUSE_CHANNEL_PROTOCOL_UUID
-types in the visorbus_register_visor_driver() call. visorhid uses
+types in the visorbus_register_visor_driver() call. visorinput uses
 input_register_device() to expose devices of class input
 (e.g., /sys/class/input/) for virtual keyboard and virtual mouse devices.
 A s-Par virtual keyboard device maps 1-to-1 with a Linux input device
@@ -312,7 +312,7 @@ devices created for it: 1 named "visor Wheel", and 1 named "visor Mouse".
 By registering as input class devices, modern versions of X will
 automatically find and properly use s-Par virtual keyboard and mouse devices.
 As the s-Par back-end reports keyboard and mouse activity via events on the
-virtual device channel, the visorhid driver delivers the activity to the
+virtual device channel, the visorinput driver delivers the activity to the
 Linux environment by calling input_report_key() and input_report_abs().
 
 You can interact with the guest console using the usyscon Partition Desktop
@@ -322,7 +322,7 @@ usyscon_partitiondesktop-*.rpm, or into a Windows environment via
 PartitionDesktop.msi, you will be able to launch a console for your guest
 Linux environment by clicking the console icon in the s-Par web UI.
 
-When compiled as a module, visorhid can be autoloaded by visorbus in
+When compiled as a module, visorinput can be autoloaded by visorbus in
 standard udev/systemd environments, as it includes the modules.alias
 definition:
 
@@ -331,8 +331,8 @@ definition:
 
 i.e.:
 
-    alias visorbus:c73416d0-b0b8-44af-b304-9d2ae99f1b3d visorhid
-    alias visorbus:addf07d4-94a9-46e2-81c3-61abcdbdbd87 visorhid
+    alias visorbus:c73416d0-b0b8-44af-b304-9d2ae99f1b3d visorinput
+    alias visorbus:addf07d4-94a9-46e2-81c3-61abcdbdbd87 visorinput
 
 
 3. Minimum Required Driver Set
@@ -352,5 +352,5 @@ the s-Par back-end, which is the default configuration.  However, for
 configurations where the Linux guest is provided with an SR-IOV NIC
 for example, visornic is not technically required.
 
-visorhid is only required for a Linux guest running under s-Par if you
+visorinput is only required for a Linux guest running under s-Par if you
 require graphics-mode access to your guest console.
index 5cbb791053ed2b03a36e600fe4426cbed1969949..4f1f5e624604dc00ee0f29f1d298d31b6a47b361 100644 (file)
@@ -13,7 +13,7 @@ if UNISYSSPAR
 
 source "drivers/staging/unisys/visorbus/Kconfig"
 source "drivers/staging/unisys/visornic/Kconfig"
-source "drivers/staging/unisys/visorhid/Kconfig"
+source "drivers/staging/unisys/visorinput/Kconfig"
 source "drivers/staging/unisys/visorhba/Kconfig"
 
 endif # UNISYSSPAR
index 79c9036edb5c1a4385793fcacd54466c8b9fd578..20eb098538d3fa9c3498c7e4df70232c994cf679 100644 (file)
@@ -3,5 +3,5 @@
 #
 obj-$(CONFIG_UNISYS_VISORBUS)          += visorbus/
 obj-$(CONFIG_UNISYS_VISORNIC)          += visornic/
-obj-$(CONFIG_UNISYS_VISORHID)          += visorhid/
+obj-$(CONFIG_UNISYS_VISORINPUT)                += visorinput/
 obj-$(CONFIG_UNISYS_VISORHBA)          += visorhba/
diff --git a/drivers/staging/unisys/visorhid/Kconfig b/drivers/staging/unisys/visorhid/Kconfig
deleted file mode 100644 (file)
index 3b83e2c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Unisys visorhid configuration
-#
-
-config UNISYS_VISORHID
-       tristate "Unisys visorhid driver"
-       depends on UNISYSSPAR && UNISYS_VISORBUS && FB
-       ---help---
-       If you say Y here, you will enable the Unisys visorhid driver.
-
diff --git a/drivers/staging/unisys/visorhid/Makefile b/drivers/staging/unisys/visorhid/Makefile
deleted file mode 100644 (file)
index e457bd1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for Unisys visorhid
-#
-
-obj-$(CONFIG_UNISYS_VISORHID)  += visorhid.o
-
-ccflags-y += -Idrivers/staging/unisys/include
diff --git a/drivers/staging/unisys/visorhid/keyboardchannel.h b/drivers/staging/unisys/visorhid/keyboardchannel.h
deleted file mode 100644 (file)
index 2ed2602..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * 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 that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __SPAR_KEYBOARDCHANNEL_H__
-#define __SPAR_KEYBOARDCHANNEL_H__
-
-#include <linux/kernel.h>
-#include <linux/uuid.h>
-
-#include "channel.h"
-#include "ultrainputreport.h"
-
-/* {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */
-#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID                            \
-       UUID_LE(0xc73416d0, 0xb0b8, 0x44af,                             \
-               0xb3, 0x4, 0x9d, 0x2a, 0xe9, 0x9f, 0x1b, 0x3d)
-#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR "c73416d0-b0b8-44af-b304-9d2ae99f1b3d"
-#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_VERSIONID 1
-#define KEYBOARD_MAXINPUTREPORTS 50
-
-#endif
diff --git a/drivers/staging/unisys/visorhid/mousechannel.h b/drivers/staging/unisys/visorhid/mousechannel.h
deleted file mode 100644 (file)
index 256477a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * 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 that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __SPAR_MOUSECHANNEL_H__
-#define __SPAR_MOUSECHANNEL_H__
-
-#include <linux/kernel.h>
-#include <linux/uuid.h>
-
-#include "channel.h"
-#include "ultrainputreport.h"
-
-/* {addf07d4-94a9-46e2-81c3-61abcdbdbd87} */
-#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID  \
-       UUID_LE(0xaddf07d4, 0x94a9, 0x46e2, \
-               0x81, 0xc3, 0x61, 0xab, 0xcd, 0xbd, 0xbd, 0x87)
-#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR \
-       "addf07d4-94a9-46e2-81c3-61abcdbdbd87"
-#define SPAR_MOUSE_CHANNEL_PROTOCOL_VERSIONID 1
-#define MOUSE_MAXINPUTREPORTS 50
-
-#endif
diff --git a/drivers/staging/unisys/visorhid/ultrainputreport.h b/drivers/staging/unisys/visorhid/ultrainputreport.h
deleted file mode 100644 (file)
index 3e6a52f..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * 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 that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#ifndef __SPAR_ULTRAINPUTREPORT_H__
-#define __SPAR_ULTRAINPUTREPORT_H__
-
-#include <linux/types.h>
-
-#include "ultrainputreport.h"
-
-/* Identifies mouse and keyboard activity which is specified by the firmware to
- *  the host using the cmsimpleinput protocol.  @ingroup coretypes
- */
-enum ultra_inputaction {
-       inputaction_none = 0,
-       inputaction_xy_motion = 1,      /* only motion; arg1=x, arg2=y */
-       inputaction_mouse_button_down = 2, /* arg1: 1=left,2=center,3=right */
-       inputaction_mouse_button_up = 3, /* arg1: 1=left,2=center,3=right */
-       inputaction_mouse_button_click = 4, /* arg1: 1=left,2=center,3=right */
-       inputaction_mouse_button_dclick = 5, /* arg1: 1=left,2=center,
-                                               3=right */
-       inputaction_wheel_rotate_away = 6, /* arg1: wheel rotation away from
-                                             user */
-       inputaction_wheel_rotate_toward = 7, /* arg1: wheel rotation toward
-                                               user */
-       inputaction_set_max_xy = 8,     /* set screen maxXY; arg1=x, arg2=y */
-       inputaction_key_down = 64,      /* arg1: scancode, as follows:
-                                          If arg1 <= 0xff, it's a 1-byte
-                                          scancode and arg1 is that scancode.
-                                          If arg1 > 0xff, it's a 2-byte
-                                          scanecode, with the 1st byte in the
-                                          low 8 bits, and the 2nd byte in the
-                                          high 8 bits.  E.g., the right ALT key
-                                          would appear as x'38e0'. */
-       inputaction_key_up = 65,        /* arg1: scancode (in same format as
-                                          inputaction_keyDown) */
-       inputaction_set_locking_key_state = 66,
-                                       /* arg1: scancode (in same format
-                                                as inputaction_keyDown);
-                                                MUST refer to one of the
-                                                locking keys, like capslock,
-                                                numlock, or scrolllock
-                                          arg2: 1 iff locking key should be
-                                                in the LOCKED position
-                                                (e.g., light is ON) */
-       inputaction_key_down_up = 67,   /* arg1: scancode (in same format
-                                                as inputaction_keyDown) */
-       inputaction_last
-};
-
-struct ultra_inputactivity {
-       u16 action;
-       u16 arg1;
-       u16 arg2;
-       u16 arg3;
-} __packed;
-
-struct ultra_inputreport {
-       u64 seq_no;
-       struct ultra_inputactivity activity;
-} __packed;
-
-#endif
diff --git a/drivers/staging/unisys/visorhid/visorhid.c b/drivers/staging/unisys/visorhid/visorhid.c
deleted file mode 100644 (file)
index c24aaf5..0000000
+++ /dev/null
@@ -1,671 +0,0 @@
-/* visorhid.c
- *
- * Copyright (C) 2011 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * 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 that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/* This driver lives in a generic guest Linux partition, and registers to
- * receive keyboard and mouse channels from the visorbus driver.  It reads
- * inputs from such channels, and delivers it to the Linux OS in the
- * standard way the Linux expects for input drivers.
- */
-
-#include <linux/buffer_head.h>
-#include <linux/fb.h>
-#include <linux/fs.h>
-#include <linux/input.h>
-#include <linux/uaccess.h>
-
-#include "keyboardchannel.h"
-#include "mousechannel.h"
-#include "version.h"
-#include "visorbus.h"
-
-#define PIXELS_ACROSS_DEFAULT  800
-#define PIXELS_DOWN_DEFAULT    600
-
-static const uuid_le spar_keyboard_channel_protocol_uuid =
-       SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID;
-static const uuid_le spar_mouse_channel_protocol_uuid =
-       SPAR_MOUSE_CHANNEL_PROTOCOL_UUID;
-static int visorhid_probe(struct visor_device *dev);
-static void visorhid_remove(struct visor_device *dev);
-static void visorhid_channel_interrupt(struct visor_device *dev);
-static int visorhid_pause(struct visor_device *dev,
-                         visorbus_state_complete_func complete_func);
-static int visorhid_resume(struct visor_device *dev,
-                          visorbus_state_complete_func complete_func);
-static struct input_dev *register_client_keyboard(void);
-static struct input_dev *register_client_mouse(void);
-static void unregister_client_input(struct input_dev *visorinput_dev);
-
-/* GUIDS for all channel types supported by this driver. */
-static struct visor_channeltype_descriptor visorhid_channel_types[] = {
-       { SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID, "keyboard"},
-       { SPAR_MOUSE_CHANNEL_PROTOCOL_UUID, "mouse"},
-       { NULL_UUID_LE, NULL }
-};
-MODULE_DEVICE_TABLE(visorbus, visorhid_channel_types);
-MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR);
-MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR);
-
-/** This is used to tell the visor bus driver which types of visor devices
- *  we support, and what functions to call when a visor device that we support
- *  is attached or removed.
- */
-static struct visor_driver visorhid_driver = {
-       .name = "visorhid",
-       .vertag = NULL,
-       .owner = THIS_MODULE,
-       .channel_types = visorhid_channel_types,
-       .probe = visorhid_probe,
-       .remove = visorhid_remove,
-       .channel_interrupt = visorhid_channel_interrupt,
-       .pause = visorhid_pause,
-       .resume = visorhid_resume,
-};
-
-enum visorhid_device_type {
-       visorhid_keyboard,
-       visorhid_mouse,
-};
-
-/*  This is the private data that we store for each device.
- *  A pointer to this struct is maintained via
- *  dev_get_drvdata() / dev_set_drvdata() for each struct device.
- */
-struct visorhid_devdata {
-       struct visor_device *dev;
-       /** lock for dev */
-       struct rw_semaphore lock_visor_dev;
-       struct input_dev *visorinput_dev;
-       bool paused;
-};
-
-/* Borrowed from drivers/input/keyboard/atakbd.c */
-/* This maps 1-byte scancodes to keycodes. */
-static unsigned char visorkbd_keycode[256] = { /* American layout */
-       [0] = KEY_GRAVE,
-       [1] = KEY_ESC,
-       [2] = KEY_1,
-       [3] = KEY_2,
-       [4] = KEY_3,
-       [5] = KEY_4,
-       [6] = KEY_5,
-       [7] = KEY_6,
-       [8] = KEY_7,
-       [9] = KEY_8,
-       [10] = KEY_9,
-       [11] = KEY_0,
-       [12] = KEY_MINUS,
-       [13] = KEY_EQUAL,
-       [14] = KEY_BACKSPACE,
-       [15] = KEY_TAB,
-       [16] = KEY_Q,
-       [17] = KEY_W,
-       [18] = KEY_E,
-       [19] = KEY_R,
-       [20] = KEY_T,
-       [21] = KEY_Y,
-       [22] = KEY_U,
-       [23] = KEY_I,
-       [24] = KEY_O,
-       [25] = KEY_P,
-       [26] = KEY_LEFTBRACE,
-       [27] = KEY_RIGHTBRACE,
-       [28] = KEY_ENTER,
-       [29] = KEY_LEFTCTRL,
-       [30] = KEY_A,
-       [31] = KEY_S,
-       [32] = KEY_D,
-       [33] = KEY_F,
-       [34] = KEY_G,
-       [35] = KEY_H,
-       [36] = KEY_J,
-       [37] = KEY_K,
-       [38] = KEY_L,
-       [39] = KEY_SEMICOLON,
-       [40] = KEY_APOSTROPHE,
-       [41] = KEY_GRAVE,       /* FIXME, '#' */
-       [42] = KEY_LEFTSHIFT,
-       [43] = KEY_BACKSLASH,   /* FIXME, '~' */
-       [44] = KEY_Z,
-       [45] = KEY_X,
-       [46] = KEY_C,
-       [47] = KEY_V,
-       [48] = KEY_B,
-       [49] = KEY_N,
-       [50] = KEY_M,
-       [51] = KEY_COMMA,
-       [52] = KEY_DOT,
-       [53] = KEY_SLASH,
-       [54] = KEY_RIGHTSHIFT,
-       [55] = KEY_KPASTERISK,
-       [56] = KEY_LEFTALT,
-       [57] = KEY_SPACE,
-       [58] = KEY_CAPSLOCK,
-       [59] = KEY_F1,
-       [60] = KEY_F2,
-       [61] = KEY_F3,
-       [62] = KEY_F4,
-       [63] = KEY_F5,
-       [64] = KEY_F6,
-       [65] = KEY_F7,
-       [66] = KEY_F8,
-       [67] = KEY_F9,
-       [68] = KEY_F10,
-       [69] = KEY_NUMLOCK,
-       [70] = KEY_SCROLLLOCK,
-       [71] = KEY_KP7,
-       [72] = KEY_KP8,
-       [73] = KEY_KP9,
-       [74] = KEY_KPMINUS,
-       [75] = KEY_KP4,
-       [76] = KEY_KP5,
-       [77] = KEY_KP6,
-       [78] = KEY_KPPLUS,
-       [79] = KEY_KP1,
-       [80] = KEY_KP2,
-       [81] = KEY_KP3,
-       [82] = KEY_KP0,
-       [83] = KEY_KPDOT,
-       [86] = KEY_102ND, /* enables UK backslash+pipe key,
-                          * and FR lessthan+greaterthan key */
-       [87] = KEY_F11,
-       [88] = KEY_F12,
-       [90] = KEY_KPLEFTPAREN,
-       [91] = KEY_KPRIGHTPAREN,
-       [92] = KEY_KPASTERISK,  /* FIXME */
-       [93] = KEY_KPASTERISK,
-       [94] = KEY_KPPLUS,
-       [95] = KEY_HELP,
-       [96] = KEY_KPENTER,
-       [97] = KEY_RIGHTCTRL,
-       [98] = KEY_KPSLASH,
-       [99] = KEY_KPLEFTPAREN,
-       [100] = KEY_KPRIGHTPAREN,
-       [101] = KEY_KPSLASH,
-       [102] = KEY_HOME,
-       [103] = KEY_UP,
-       [104] = KEY_PAGEUP,
-       [105] = KEY_LEFT,
-       [106] = KEY_RIGHT,
-       [107] = KEY_END,
-       [108] = KEY_DOWN,
-       [109] = KEY_PAGEDOWN,
-       [110] = KEY_INSERT,
-       [111] = KEY_DELETE,
-       [112] = KEY_MACRO,
-       [113] = KEY_MUTE
-};
-
-/* This maps the <xx> in extended scancodes of the form "0xE0 <xx>" into
- * keycodes.
- */
-static unsigned char visorkbd_ext_keycode[256] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x00 */
-       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x10 */
-       0, 0, 0, 0, KEY_KPENTER, KEY_RIGHTCTRL, 0, 0,               /* 0x18 */
-       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x20 */
-       KEY_RIGHTALT, 0, 0, 0, 0, 0, 0, 0,                          /* 0x28 */
-       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x30 */
-       KEY_RIGHTALT /* AltGr */, 0, 0, 0, 0, 0, 0, 0,              /* 0x38 */
-       0, 0, 0, 0, 0, 0, 0, KEY_HOME,                              /* 0x40 */
-       KEY_UP, KEY_PAGEUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END,  /* 0x48 */
-       KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE, 0, 0, 0, 0, /* 0x50 */
-       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x58 */
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x60 */
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x70 */
-};
-
-static struct visorhid_devdata *
-devdata_create(struct visor_device *dev, enum visorhid_device_type devtype)
-{
-       struct visorhid_devdata *devdata = NULL;
-
-       devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
-       if (!devdata)
-               return NULL;
-       devdata->dev = dev;
-
-       /* This is an input device in a client guest partition,
-        * so we need to create whatever gizmos are necessary to
-        * deliver our inputs to the guest OS.
-        */
-       switch (devtype) {
-       case visorhid_keyboard:
-               devdata->visorinput_dev = register_client_keyboard();
-               if (!devdata->visorinput_dev)
-                       goto cleanups_register;
-               break;
-       case visorhid_mouse:
-               devdata->visorinput_dev = register_client_mouse();
-               if (!devdata->visorinput_dev)
-                       goto cleanups_register;
-               break;
-       }
-
-       init_rwsem(&devdata->lock_visor_dev);
-
-       return devdata;
-
-cleanups_register:
-       kfree(devdata);
-       return NULL;
-}
-
-static int
-visorhid_probe(struct visor_device *dev)
-{
-       struct visorhid_devdata *devdata = NULL;
-       uuid_le guid;
-       enum visorhid_device_type devtype;
-
-       guid = visorchannel_get_uuid(dev->visorchannel);
-       if (uuid_le_cmp(guid, spar_mouse_channel_protocol_uuid) == 0)
-               devtype = visorhid_mouse;
-       else if (uuid_le_cmp(guid, spar_keyboard_channel_protocol_uuid) == 0)
-               devtype = visorhid_keyboard;
-       else
-               return -ENODEV;
-       devdata = devdata_create(dev, devtype);
-       if (!devdata)
-               return -ENOMEM;
-       dev_set_drvdata(&dev->device, devdata);
-       visorbus_enable_channel_interrupts(dev);
-       return 0;
-}
-
-static void
-visorhid_remove(struct visor_device *dev)
-{
-       struct visorhid_devdata *devdata = dev_get_drvdata(&dev->device);
-
-       if (!devdata)
-               return;
-
-       visorbus_disable_channel_interrupts(dev);
-
-       /* due to above, at this time no thread of execution will be
-       * in visorhid_channel_interrupt()
-       */
-
-       down_write(&devdata->lock_visor_dev);
-       dev_set_drvdata(&dev->device, NULL);
-       unregister_client_input(devdata->visorinput_dev);
-       up_write(&devdata->lock_visor_dev);
-       kfree(devdata);
-}
-
-static void
-unregister_client_input(struct input_dev *visorinput_dev)
-{
-       if (visorinput_dev)
-               input_unregister_device(visorinput_dev);
-}
-
-/* register_client_keyboard() initializes and returns a Linux gizmo that we
- * can use to deliver keyboard inputs to Linux.  We of course do this when
- * we see keyboard inputs coming in on a keyboard channel.
- */
-static struct input_dev *
-register_client_keyboard(void)
-{
-       int i, error;
-       struct input_dev *visorinput_dev = NULL;
-
-       visorinput_dev = input_allocate_device();
-       if (!visorinput_dev)
-               return NULL;
-
-       visorinput_dev->name = "visor Keyboard";
-       visorinput_dev->phys = "visorkbd:input0";
-       visorinput_dev->id.bustype = BUS_HOST;
-       visorinput_dev->id.vendor = 0x0001;
-       visorinput_dev->id.product = 0x0001;
-       visorinput_dev->id.version = 0x0100;
-
-       visorinput_dev->evbit[0] = BIT_MASK(EV_KEY) |
-                                  BIT_MASK(EV_REP) |
-                                  BIT_MASK(EV_LED);
-       visorinput_dev->ledbit[0] = BIT_MASK(LED_CAPSL) |
-                                   BIT_MASK(LED_SCROLLL) |
-                                   BIT_MASK(LED_NUML);
-       visorinput_dev->keycode = visorkbd_keycode;
-       visorinput_dev->keycodesize = sizeof(unsigned char);
-       visorinput_dev->keycodemax = ARRAY_SIZE(visorkbd_keycode);
-
-       for (i = 1; i < ARRAY_SIZE(visorkbd_keycode); i++)
-               set_bit(visorkbd_keycode[i], visorinput_dev->keybit);
-
-       for (i = 1; i < ARRAY_SIZE(visorkbd_ext_keycode); i++)
-               set_bit(visorkbd_ext_keycode[i], visorinput_dev->keybit);
-
-       error = input_register_device(visorinput_dev);
-       if (error) {
-               input_free_device(visorinput_dev);
-               return NULL;
-       }
-       return visorinput_dev;
-}
-
-static struct input_dev *
-register_client_mouse(void)
-{
-       int error;
-       struct input_dev *visorinput_dev = NULL;
-       int xres, yres;
-       struct fb_info *fb0;
-
-       visorinput_dev = input_allocate_device();
-       if (!visorinput_dev)
-               return NULL;
-
-       visorinput_dev->name = "visor Mouse";
-       visorinput_dev->phys = "visormou:input0";
-       visorinput_dev->id.bustype = BUS_HOST;
-       visorinput_dev->id.vendor = 0x0001;
-       visorinput_dev->id.product = 0x0002;
-       visorinput_dev->id.version = 0x0100;
-
-       visorinput_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       set_bit(BTN_LEFT, visorinput_dev->keybit);
-       set_bit(BTN_RIGHT, visorinput_dev->keybit);
-       set_bit(BTN_MIDDLE, visorinput_dev->keybit);
-
-       if (registered_fb[0]) {
-               fb0 = registered_fb[0];
-               xres = fb0->var.xres_virtual;
-               yres = fb0->var.yres_virtual;
-       } else {
-               xres = PIXELS_ACROSS_DEFAULT;
-               yres = PIXELS_DOWN_DEFAULT;
-       }
-       input_set_abs_params(visorinput_dev, ABS_X, 0, xres, 0, 0);
-       input_set_abs_params(visorinput_dev, ABS_Y, 0, yres, 0, 0);
-
-       error = input_register_device(visorinput_dev);
-       if (error) {
-               input_free_device(visorinput_dev);
-               return NULL;
-       }
-
-       /* Sending top-left and bottom-right positions is ABSOLUTELY
-        * REQUIRED if we want X to move the mouse to the exact points
-        * we tell it.  I have NO IDEA why.
-        */
-       input_report_abs(visorinput_dev, ABS_X, 0);
-       input_report_abs(visorinput_dev, ABS_Y, 0);
-       input_sync(visorinput_dev);
-       input_report_abs(visorinput_dev, ABS_X, xres - 1);
-       input_report_abs(visorinput_dev, ABS_Y, yres - 1);
-       input_sync(visorinput_dev);
-
-       input_set_capability(visorinput_dev, EV_REL, REL_WHEEL);
-
-       return visorinput_dev;
-}
-
-static void
-do_key(struct input_dev *inpt, int keycode, int down)
-{
-       input_report_key(inpt, keycode, down);
-}
-
-/* Make it so the current locking state of the locking key indicated by
- * <keycode> is as indicated by <desired_state> (1=locked, 0=unlocked).
- */
-static void
-handle_locking_key(struct input_dev *visorinput_dev,
-                  int keycode, int desired_state)
-{
-       int led;
-       char *sled;
-
-       switch (keycode) {
-       case KEY_CAPSLOCK:
-               led = LED_CAPSL;
-               sled = "CAP";
-               break;
-       case KEY_SCROLLLOCK:
-               led = LED_SCROLLL;
-               sled = "SCR";
-               break;
-       case KEY_NUMLOCK:
-               led = LED_NUML;
-               sled = "NUM";
-               break;
-       default:
-               led = -1;
-               break;
-       }
-       if (led >= 0) {
-               int old_state = (test_bit(led, visorinput_dev->led) != 0);
-
-               if (old_state != desired_state) {
-                       do_key(visorinput_dev, keycode, 1);
-                       input_sync(visorinput_dev);
-                       do_key(visorinput_dev, keycode, 0);
-                       input_sync(visorinput_dev);
-                       __change_bit(led, visorinput_dev->led);
-               }
-       }
-}
-
-/* <scancode> is either a 1-byte scancode, or an extended 16-bit scancode
- * with 0xE0 in the low byte and the extended scancode value in the next
- * higher byte.
- */
-static int
-scancode_to_keycode(int scancode)
-{
-       int keycode;
-
-       if (scancode > 0xff)
-               keycode = visorkbd_ext_keycode[(scancode >> 8) & 0xff];
-       else
-               keycode = visorkbd_keycode[scancode];
-       return keycode;
-}
-
-static int
-calc_button(int x)
-{
-       switch (x) {
-       case 1:
-               return BTN_LEFT;
-       case 2:
-               return BTN_MIDDLE;
-       case 3:
-               return BTN_RIGHT;
-       default:
-               return -1;
-       }
-}
-
-/* This is used only when this driver is active as an input driver in the
- * client guest partition.  It is called periodically so we can obtain inputs
- * from the channel, and deliver them to the guest OS.
- */
-static void
-visorhid_channel_interrupt(struct visor_device *dev)
-{
-       struct ultra_inputreport r;
-       int scancode, keycode;
-       struct input_dev *visorinput_dev;
-       int xmotion, ymotion, zmotion, button;
-       int i;
-
-       struct visorhid_devdata *devdata = dev_get_drvdata(&dev->device);
-
-       if (!devdata)
-               return;
-
-       down_write(&devdata->lock_visor_dev);
-       if (devdata->paused) /* don't touch device/channel when paused */
-               goto out_locked;
-
-       visorinput_dev = devdata->visorinput_dev;
-       if (!visorinput_dev)
-               goto out_locked;
-
-       while (visorchannel_signalremove(dev->visorchannel, 0, &r)) {
-               scancode = r.activity.arg1;
-               keycode = scancode_to_keycode(scancode);
-               switch (r.activity.action) {
-               case inputaction_key_down:
-                       do_key(visorinput_dev, keycode, 1);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_key_up:
-                       do_key(visorinput_dev, keycode, 0);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_key_down_up:
-                       do_key(visorinput_dev, keycode, 1);
-                       input_sync(visorinput_dev);
-                       do_key(visorinput_dev, keycode, 0);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_set_locking_key_state:
-                       handle_locking_key(visorinput_dev, keycode,
-                                          r.activity.arg2);
-                       break;
-               case inputaction_xy_motion:
-                       xmotion = r.activity.arg1;
-                       ymotion = r.activity.arg2;
-                       input_report_abs(visorinput_dev, ABS_X, xmotion);
-                       input_report_abs(visorinput_dev, ABS_Y, ymotion);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_mouse_button_down:
-                       button = calc_button(r.activity.arg1);
-                       if (button < 0)
-                               break;
-                       input_report_key(visorinput_dev, button, 1);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_mouse_button_up:
-                       button = calc_button(r.activity.arg1);
-                       if (button < 0)
-                               break;
-                       input_report_key(visorinput_dev, button, 0);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_mouse_button_click:
-                       button = calc_button(r.activity.arg1);
-                       if (button < 0)
-                               break;
-                       input_report_key(visorinput_dev, button, 1);
-
-                       input_sync(visorinput_dev);
-                       input_report_key(visorinput_dev, button, 0);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_mouse_button_dclick:
-                       button = calc_button(r.activity.arg1);
-                       if (button < 0)
-                               break;
-                       for (i = 0; i < 2; i++) {
-                               input_report_key(visorinput_dev, button, 1);
-                               input_sync(visorinput_dev);
-                               input_report_key(visorinput_dev, button, 0);
-                               input_sync(visorinput_dev);
-                       }
-                       break;
-               case inputaction_wheel_rotate_away:
-                       zmotion = r.activity.arg1;
-                       input_report_rel(visorinput_dev, REL_WHEEL, 1);
-                       input_sync(visorinput_dev);
-                       break;
-               case inputaction_wheel_rotate_toward:
-                       zmotion = r.activity.arg1;
-                       input_report_rel(visorinput_dev, REL_WHEEL, -1);
-                       input_sync(visorinput_dev);
-                       break;
-               }
-       }
-out_locked:
-       up_write(&devdata->lock_visor_dev);
-}
-
-static int
-visorhid_pause(struct visor_device *dev,
-              visorbus_state_complete_func complete_func)
-{
-       int rc;
-       struct visorhid_devdata *devdata = dev_get_drvdata(&dev->device);
-
-       if (!devdata) {
-               rc = -ENODEV;
-               goto out;
-       }
-
-       down_write(&devdata->lock_visor_dev);
-       if (devdata->paused) {
-               rc = -EBUSY;
-               goto out_locked;
-       }
-       devdata->paused = true;
-       complete_func(dev, 0);
-       rc = 0;
-out_locked:
-       up_write(&devdata->lock_visor_dev);
-out:
-       return rc;
-}
-
-static int
-visorhid_resume(struct visor_device *dev,
-               visorbus_state_complete_func complete_func)
-{
-       int rc;
-       struct visorhid_devdata *devdata = dev_get_drvdata(&dev->device);
-
-       if (!devdata) {
-               rc = -ENODEV;
-               goto out;
-       }
-       down_write(&devdata->lock_visor_dev);
-       if (!devdata->paused) {
-               rc = -EBUSY;
-               goto out_locked;
-       }
-       devdata->paused = false;
-       complete_func(dev, 0);
-       rc = 0;
-out_locked:
-       up_write(&devdata->lock_visor_dev);
-out:
-       return rc;
-}
-
-static int
-visorhid_init(void)
-{
-       return visorbus_register_visor_driver(&visorhid_driver);
-}
-
-static void
-visorhid_cleanup(void)
-{
-       visorbus_unregister_visor_driver(&visorhid_driver);
-}
-
-module_init(visorhid_init);
-module_exit(visorhid_cleanup);
-
-MODULE_AUTHOR("Unisys");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("s-Par human input driver for guest Linux");
-MODULE_VERSION(VERSION);
diff --git a/drivers/staging/unisys/visorinput/Kconfig b/drivers/staging/unisys/visorinput/Kconfig
new file mode 100644 (file)
index 0000000..d83deb4
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Unisys visorinput configuration
+#
+
+config UNISYS_VISORINPUT
+       tristate "Unisys visorinput driver"
+       depends on UNISYSSPAR && UNISYS_VISORBUS && FB
+       ---help---
+       If you say Y here, you will enable the Unisys visorinput driver.
+
diff --git a/drivers/staging/unisys/visorinput/Makefile b/drivers/staging/unisys/visorinput/Makefile
new file mode 100644 (file)
index 0000000..beedca7
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for Unisys visorinput
+#
+
+obj-$(CONFIG_UNISYS_VISORINPUT)        += visorinput.o
+
+ccflags-y += -Idrivers/staging/unisys/include
diff --git a/drivers/staging/unisys/visorinput/keyboardchannel.h b/drivers/staging/unisys/visorinput/keyboardchannel.h
new file mode 100644 (file)
index 0000000..2ed2602
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * 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 that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __SPAR_KEYBOARDCHANNEL_H__
+#define __SPAR_KEYBOARDCHANNEL_H__
+
+#include <linux/kernel.h>
+#include <linux/uuid.h>
+
+#include "channel.h"
+#include "ultrainputreport.h"
+
+/* {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */
+#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID                            \
+       UUID_LE(0xc73416d0, 0xb0b8, 0x44af,                             \
+               0xb3, 0x4, 0x9d, 0x2a, 0xe9, 0x9f, 0x1b, 0x3d)
+#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR "c73416d0-b0b8-44af-b304-9d2ae99f1b3d"
+#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_VERSIONID 1
+#define KEYBOARD_MAXINPUTREPORTS 50
+
+#endif
diff --git a/drivers/staging/unisys/visorinput/mousechannel.h b/drivers/staging/unisys/visorinput/mousechannel.h
new file mode 100644 (file)
index 0000000..256477a
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * 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 that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __SPAR_MOUSECHANNEL_H__
+#define __SPAR_MOUSECHANNEL_H__
+
+#include <linux/kernel.h>
+#include <linux/uuid.h>
+
+#include "channel.h"
+#include "ultrainputreport.h"
+
+/* {addf07d4-94a9-46e2-81c3-61abcdbdbd87} */
+#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID  \
+       UUID_LE(0xaddf07d4, 0x94a9, 0x46e2, \
+               0x81, 0xc3, 0x61, 0xab, 0xcd, 0xbd, 0xbd, 0x87)
+#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR \
+       "addf07d4-94a9-46e2-81c3-61abcdbdbd87"
+#define SPAR_MOUSE_CHANNEL_PROTOCOL_VERSIONID 1
+#define MOUSE_MAXINPUTREPORTS 50
+
+#endif
diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h
new file mode 100644 (file)
index 0000000..3e6a52f
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * 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 that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __SPAR_ULTRAINPUTREPORT_H__
+#define __SPAR_ULTRAINPUTREPORT_H__
+
+#include <linux/types.h>
+
+#include "ultrainputreport.h"
+
+/* Identifies mouse and keyboard activity which is specified by the firmware to
+ *  the host using the cmsimpleinput protocol.  @ingroup coretypes
+ */
+enum ultra_inputaction {
+       inputaction_none = 0,
+       inputaction_xy_motion = 1,      /* only motion; arg1=x, arg2=y */
+       inputaction_mouse_button_down = 2, /* arg1: 1=left,2=center,3=right */
+       inputaction_mouse_button_up = 3, /* arg1: 1=left,2=center,3=right */
+       inputaction_mouse_button_click = 4, /* arg1: 1=left,2=center,3=right */
+       inputaction_mouse_button_dclick = 5, /* arg1: 1=left,2=center,
+                                               3=right */
+       inputaction_wheel_rotate_away = 6, /* arg1: wheel rotation away from
+                                             user */
+       inputaction_wheel_rotate_toward = 7, /* arg1: wheel rotation toward
+                                               user */
+       inputaction_set_max_xy = 8,     /* set screen maxXY; arg1=x, arg2=y */
+       inputaction_key_down = 64,      /* arg1: scancode, as follows:
+                                          If arg1 <= 0xff, it's a 1-byte
+                                          scancode and arg1 is that scancode.
+                                          If arg1 > 0xff, it's a 2-byte
+                                          scanecode, with the 1st byte in the
+                                          low 8 bits, and the 2nd byte in the
+                                          high 8 bits.  E.g., the right ALT key
+                                          would appear as x'38e0'. */
+       inputaction_key_up = 65,        /* arg1: scancode (in same format as
+                                          inputaction_keyDown) */
+       inputaction_set_locking_key_state = 66,
+                                       /* arg1: scancode (in same format
+                                                as inputaction_keyDown);
+                                                MUST refer to one of the
+                                                locking keys, like capslock,
+                                                numlock, or scrolllock
+                                          arg2: 1 iff locking key should be
+                                                in the LOCKED position
+                                                (e.g., light is ON) */
+       inputaction_key_down_up = 67,   /* arg1: scancode (in same format
+                                                as inputaction_keyDown) */
+       inputaction_last
+};
+
+struct ultra_inputactivity {
+       u16 action;
+       u16 arg1;
+       u16 arg2;
+       u16 arg3;
+} __packed;
+
+struct ultra_inputreport {
+       u64 seq_no;
+       struct ultra_inputactivity activity;
+} __packed;
+
+#endif
diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c
new file mode 100644 (file)
index 0000000..e1c328e
--- /dev/null
@@ -0,0 +1,671 @@
+/* visorinput.c
+ *
+ * Copyright (C) 2011 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * 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 that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This driver lives in a generic guest Linux partition, and registers to
+ * receive keyboard and mouse channels from the visorbus driver.  It reads
+ * inputs from such channels, and delivers it to the Linux OS in the
+ * standard way the Linux expects for input drivers.
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+
+#include "keyboardchannel.h"
+#include "mousechannel.h"
+#include "version.h"
+#include "visorbus.h"
+
+#define PIXELS_ACROSS_DEFAULT  800
+#define PIXELS_DOWN_DEFAULT    600
+
+static const uuid_le spar_keyboard_channel_protocol_uuid =
+       SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID;
+static const uuid_le spar_mouse_channel_protocol_uuid =
+       SPAR_MOUSE_CHANNEL_PROTOCOL_UUID;
+static int visorinput_probe(struct visor_device *dev);
+static void visorinput_remove(struct visor_device *dev);
+static void visorinput_channel_interrupt(struct visor_device *dev);
+static int visorinput_pause(struct visor_device *dev,
+                         visorbus_state_complete_func complete_func);
+static int visorinput_resume(struct visor_device *dev,
+                          visorbus_state_complete_func complete_func);
+static struct input_dev *register_client_keyboard(void);
+static struct input_dev *register_client_mouse(void);
+static void unregister_client_input(struct input_dev *visorinput_dev);
+
+/* GUIDS for all channel types supported by this driver. */
+static struct visor_channeltype_descriptor visorinput_channel_types[] = {
+       { SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID, "keyboard"},
+       { SPAR_MOUSE_CHANNEL_PROTOCOL_UUID, "mouse"},
+       { NULL_UUID_LE, NULL }
+};
+MODULE_DEVICE_TABLE(visorbus, visorinput_channel_types);
+MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR);
+MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR);
+
+/** This is used to tell the visor bus driver which types of visor devices
+ *  we support, and what functions to call when a visor device that we support
+ *  is attached or removed.
+ */
+static struct visor_driver visorinput_driver = {
+       .name = "visorinput",
+       .vertag = NULL,
+       .owner = THIS_MODULE,
+       .channel_types = visorinput_channel_types,
+       .probe = visorinput_probe,
+       .remove = visorinput_remove,
+       .channel_interrupt = visorinput_channel_interrupt,
+       .pause = visorinput_pause,
+       .resume = visorinput_resume,
+};
+
+enum visorinput_device_type {
+       visorinput_keyboard,
+       visorinput_mouse,
+};
+
+/*  This is the private data that we store for each device.
+ *  A pointer to this struct is maintained via
+ *  dev_get_drvdata() / dev_set_drvdata() for each struct device.
+ */
+struct visorinput_devdata {
+       struct visor_device *dev;
+       /** lock for dev */
+       struct rw_semaphore lock_visor_dev;
+       struct input_dev *visorinput_dev;
+       bool paused;
+};
+
+/* Borrowed from drivers/input/keyboard/atakbd.c */
+/* This maps 1-byte scancodes to keycodes. */
+static unsigned char visorkbd_keycode[256] = { /* American layout */
+       [0] = KEY_GRAVE,
+       [1] = KEY_ESC,
+       [2] = KEY_1,
+       [3] = KEY_2,
+       [4] = KEY_3,
+       [5] = KEY_4,
+       [6] = KEY_5,
+       [7] = KEY_6,
+       [8] = KEY_7,
+       [9] = KEY_8,
+       [10] = KEY_9,
+       [11] = KEY_0,
+       [12] = KEY_MINUS,
+       [13] = KEY_EQUAL,
+       [14] = KEY_BACKSPACE,
+       [15] = KEY_TAB,
+       [16] = KEY_Q,
+       [17] = KEY_W,
+       [18] = KEY_E,
+       [19] = KEY_R,
+       [20] = KEY_T,
+       [21] = KEY_Y,
+       [22] = KEY_U,
+       [23] = KEY_I,
+       [24] = KEY_O,
+       [25] = KEY_P,
+       [26] = KEY_LEFTBRACE,
+       [27] = KEY_RIGHTBRACE,
+       [28] = KEY_ENTER,
+       [29] = KEY_LEFTCTRL,
+       [30] = KEY_A,
+       [31] = KEY_S,
+       [32] = KEY_D,
+       [33] = KEY_F,
+       [34] = KEY_G,
+       [35] = KEY_H,
+       [36] = KEY_J,
+       [37] = KEY_K,
+       [38] = KEY_L,
+       [39] = KEY_SEMICOLON,
+       [40] = KEY_APOSTROPHE,
+       [41] = KEY_GRAVE,       /* FIXME, '#' */
+       [42] = KEY_LEFTSHIFT,
+       [43] = KEY_BACKSLASH,   /* FIXME, '~' */
+       [44] = KEY_Z,
+       [45] = KEY_X,
+       [46] = KEY_C,
+       [47] = KEY_V,
+       [48] = KEY_B,
+       [49] = KEY_N,
+       [50] = KEY_M,
+       [51] = KEY_COMMA,
+       [52] = KEY_DOT,
+       [53] = KEY_SLASH,
+       [54] = KEY_RIGHTSHIFT,
+       [55] = KEY_KPASTERISK,
+       [56] = KEY_LEFTALT,
+       [57] = KEY_SPACE,
+       [58] = KEY_CAPSLOCK,
+       [59] = KEY_F1,
+       [60] = KEY_F2,
+       [61] = KEY_F3,
+       [62] = KEY_F4,
+       [63] = KEY_F5,
+       [64] = KEY_F6,
+       [65] = KEY_F7,
+       [66] = KEY_F8,
+       [67] = KEY_F9,
+       [68] = KEY_F10,
+       [69] = KEY_NUMLOCK,
+       [70] = KEY_SCROLLLOCK,
+       [71] = KEY_KP7,
+       [72] = KEY_KP8,
+       [73] = KEY_KP9,
+       [74] = KEY_KPMINUS,
+       [75] = KEY_KP4,
+       [76] = KEY_KP5,
+       [77] = KEY_KP6,
+       [78] = KEY_KPPLUS,
+       [79] = KEY_KP1,
+       [80] = KEY_KP2,
+       [81] = KEY_KP3,
+       [82] = KEY_KP0,
+       [83] = KEY_KPDOT,
+       [86] = KEY_102ND, /* enables UK backslash+pipe key,
+                          * and FR lessthan+greaterthan key */
+       [87] = KEY_F11,
+       [88] = KEY_F12,
+       [90] = KEY_KPLEFTPAREN,
+       [91] = KEY_KPRIGHTPAREN,
+       [92] = KEY_KPASTERISK,  /* FIXME */
+       [93] = KEY_KPASTERISK,
+       [94] = KEY_KPPLUS,
+       [95] = KEY_HELP,
+       [96] = KEY_KPENTER,
+       [97] = KEY_RIGHTCTRL,
+       [98] = KEY_KPSLASH,
+       [99] = KEY_KPLEFTPAREN,
+       [100] = KEY_KPRIGHTPAREN,
+       [101] = KEY_KPSLASH,
+       [102] = KEY_HOME,
+       [103] = KEY_UP,
+       [104] = KEY_PAGEUP,
+       [105] = KEY_LEFT,
+       [106] = KEY_RIGHT,
+       [107] = KEY_END,
+       [108] = KEY_DOWN,
+       [109] = KEY_PAGEDOWN,
+       [110] = KEY_INSERT,
+       [111] = KEY_DELETE,
+       [112] = KEY_MACRO,
+       [113] = KEY_MUTE
+};
+
+/* This maps the <xx> in extended scancodes of the form "0xE0 <xx>" into
+ * keycodes.
+ */
+static unsigned char visorkbd_ext_keycode[256] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x00 */
+       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x10 */
+       0, 0, 0, 0, KEY_KPENTER, KEY_RIGHTCTRL, 0, 0,               /* 0x18 */
+       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x20 */
+       KEY_RIGHTALT, 0, 0, 0, 0, 0, 0, 0,                          /* 0x28 */
+       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x30 */
+       KEY_RIGHTALT /* AltGr */, 0, 0, 0, 0, 0, 0, 0,              /* 0x38 */
+       0, 0, 0, 0, 0, 0, 0, KEY_HOME,                              /* 0x40 */
+       KEY_UP, KEY_PAGEUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END,  /* 0x48 */
+       KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE, 0, 0, 0, 0, /* 0x50 */
+       0, 0, 0, 0, 0, 0, 0, 0,                                     /* 0x58 */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x60 */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             /* 0x70 */
+};
+
+static struct visorinput_devdata *
+devdata_create(struct visor_device *dev, enum visorinput_device_type devtype)
+{
+       struct visorinput_devdata *devdata = NULL;
+
+       devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
+       if (!devdata)
+               return NULL;
+       devdata->dev = dev;
+
+       /* This is an input device in a client guest partition,
+        * so we need to create whatever gizmos are necessary to
+        * deliver our inputs to the guest OS.
+        */
+       switch (devtype) {
+       case visorinput_keyboard:
+               devdata->visorinput_dev = register_client_keyboard();
+               if (!devdata->visorinput_dev)
+                       goto cleanups_register;
+               break;
+       case visorinput_mouse:
+               devdata->visorinput_dev = register_client_mouse();
+               if (!devdata->visorinput_dev)
+                       goto cleanups_register;
+               break;
+       }
+
+       init_rwsem(&devdata->lock_visor_dev);
+
+       return devdata;
+
+cleanups_register:
+       kfree(devdata);
+       return NULL;
+}
+
+static int
+visorinput_probe(struct visor_device *dev)
+{
+       struct visorinput_devdata *devdata = NULL;
+       uuid_le guid;
+       enum visorinput_device_type devtype;
+
+       guid = visorchannel_get_uuid(dev->visorchannel);
+       if (uuid_le_cmp(guid, spar_mouse_channel_protocol_uuid) == 0)
+               devtype = visorinput_mouse;
+       else if (uuid_le_cmp(guid, spar_keyboard_channel_protocol_uuid) == 0)
+               devtype = visorinput_keyboard;
+       else
+               return -ENODEV;
+       devdata = devdata_create(dev, devtype);
+       if (!devdata)
+               return -ENOMEM;
+       dev_set_drvdata(&dev->device, devdata);
+       visorbus_enable_channel_interrupts(dev);
+       return 0;
+}
+
+static void
+visorinput_remove(struct visor_device *dev)
+{
+       struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device);
+
+       if (!devdata)
+               return;
+
+       visorbus_disable_channel_interrupts(dev);
+
+       /* due to above, at this time no thread of execution will be
+       * in visorinput_channel_interrupt()
+       */
+
+       down_write(&devdata->lock_visor_dev);
+       dev_set_drvdata(&dev->device, NULL);
+       unregister_client_input(devdata->visorinput_dev);
+       up_write(&devdata->lock_visor_dev);
+       kfree(devdata);
+}
+
+static void
+unregister_client_input(struct input_dev *visorinput_dev)
+{
+       if (visorinput_dev)
+               input_unregister_device(visorinput_dev);
+}
+
+/* register_client_keyboard() initializes and returns a Linux gizmo that we
+ * can use to deliver keyboard inputs to Linux.  We of course do this when
+ * we see keyboard inputs coming in on a keyboard channel.
+ */
+static struct input_dev *
+register_client_keyboard(void)
+{
+       int i, error;
+       struct input_dev *visorinput_dev = NULL;
+
+       visorinput_dev = input_allocate_device();
+       if (!visorinput_dev)
+               return NULL;
+
+       visorinput_dev->name = "visor Keyboard";
+       visorinput_dev->phys = "visorkbd:input0";
+       visorinput_dev->id.bustype = BUS_HOST;
+       visorinput_dev->id.vendor = 0x0001;
+       visorinput_dev->id.product = 0x0001;
+       visorinput_dev->id.version = 0x0100;
+
+       visorinput_dev->evbit[0] = BIT_MASK(EV_KEY) |
+                                  BIT_MASK(EV_REP) |
+                                  BIT_MASK(EV_LED);
+       visorinput_dev->ledbit[0] = BIT_MASK(LED_CAPSL) |
+                                   BIT_MASK(LED_SCROLLL) |
+                                   BIT_MASK(LED_NUML);
+       visorinput_dev->keycode = visorkbd_keycode;
+       visorinput_dev->keycodesize = sizeof(unsigned char);
+       visorinput_dev->keycodemax = ARRAY_SIZE(visorkbd_keycode);
+
+       for (i = 1; i < ARRAY_SIZE(visorkbd_keycode); i++)
+               set_bit(visorkbd_keycode[i], visorinput_dev->keybit);
+
+       for (i = 1; i < ARRAY_SIZE(visorkbd_ext_keycode); i++)
+               set_bit(visorkbd_ext_keycode[i], visorinput_dev->keybit);
+
+       error = input_register_device(visorinput_dev);
+       if (error) {
+               input_free_device(visorinput_dev);
+               return NULL;
+       }
+       return visorinput_dev;
+}
+
+static struct input_dev *
+register_client_mouse(void)
+{
+       int error;
+       struct input_dev *visorinput_dev = NULL;
+       int xres, yres;
+       struct fb_info *fb0;
+
+       visorinput_dev = input_allocate_device();
+       if (!visorinput_dev)
+               return NULL;
+
+       visorinput_dev->name = "visor Mouse";
+       visorinput_dev->phys = "visormou:input0";
+       visorinput_dev->id.bustype = BUS_HOST;
+       visorinput_dev->id.vendor = 0x0001;
+       visorinput_dev->id.product = 0x0002;
+       visorinput_dev->id.version = 0x0100;
+
+       visorinput_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       set_bit(BTN_LEFT, visorinput_dev->keybit);
+       set_bit(BTN_RIGHT, visorinput_dev->keybit);
+       set_bit(BTN_MIDDLE, visorinput_dev->keybit);
+
+       if (registered_fb[0]) {
+               fb0 = registered_fb[0];
+               xres = fb0->var.xres_virtual;
+               yres = fb0->var.yres_virtual;
+       } else {
+               xres = PIXELS_ACROSS_DEFAULT;
+               yres = PIXELS_DOWN_DEFAULT;
+       }
+       input_set_abs_params(visorinput_dev, ABS_X, 0, xres, 0, 0);
+       input_set_abs_params(visorinput_dev, ABS_Y, 0, yres, 0, 0);
+
+       error = input_register_device(visorinput_dev);
+       if (error) {
+               input_free_device(visorinput_dev);
+               return NULL;
+       }
+
+       /* Sending top-left and bottom-right positions is ABSOLUTELY
+        * REQUIRED if we want X to move the mouse to the exact points
+        * we tell it.  I have NO IDEA why.
+        */
+       input_report_abs(visorinput_dev, ABS_X, 0);
+       input_report_abs(visorinput_dev, ABS_Y, 0);
+       input_sync(visorinput_dev);
+       input_report_abs(visorinput_dev, ABS_X, xres - 1);
+       input_report_abs(visorinput_dev, ABS_Y, yres - 1);
+       input_sync(visorinput_dev);
+
+       input_set_capability(visorinput_dev, EV_REL, REL_WHEEL);
+
+       return visorinput_dev;
+}
+
+static void
+do_key(struct input_dev *inpt, int keycode, int down)
+{
+       input_report_key(inpt, keycode, down);
+}
+
+/* Make it so the current locking state of the locking key indicated by
+ * <keycode> is as indicated by <desired_state> (1=locked, 0=unlocked).
+ */
+static void
+handle_locking_key(struct input_dev *visorinput_dev,
+                  int keycode, int desired_state)
+{
+       int led;
+       char *sled;
+
+       switch (keycode) {
+       case KEY_CAPSLOCK:
+               led = LED_CAPSL;
+               sled = "CAP";
+               break;
+       case KEY_SCROLLLOCK:
+               led = LED_SCROLLL;
+               sled = "SCR";
+               break;
+       case KEY_NUMLOCK:
+               led = LED_NUML;
+               sled = "NUM";
+               break;
+       default:
+               led = -1;
+               break;
+       }
+       if (led >= 0) {
+               int old_state = (test_bit(led, visorinput_dev->led) != 0);
+
+               if (old_state != desired_state) {
+                       do_key(visorinput_dev, keycode, 1);
+                       input_sync(visorinput_dev);
+                       do_key(visorinput_dev, keycode, 0);
+                       input_sync(visorinput_dev);
+                       __change_bit(led, visorinput_dev->led);
+               }
+       }
+}
+
+/* <scancode> is either a 1-byte scancode, or an extended 16-bit scancode
+ * with 0xE0 in the low byte and the extended scancode value in the next
+ * higher byte.
+ */
+static int
+scancode_to_keycode(int scancode)
+{
+       int keycode;
+
+       if (scancode > 0xff)
+               keycode = visorkbd_ext_keycode[(scancode >> 8) & 0xff];
+       else
+               keycode = visorkbd_keycode[scancode];
+       return keycode;
+}
+
+static int
+calc_button(int x)
+{
+       switch (x) {
+       case 1:
+               return BTN_LEFT;
+       case 2:
+               return BTN_MIDDLE;
+       case 3:
+               return BTN_RIGHT;
+       default:
+               return -1;
+       }
+}
+
+/* This is used only when this driver is active as an input driver in the
+ * client guest partition.  It is called periodically so we can obtain inputs
+ * from the channel, and deliver them to the guest OS.
+ */
+static void
+visorinput_channel_interrupt(struct visor_device *dev)
+{
+       struct ultra_inputreport r;
+       int scancode, keycode;
+       struct input_dev *visorinput_dev;
+       int xmotion, ymotion, zmotion, button;
+       int i;
+
+       struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device);
+
+       if (!devdata)
+               return;
+
+       down_write(&devdata->lock_visor_dev);
+       if (devdata->paused) /* don't touch device/channel when paused */
+               goto out_locked;
+
+       visorinput_dev = devdata->visorinput_dev;
+       if (!visorinput_dev)
+               goto out_locked;
+
+       while (visorchannel_signalremove(dev->visorchannel, 0, &r)) {
+               scancode = r.activity.arg1;
+               keycode = scancode_to_keycode(scancode);
+               switch (r.activity.action) {
+               case inputaction_key_down:
+                       do_key(visorinput_dev, keycode, 1);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_key_up:
+                       do_key(visorinput_dev, keycode, 0);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_key_down_up:
+                       do_key(visorinput_dev, keycode, 1);
+                       input_sync(visorinput_dev);
+                       do_key(visorinput_dev, keycode, 0);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_set_locking_key_state:
+                       handle_locking_key(visorinput_dev, keycode,
+                                          r.activity.arg2);
+                       break;
+               case inputaction_xy_motion:
+                       xmotion = r.activity.arg1;
+                       ymotion = r.activity.arg2;
+                       input_report_abs(visorinput_dev, ABS_X, xmotion);
+                       input_report_abs(visorinput_dev, ABS_Y, ymotion);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_mouse_button_down:
+                       button = calc_button(r.activity.arg1);
+                       if (button < 0)
+                               break;
+                       input_report_key(visorinput_dev, button, 1);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_mouse_button_up:
+                       button = calc_button(r.activity.arg1);
+                       if (button < 0)
+                               break;
+                       input_report_key(visorinput_dev, button, 0);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_mouse_button_click:
+                       button = calc_button(r.activity.arg1);
+                       if (button < 0)
+                               break;
+                       input_report_key(visorinput_dev, button, 1);
+
+                       input_sync(visorinput_dev);
+                       input_report_key(visorinput_dev, button, 0);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_mouse_button_dclick:
+                       button = calc_button(r.activity.arg1);
+                       if (button < 0)
+                               break;
+                       for (i = 0; i < 2; i++) {
+                               input_report_key(visorinput_dev, button, 1);
+                               input_sync(visorinput_dev);
+                               input_report_key(visorinput_dev, button, 0);
+                               input_sync(visorinput_dev);
+                       }
+                       break;
+               case inputaction_wheel_rotate_away:
+                       zmotion = r.activity.arg1;
+                       input_report_rel(visorinput_dev, REL_WHEEL, 1);
+                       input_sync(visorinput_dev);
+                       break;
+               case inputaction_wheel_rotate_toward:
+                       zmotion = r.activity.arg1;
+                       input_report_rel(visorinput_dev, REL_WHEEL, -1);
+                       input_sync(visorinput_dev);
+                       break;
+               }
+       }
+out_locked:
+       up_write(&devdata->lock_visor_dev);
+}
+
+static int
+visorinput_pause(struct visor_device *dev,
+              visorbus_state_complete_func complete_func)
+{
+       int rc;
+       struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device);
+
+       if (!devdata) {
+               rc = -ENODEV;
+               goto out;
+       }
+
+       down_write(&devdata->lock_visor_dev);
+       if (devdata->paused) {
+               rc = -EBUSY;
+               goto out_locked;
+       }
+       devdata->paused = true;
+       complete_func(dev, 0);
+       rc = 0;
+out_locked:
+       up_write(&devdata->lock_visor_dev);
+out:
+       return rc;
+}
+
+static int
+visorinput_resume(struct visor_device *dev,
+               visorbus_state_complete_func complete_func)
+{
+       int rc;
+       struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device);
+
+       if (!devdata) {
+               rc = -ENODEV;
+               goto out;
+       }
+       down_write(&devdata->lock_visor_dev);
+       if (!devdata->paused) {
+               rc = -EBUSY;
+               goto out_locked;
+       }
+       devdata->paused = false;
+       complete_func(dev, 0);
+       rc = 0;
+out_locked:
+       up_write(&devdata->lock_visor_dev);
+out:
+       return rc;
+}
+
+static int
+visorinput_init(void)
+{
+       return visorbus_register_visor_driver(&visorinput_driver);
+}
+
+static void
+visorinput_cleanup(void)
+{
+       visorbus_unregister_visor_driver(&visorinput_driver);
+}
+
+module_init(visorinput_init);
+module_exit(visorinput_cleanup);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("s-Par human input driver for guest Linux");
+MODULE_VERSION(VERSION);