[PATCH 03/13] staging: unisys: visorhid: rename to visorinput

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Tim Sell <Timothy.Sell@xxxxxxxxxx>

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@xxxxxxxxxx>
Signed-off-by: Benjamin Romer <benjamin.romer@xxxxxxxxxx>
---
 drivers/staging/unisys/Documentation/overview.txt  |  22 +-
 drivers/staging/unisys/Kconfig                     |   2 +-
 drivers/staging/unisys/Makefile                    |   2 +-
 drivers/staging/unisys/visorhid/Kconfig            |  10 -
 drivers/staging/unisys/visorhid/Makefile           |   7 -
 drivers/staging/unisys/visorhid/keyboardchannel.h  |  32 -
 drivers/staging/unisys/visorhid/mousechannel.h     |  33 -
 drivers/staging/unisys/visorhid/ultrainputreport.h |  74 ---
 drivers/staging/unisys/visorhid/visorhid.c         | 671 ---------------------
 drivers/staging/unisys/visorinput/Kconfig          |  10 +
 drivers/staging/unisys/visorinput/Makefile         |   7 +
 .../staging/unisys/visorinput/keyboardchannel.h    |  32 +
 drivers/staging/unisys/visorinput/mousechannel.h   |  33 +
 .../staging/unisys/visorinput/ultrainputreport.h   |  74 +++
 drivers/staging/unisys/visorinput/visorinput.c     | 671 +++++++++++++++++++++
 15 files changed, 840 insertions(+), 840 deletions(-)
 delete mode 100644 drivers/staging/unisys/visorhid/Kconfig
 delete mode 100644 drivers/staging/unisys/visorhid/Makefile
 delete mode 100644 drivers/staging/unisys/visorhid/keyboardchannel.h
 delete mode 100644 drivers/staging/unisys/visorhid/mousechannel.h
 delete mode 100644 drivers/staging/unisys/visorhid/ultrainputreport.h
 delete mode 100644 drivers/staging/unisys/visorhid/visorhid.c
 create mode 100644 drivers/staging/unisys/visorinput/Kconfig
 create mode 100644 drivers/staging/unisys/visorinput/Makefile
 create mode 100644 drivers/staging/unisys/visorinput/keyboardchannel.h
 create mode 100644 drivers/staging/unisys/visorinput/mousechannel.h
 create mode 100644 drivers/staging/unisys/visorinput/ultrainputreport.h
 create mode 100644 drivers/staging/unisys/visorinput/visorinput.c

diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt
index 25f93f2..c2d8dd4 100644
--- a/drivers/staging/unisys/Documentation/overview.txt
+++ b/drivers/staging/unisys/Documentation/overview.txt
@@ -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.
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
index 5cbb791..4f1f5e6 100644
--- a/drivers/staging/unisys/Kconfig
+++ b/drivers/staging/unisys/Kconfig
@@ -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
diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile
index 79c9036..20eb098 100644
--- a/drivers/staging/unisys/Makefile
+++ b/drivers/staging/unisys/Makefile
@@ -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
index 3b83e2c..0000000
--- a/drivers/staging/unisys/visorhid/Kconfig
+++ /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
index e457bd1..0000000
--- a/drivers/staging/unisys/visorhid/Makefile
+++ /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
index 2ed2602..0000000
--- a/drivers/staging/unisys/visorhid/keyboardchannel.h
+++ /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
index 256477a..0000000
--- a/drivers/staging/unisys/visorhid/mousechannel.h
+++ /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
index 3e6a52f..0000000
--- a/drivers/staging/unisys/visorhid/ultrainputreport.h
+++ /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
index c24aaf5..0000000
--- a/drivers/staging/unisys/visorhid/visorhid.c
+++ /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
index 0000000..d83deb4
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/Kconfig
@@ -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
index 0000000..beedca7
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/Makefile
@@ -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
index 0000000..2ed2602
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/keyboardchannel.h
@@ -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
index 0000000..256477a
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/mousechannel.h
@@ -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
index 0000000..3e6a52f
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/ultrainputreport.h
@@ -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
index 0000000..e1c328e
--- /dev/null
+++ b/drivers/staging/unisys/visorinput/visorinput.c
@@ -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);
-- 
2.1.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux