On Thu, Jun 25, 2015 at 09:58:51AM -0400, Benjamin Romer wrote:
> From: Erik Arfvidson <erik.arfvid...@unisys.com>
> 
> This driver provides mouse and keyboard input to Unisys s-Par
> Partition Desktop application. This device is created by the
> visorbus device.
> 
> Signed-off-by: Erik Arfvidson <erik.arfvid...@unisys.com>
> Signed-off-by: Benjamin Romer <benjamin.ro...@unisys.com>
> ---
>  drivers/staging/unisys/Kconfig                     |   1 +
>  drivers/staging/unisys/Makefile                    |   1 +
>  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     |  32 +
>  drivers/staging/unisys/visorhid/ultrainputreport.h |  82 +++
>  drivers/staging/unisys/visorhid/visorhid.c         | 798 
> +++++++++++++++++++++
>  8 files changed, 963 insertions(+)
>  create mode 100644 drivers/staging/unisys/visorhid/Kconfig
>  create mode 100644 drivers/staging/unisys/visorhid/Makefile
>  create mode 100644 drivers/staging/unisys/visorhid/keyboardchannel.h
>  create mode 100644 drivers/staging/unisys/visorhid/mousechannel.h
>  create mode 100644 drivers/staging/unisys/visorhid/ultrainputreport.h
>  create mode 100644 drivers/staging/unisys/visorhid/visorhid.c
> 
> diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
> index 778f9d0..bdc8ba8 100644
> --- a/drivers/staging/unisys/Kconfig
> +++ b/drivers/staging/unisys/Kconfig
> @@ -13,5 +13,6 @@ if UNISYSSPAR
>  
>  source "drivers/staging/unisys/visorbus/Kconfig"
>  source "drivers/staging/unisys/visornic/Kconfig"
> +source "drivers/staging/unisys/visorhid/Kconfig"
>  
>  endif # UNISYSSPAR
> diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile
> index a515ebc..d071094 100644
> --- a/drivers/staging/unisys/Makefile
> +++ b/drivers/staging/unisys/Makefile
> @@ -3,3 +3,4 @@
>  #
>  obj-$(CONFIG_UNISYS_VISORBUS)                += visorbus/
>  obj-$(CONFIG_UNISYS_VISORNIC)                += visornic/
> +obj-$(CONFIG_UNISYS_VISORHID)          += visorhid/
> diff --git a/drivers/staging/unisys/visorhid/Kconfig 
> b/drivers/staging/unisys/visorhid/Kconfig
> new file mode 100644
> index 0000000..3b83e2c
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/Kconfig
> @@ -0,0 +1,10 @@
> +#
> +# 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
> new file mode 100644
> index 0000000..e457bd1
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# 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
> new file mode 100644
> index 0000000..0722c60
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/keyboardchannel.h
> @@ -0,0 +1,32 @@
> +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
> + * All rights reserved.

2013?

> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.

I have to ask, do you really mean "any later version"?

> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + * NON INFRINGEMENT.  See the GNU General Public License for more
> + * details.
> + */
> +
> +#ifndef __KEYBOARDCHANNEL_H__
> +#define __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_VERSIONID 1
> +#define KEYBOARD_MAXINPUTREPORTS 50
> +
> +#endif
> diff --git a/drivers/staging/unisys/visorhid/mousechannel.h 
> b/drivers/staging/unisys/visorhid/mousechannel.h
> new file mode 100644
> index 0000000..ac6883b
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/mousechannel.h
> @@ -0,0 +1,32 @@
> +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
> + * All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + * NON INFRINGEMENT.  See the GNU General Public License for more
> + * details.
> + */
> +
> +#ifndef __MOUSECHANNEL_H__
> +#define __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_VERSIONID 1
> +#define MOUSE_MAXINPUTREPORTS 50
> +
> +#endif
> diff --git a/drivers/staging/unisys/visorhid/ultrainputreport.h 
> b/drivers/staging/unisys/visorhid/ultrainputreport.h
> new file mode 100644
> index 0000000..4cd75cc
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/ultrainputreport.h
> @@ -0,0 +1,82 @@
> +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
> + * All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + * NON INFRINGEMENT.  See the GNU General Public License for more
> + * details.
> + */
> +
> +#ifndef __ULTRAINPUTREPORT_H__
> +#define __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,
> +                                         4, *  5 */
> +     inputaction_mouse_button_up = 3, /*< arg1: 1=left, 2=center, 3=right,
> +                                       4,*  5 */

Very odd comment style, it's not readable at all.  I think you ran this
through some script...


> +     inputaction_mouse_button_click = 4, /*< arg1: 1=left, 2=center, 3=right,
> +                                      *  4, 5 */
> +     inputaction_mouse_button_dclick = 5, /*< arg1: 1=left, 2=center,
> +                                      3=right, *  4, 5 */
> +     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
> new file mode 100644
> index 0000000..7384bef
> --- /dev/null
> +++ b/drivers/staging/unisys/visorhid/visorhid.c
> @@ -0,0 +1,798 @@
> +/* visorhid.c
> + *
> + * Copyright (C) 2011 - 2014 UNISYS CORPORATION
> + * All rights reserved.

2014?

> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, 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/serio.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/segment.h>
> +
> +#include "keyboardchannel.h"
> +#include "mousechannel.h"
> +#include "version.h"
> +#include "visorbus.h"
> +
> +#define MAXDEVICES     16384

That's a lot of devices, do you really mean it?

> +#define PIXELS_ACROSS_DEFAULT 800
> +#define PIXELS_DOWN_DEFAULT   600
> +#define DEV_NAME_SIZE 99

No tabs for indenting?

> +#define SYSFS_VIRTUALSIZE "/sys/class/graphics/fb0/virtual_size"

I really hate to even look as to why you have a full sysfs path in a
#define in a kernel file.  Luckily I don't see it used anywhere, please
remove it.

> +
> +static spinlock_t devnopool_lock;
> +static void *dev_no_pool; /* < pool to grab device numbers from */

What is up with the '<' character in comments?

> +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 struct input_dev *register_client_wheel(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[] = {
> +     {
> +             .guid = SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID,
> +             .name = "keyboard"
> +     },
> +     {
> +             .guid = SPAR_MOUSE_CHANNEL_PROTOCOL_UUID,
> +             .name = "mouse"
> +     },
> +     {
> +             .guid = NULL_UUID_LE,
> +             .name = NULL
> +     }
> +};
> +
> +/** 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",
> +     .version = VERSION,

Why do we care about "versions"?

> +     .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,
> +};
> +
> +/*  This is the private data that we store for each device.
> + *  A pointer to this struct is kept in each "struct device"

Why isn't this embedded in a struct device?

> + */
> +struct visorhid_devdata {
> +     int devno;
> +     struct visor_device *dev;
> +     /** lock for dev */
> +     struct rw_semaphore lock_visor_dev;
> +     char name[DEV_NAME_SIZE];

Why duplicate the name, why can't you use the struct device?

> +     struct list_head list_all;   /* < link within list_all_devices list */
> +     struct kref kref;

You don't use this reference at all, why even have it?

> +     struct input_dev *visorinput_dev;
> +     struct input_dev *visorinput_dev2;
> +     bool supported_client_device;
> +     bool paused;
> +};
> +
> + /* List of all visorhid_devdata structs,
> +  * linked via the list_all member
> +  */
> +static LIST_HEAD(list_all_devices);
> +static DEFINE_SPINLOCK(lock_all_devices);
> +
> +/* 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,
> +     [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 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, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */
> +     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)
> +{
> +     struct visorhid_devdata *devdata = NULL;
> +     int devno = -1;
> +     uuid_le guid;
> +
> +     guid = visorchannel_get_uuid(dev->visorchannel);
> +     devdata = kzalloc(sizeof(*devdata),
> +                       GFP_KERNEL | __GFP_NORETRY);
> +     if (!devdata)
> +             goto cleanups;
> +
> +     spin_lock(&devnopool_lock);
> +     devno = find_first_zero_bit(dev_no_pool, MAXDEVICES);
> +     spin_unlock(&devnopool_lock);

Why not use an idr or ida structure?  Much simpler, easier, and correct.

> +     if (devno == MAXDEVICES)
> +             goto cleanups_set_bit;
> +     set_bit(devno, dev_no_pool);
> +     devdata->devno = devno;
> +     devdata->dev = dev;
> +     strncpy(devdata->name, dev_name(&dev->device), sizeof(devdata->name));

Again, why is this needed?

> +
> +     /* 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.
> +      */
> +     if (!uuid_le_cmp(guid, spar_keyboard_channel_protocol_uuid)) {
> +             devdata->visorinput_dev = register_client_keyboard();
> +             if (!devdata->visorinput_dev)
> +                     goto cleanups_register;
> +             devdata->supported_client_device = true;
> +     } else if (!uuid_le_cmp(guid, spar_mouse_channel_protocol_uuid)) {
> +             devdata->visorinput_dev = register_client_mouse();
> +             if (!devdata->visorinput_dev)
> +                     goto cleanups_register2;
> +             devdata->visorinput_dev2 = register_client_wheel();
> +             if (!devdata->visorinput_dev2)
> +                     goto cleanups_register2;
> +             devdata->supported_client_device = true;
> +     }
> +
> +     init_rwsem(&devdata->lock_visor_dev);
> +     kref_init(&devdata->kref);
> +
> +     spin_lock(&lock_all_devices);
> +     list_add_tail(&devdata->list_all, &list_all_devices);
> +     spin_unlock(&lock_all_devices);
> +     return devdata;
> +
> +cleanups_register2:
> +     unregister_client_input(devdata->visorinput_dev);
> +     devdata->visorinput_dev = NULL;
> +cleanups_register:
> +     clear_bit(devno, dev_no_pool);
> +cleanups_set_bit:
> +     kfree(devdata);
> +cleanups:
> +     return NULL;
> +}
> +
> +static void
> +devdata_release(struct kref *mykref)
> +{
> +     struct visorhid_devdata *devdata =
> +         container_of(mykref, struct visorhid_devdata, kref);
> +     clear_bit(devdata->devno, dev_no_pool);
> +     spin_lock(&lock_all_devices);
> +     list_del(&devdata->list_all);
> +     spin_unlock(&lock_all_devices);
> +}
> +
> +static int
> +visorhid_probe(struct visor_device *dev)
> +{
> +     int rc = 0;
> +     struct visorhid_devdata *devdata = NULL;
> +     uuid_le guid;
> +
> +     devdata = devdata_create(dev);
> +     if (!devdata) {
> +             rc = -1;
> +             goto cleanups;
> +     }
> +     dev_set_drvdata(&dev->device, devdata);
> +     guid = visorchannel_get_uuid(dev->visorchannel);
> +     if (uuid_le_cmp(guid, spar_mouse_channel_protocol_uuid) &&
> +         uuid_le_cmp(guid, spar_keyboard_channel_protocol_uuid)) {
> +             rc = -1;
> +             goto cleanups;
> +     }
> +
> +     if (devdata->supported_client_device)
> +             visorbus_enable_channel_interrupts(dev);
> +
> +cleanups:
> +     if (rc < 0) {
> +             if (devdata)
> +                     kref_put(&devdata->kref, devdata_release);
> +     }
> +     return rc;
> +}
> +
> +static void
> +host_side_disappeared(struct visorhid_devdata *devdata)
> +{
> +     down_write(&devdata->lock_visor_dev);
> +     sprintf(devdata->name, "<dev#%d-history>", devdata->devno);
> +     devdata->dev = NULL;    /* indicate device destroyed */
> +     up_write(&devdata->lock_visor_dev);
> +}
> +
> +static void
> +visorhid_remove(struct visor_device *dev)
> +{
> +     struct visorhid_devdata *devdata = dev_get_drvdata(&dev->device);
> +
> +     if (!devdata)
> +             return;
> +
> +     dev_set_drvdata(&dev->device, NULL);
> +     host_side_disappeared(devdata);
> +     unregister_client_input(devdata->visorinput_dev);
> +     devdata->visorinput_dev = NULL;
> +     unregister_client_input(devdata->visorinput_dev2);
> +     devdata->visorinput_dev2 = NULL;
> +     kref_put(&devdata->kref, devdata_release);
> +}
> +
> +static void
> +visorhid_cleanup_guts(void)
> +{
> +     visorbus_unregister_visor_driver(&visorhid_driver);
> +             kfree(dev_no_pool);
> +             dev_no_pool = NULL;
> +}
> +
> +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";

Shouldn't that be "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);
> +
> +     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";

/me hands you a some extra "me" characters...

Again, s/\//\!/g

> +     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_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);
> +
> +     return visorinput_dev;
> +}
> +
> +static struct input_dev *
> +register_client_wheel(void)
> +{
> +     int error;
> +     struct input_dev *visorinput_dev = NULL;
> +
> +     visorinput_dev = input_allocate_device();
> +     if (!visorinput_dev)
> +             return NULL;
> +
> +     visorinput_dev->name = "visor Wheel";
> +     visorinput_dev->phys = "visorwhl/input0";

Same '!' issue.

> +     visorinput_dev->id.bustype = BUS_HOST;
> +     visorinput_dev->id.vendor = 0x0001;
> +     visorinput_dev->id.product = 0x0001;
> +     visorinput_dev->id.version = 0x0100;
> +
> +     /* We need to lie a little to prevent the evdev driver "Don't
> +      * know how to use device" error.  (evdev erroneously thinks
> +      * that a device without an X and Y axis is useless.)
> +      */
> +     visorinput_dev->evbit[0] = BIT_MASK(EV_REL) |
> +                     /*lie */   BIT_MASK(EV_KEY);
> +     visorinput_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
> +                     /*lie */    BIT_MASK(REL_X) |
> +                     /*lie */    BIT_MASK(REL_Y);
> +     set_bit(BTN_LEFT, visorinput_dev->keybit);      /*lie */
> +     set_bit(BTN_RIGHT, visorinput_dev->keybit);     /*lie */
> +     set_bit(BTN_MIDDLE, visorinput_dev->keybit);    /*lie */
> +
> +     error = input_register_device(visorinput_dev);
> +     if (error) {
> +             input_free_device(visorinput_dev);
> +             return NULL;
> +     }
> +     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);
> +                     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 = 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;
> +     struct input_dev *visorinput_dev2;
> +     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;
> +
> +     visorinput_dev2 = devdata->visorinput_dev2;
> +     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);
> +                     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:
> +                     if (!visorinput_dev2)
> +                             goto out_locked;
> +                     zmotion = r.activity.arg1;
> +                     input_report_rel(visorinput_dev2, REL_WHEEL, 1);
> +                     input_sync(visorinput_dev2);
> +                     break;
> +             case inputaction_wheel_rotate_toward:
> +                     if (!visorinput_dev2)
> +                             goto out_locked;
> +                     zmotion = r.activity.arg1;
> +                     input_report_rel(visorinput_dev2, REL_WHEEL, -1);
> +                     input_sync(visorinput_dev2);
> +                     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)
> +{
> +     int rc = 0;
> +
> +     spin_lock_init(&devnopool_lock);
> +     dev_no_pool = kzalloc(BITS_TO_LONGS(MAXDEVICES), GFP_KERNEL);

Again, use an idr/ida structure instead please.

> +     if (!dev_no_pool) {
> +             rc = -ENOMEM;
> +             goto cleanups;
> +     }
> +     visorbus_register_visor_driver(&visorhid_driver);

No error checking?

greg k-h
_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to