2009-04-08 07:30:32

by Dmitry Torokhov

[permalink] [raw]
Subject: [git pull] Input updates for 2.6.30-rc1

Hi Linus,

Please pull from:

git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
or
master.kernel.org:/pub/scm/linux/kernel/git/dtor/input.git for-linus

to receive updates for the input subsystem. Bunch of new drivers plus
some cleanups to existing ones, nothing too exciting. It looks like I
managed to miss the merge window. Oh well...

Changelog:
---------

Adrian McMenamin (1):
Input: add support for the Maple mouse on the SEGA Dreamcast

Andy Whitcroft (1):
Input: psmouse - add newline to OLPC HGPK touchpad debugging

Daniel Mack (1):
Input: generic driver for rotary encoders on GPIOs

Daniel Mierswa (2):
Input: atkbd - consolidate force release quirk setup
Input: atkbd - add quirk for Fujitsu Siemens Amilo PA 1510

Dmitry Torokhov (3):
Input: fix polling of /proc/bus/input/devices
Input: arrange drivers/input/misc/Makefile in alphabetical order
Input: i8042 - add HP DV9700 to the noloop list

Helge Deller (1):
Input: hilkbd - fix crash when removing hilkbd module

Johannes Berg (1):
Input: stop autorepeat timer on key release

Mark Brown (2):
Input: wm97xx - use disable_irq_nosync() for Mainstone
Input: add accelerated touchscreen support for Marvell Zylonite

Michael Hennerich (3):
Input: bf54x-keys - fix typo in warning
Input: add AD7877 touchscreen driver
Input: add AD7879 Touchscreen driver

Mike Rapoport (2):
Input: wm97xx - add BTN_TOUCH event to wm97xx to use it with Android
Input: ucb1400_ts, mainstone-wm97xx - add BTN_TOUCH events

Phil Sutter (1):
Input: add driver for S1 button of rb532

Roel Kluin (1):
Input: pc110pad - use no_pci_devices()

Ville Syrjala (3):
Input: ati_remote2 - complete suspend support
Input: ati_remote2 - add per device attrs
Input: ati_remote2 - check module params


Diffstat:
--------

Documentation/input/rotary-encoder.txt | 101 +++
arch/mips/include/asm/mach-rc32434/gpio.h | 3 +
arch/mips/rb532/devices.c | 19 +-
drivers/input/input.c | 13 +-
drivers/input/keyboard/atkbd.c | 135 ++---
drivers/input/keyboard/bf54x-keys.c | 4 +-
drivers/input/keyboard/hilkbd.c | 140 +++--
drivers/input/misc/Kconfig | 23 +
drivers/input/misc/Makefile | 28 +-
drivers/input/misc/ati_remote2.c | 277 ++++++++-
drivers/input/misc/rb532_button.c | 120 ++++
drivers/input/misc/rotary_encoder.c | 221 +++++++
drivers/input/mouse/Kconfig | 11 +
drivers/input/mouse/Makefile | 9 +-
drivers/input/mouse/hgpk.c | 2 +-
drivers/input/mouse/maplemouse.c | 147 +++++
drivers/input/mouse/pc110pad.c | 5 +-
drivers/input/serio/i8042-x86ia64io.h | 8 +
drivers/input/touchscreen/Kconfig | 58 ++
drivers/input/touchscreen/Makefile | 3 +
drivers/input/touchscreen/ad7877.c | 844 ++++++++++++++++++++++++++
drivers/input/touchscreen/ad7879.c | 782 ++++++++++++++++++++++++
drivers/input/touchscreen/mainstone-wm97xx.c | 3 +-
drivers/input/touchscreen/ucb1400_ts.c | 5 +-
drivers/input/touchscreen/wm97xx-core.c | 13 +-
drivers/input/touchscreen/zylonite-wm97xx.c | 240 ++++++++
include/linux/rotary_encoder.h | 13 +
include/linux/spi/ad7879.h | 35 ++
28 files changed, 3062 insertions(+), 200 deletions(-)
create mode 100644 Documentation/input/rotary-encoder.txt
create mode 100644 drivers/input/misc/rb532_button.c
create mode 100644 drivers/input/misc/rotary_encoder.c
create mode 100644 drivers/input/mouse/maplemouse.c
create mode 100644 drivers/input/touchscreen/ad7877.c
create mode 100644 drivers/input/touchscreen/ad7879.c
create mode 100644 drivers/input/touchscreen/zylonite-wm97xx.c
create mode 100644 include/linux/rotary_encoder.h
create mode 100644 include/linux/spi/ad7879.h

--
Dmitry


2009-04-08 17:28:25

by Mark Lord

[permalink] [raw]
Subject: Input driver for Twinhan USB 6253:0100 remote control

Dmitry,

I briefly had access to a Twinhan remote control (for Mythtv et al.)
and cobbled something together quickly to make it work.

But I really don't understand the new hid/input stuff,
so this is undoubtedly a total abomination to your eyes. :)

But if somebody could give *exact* and *detailed* instructions as
to what to do to make it "fit" the new model better, then I may still
have time (before I have to return it) to clean things up enough.

I don't want to hear about 80-column limits,
but rather how to properly integrate this into
the newly refurbished hid stuff.

Have a look. Currently it's just this single source file,
which has to be loaded before usbhid (not on the quirks list there yet).



/*
* HID driver for Twinhan remote control
*
* Copyright (c) 2009 Mark Lord
*
* 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.
*/

#include <linux/device.h>
#include <linux/input.h>
#include <linux/hid.h>
#include <linux/module.h>

#ifndef HID_USB_DEVICE
#error "This driver requires a 2.6.28 (or higher) Linux kernel"
#endif

/* See /usr/include/linux/input.h for all possible KEY_* definitions */

static unsigned int twinhan_keymap (unsigned int key)
{
switch (key) {
case 0x04: key = KEY_RESERVED ; break; // Teletext ()
case 0x06: key = KEY_ESC ; break; // Recall (myth Escape/Cancel/Back)
case 0x08: key = KEY_S ; break; // EPG (myth guide)
case 0x0c: key = KEY_HOME ; break; // Rewind (myth commskip back)
case 0x0e: key = KEY_P ; break; // Preview (myth playback)
case 0x0f: key = KEY_F3 ; break; // RecordList (myth DVD root menu)
case 0x10: key = KEY_F9 ; break; // Mute (myth mute ??)
case 0x11: key = KEY_END ; break; // Forward (myth commskip forward)
case 0x13: key = KEY_RESERVED ; break; // Capture ()
case 0x17: key = KEY_P ; break; // Pause (myth Pause)
case 0x19: key = KEY_M ; break; // Favorite (myth Menu)
case 0x1d: key = KEY_W ; break; // FullScreen (myth aspect ratio zoom)
case 0x1e: key = KEY_1 ; break; // 1 (myth 1)
case 0x1f: key = KEY_2 ; break; // 2 (myth 2)
case 0x20: key = KEY_3 ; break; // 3 (myth 3)
case 0x21: key = KEY_4 ; break; // 4 (myth 4)
case 0x22: key = KEY_5 ; break; // 5 (myth 5)
case 0x23: key = KEY_6 ; break; // 6 (myth 6)
case 0x24: key = KEY_7 ; break; // 7 (myth 7)
case 0x25: key = KEY_8 ; break; // 8 (myth 8)
case 0x26: key = KEY_9 ; break; // 9 (myth 9)
case 0x27: key = KEY_0 ; break; // 0 (myth 0)
case 0x29: key = KEY_ESC ; break; // Cancel (myth Escape/Cancel/Back)
case 0x28: key = KEY_ENTER ; break; // Play (myth Okay/Play)
case 0x2b: key = KEY_RESERVED ; break; // Tab ()
case 0x3f: key = KEY_F2 ; break; // Power (myth function key 2)
case 0x4a: key = KEY_R ; break; // Record (myth record)
case 0x4b: key = KEY_UP ; break; // Up/CH+ (myth up)
case 0x4d: key = KEY_B ; break; // Stop (myth adjust audio sync)
case 0x4e: key = KEY_DOWN ; break; // Down/CH- (myth down)
case 0x51: key = KEY_LEFT ; break; // Left/VOL- (myth left)
case 0x52: key = KEY_RIGHT ; break; // Right/VOL+ (myth right)
//case 0xe0: // excess code from Power button
//case 0xe1: // excess code from Power,Left,Right buttons
//case 0xe2: // excess code from Power button
//case 0xef: // excess code from Power button
default: key = KEY_RESERVED ; break; // ignored
}
return key;
}

static int twinhan_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct input_dev *input = field->hidinput->input;
static unsigned int last_key = 0;
unsigned int key;
int ret = 0;

if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || !usage->type)
return 0;
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
return 0;

if (last_key) {
input_event(input, usage->type, last_key, 0);
last_key = 0;
ret = 1;
}
if (value) {
unsigned int val = usage->hid & HID_USAGE;
key = twinhan_keymap(val);
if (key) {
input_event(input, usage->type, key, 1);
last_key = key;
}
ret = 1;
}
return ret;
}

static const struct hid_device_id twinhan_devices[] = {
{ HID_USB_DEVICE(0x6253, 0x0100) },
{ }
};
MODULE_DEVICE_TABLE(hid, twinhan_devices);

static struct hid_driver twinhan_driver = {
.name = "twinhan",
.id_table = twinhan_devices,
.event = twinhan_event,
};

static int twinhan_init(void)
{
return hid_register_driver(&twinhan_driver);
}

static void twinhan_exit(void)
{
hid_unregister_driver(&twinhan_driver);
}

module_init(twinhan_init);
module_exit(twinhan_exit);
MODULE_LICENSE("GPL");

2009-04-13 01:04:18

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [git pull] Input updates for 2.6.30-rc1

On Wed, Apr 08, 2009 at 12:29:35AM -0700, Dmitry Torokhov wrote:
> Hi Linus,
>
> Please pull from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
> or
> master.kernel.org:/pub/scm/linux/kernel/git/dtor/input.git for-linus
>
> to receive updates for the input subsystem. Bunch of new drivers plus
> some cleanups to existing ones, nothing too exciting. It looks like I
> managed to miss the merge window. Oh well...
>

*ping* Any chance this could still be pulled? There were no significant
changes to the core code, just simple bugfixes and a few new drivers,
and the changes has been in the linux-next forever...

--
Dmitry

2009-04-14 02:31:41

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

Hi Mark,

On Wednesday 08 April 2009 10:28:09 Mark Lord wrote:
> Dmitry,
>
> I briefly had access to a Twinhan remote control (for Mythtv et al.)
> and cobbled something together quickly to make it work.
>
> But I really don't understand the new hid/input stuff,
> so this is undoubtedly a total abomination to your eyes. :)
>

Actually HID is Juri's baby so let's see what he says ;). From my POV
we need to update keymap to make it emit proper codes instead of Myth
specific ones, but that is a lesser issue.

> But if somebody could give *exact* and *detailed* instructions as
> to what to do to make it "fit" the new model better, then I may still
> have time (before I have to return it) to clean things up enough.
>
> I don't want to hear about 80-column limits,
> but rather how to properly integrate this into
> the newly refurbished hid stuff.
>
> Have a look. Currently it's just this single source file,
> which has to be loaded before usbhid (not on the quirks list there yet).
>
>
>
> /*
> * HID driver for Twinhan remote control
> *
> * Copyright (c) 2009 Mark Lord
> *
> * 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.
> */
>
> #include <linux/device.h>
> #include <linux/input.h>
> #include <linux/hid.h>
> #include <linux/module.h>
>
> #ifndef HID_USB_DEVICE
> #error "This driver requires a 2.6.28 (or higher) Linux kernel"
> #endif
>
> /* See /usr/include/linux/input.h for all possible KEY_* definitions */
>
> static unsigned int twinhan_keymap (unsigned int key)
> {
> switch (key) {
> case 0x04: key = KEY_RESERVED ; break; // Teletext ()
> case 0x06: key = KEY_ESC ; break; // Recall (myth
> Escape/Cancel/Back) case 0x08: key = KEY_S ; break; // EPG (myth
> guide)
> case 0x0c: key = KEY_HOME ; break; // Rewind (myth commskip back)
> case 0x0e: key = KEY_P ; break; // Preview (myth playback)
> case 0x0f: key = KEY_F3 ; break; // RecordList (myth DVD root
> menu) case 0x10: key = KEY_F9 ; break; // Mute (myth mute ??)
> case 0x11: key = KEY_END ; break; // Forward (myth commskip
> forward) case 0x13: key = KEY_RESERVED ; break; // Capture ()
> case 0x17: key = KEY_P ; break; // Pause (myth Pause)
> case 0x19: key = KEY_M ; break; // Favorite (myth Menu)
> case 0x1d: key = KEY_W ; break; // FullScreen (myth aspect ratio
> zoom) case 0x1e: key = KEY_1 ; break; // 1 (myth 1)
> case 0x1f: key = KEY_2 ; break; // 2 (myth 2)
> case 0x20: key = KEY_3 ; break; // 3 (myth 3)
> case 0x21: key = KEY_4 ; break; // 4 (myth 4)
> case 0x22: key = KEY_5 ; break; // 5 (myth 5)
> case 0x23: key = KEY_6 ; break; // 6 (myth 6)
> case 0x24: key = KEY_7 ; break; // 7 (myth 7)
> case 0x25: key = KEY_8 ; break; // 8 (myth 8)
> case 0x26: key = KEY_9 ; break; // 9 (myth 9)
> case 0x27: key = KEY_0 ; break; // 0 (myth 0)
> case 0x29: key = KEY_ESC ; break; // Cancel (myth
> Escape/Cancel/Back) case 0x28: key = KEY_ENTER ; break; // Play (myth
> Okay/Play) case 0x2b: key = KEY_RESERVED ; break; // Tab ()
> case 0x3f: key = KEY_F2 ; break; // Power (myth function key 2)
> case 0x4a: key = KEY_R ; break; // Record (myth record)
> case 0x4b: key = KEY_UP ; break; // Up/CH+ (myth up)
> case 0x4d: key = KEY_B ; break; // Stop (myth adjust audio sync)
> case 0x4e: key = KEY_DOWN ; break; // Down/CH- (myth down)
> case 0x51: key = KEY_LEFT ; break; // Left/VOL- (myth left)
> case 0x52: key = KEY_RIGHT ; break; // Right/VOL+ (myth right)
> //case 0xe0: // excess code from Power button
> //case 0xe1: // excess code from Power,Left,Right buttons
> //case 0xe2: // excess code from Power button
> //case 0xef: // excess code from Power button
> default: key = KEY_RESERVED ; break; // ignored
> }
> return key;
> }
>
> static int twinhan_event(struct hid_device *hdev, struct hid_field *field,
> struct hid_usage *usage, __s32 value)
> {
> struct input_dev *input = field->hidinput->input;
> static unsigned int last_key = 0;
> unsigned int key;
> int ret = 0;
>
> if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
> !usage->type) return 0;
> if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
> return 0;
>
> if (last_key) {
> input_event(input, usage->type, last_key, 0);
> last_key = 0;
> ret = 1;
> }
> if (value) {
> unsigned int val = usage->hid & HID_USAGE;
> key = twinhan_keymap(val);
> if (key) {
> input_event(input, usage->type, key, 1);
> last_key = key;
> }
> ret = 1;
> }
> return ret;
> }
>
> static const struct hid_device_id twinhan_devices[] = {
> { HID_USB_DEVICE(0x6253, 0x0100) },
> { }
> };
> MODULE_DEVICE_TABLE(hid, twinhan_devices);
>
> static struct hid_driver twinhan_driver = {
> .name = "twinhan",
> .id_table = twinhan_devices,
> .event = twinhan_event,
> };
>
> static int twinhan_init(void)
> {
> return hid_register_driver(&twinhan_driver);
> }
>
> static void twinhan_exit(void)
> {
> hid_unregister_driver(&twinhan_driver);
> }
>
> module_init(twinhan_init);
> module_exit(twinhan_exit);
> MODULE_LICENSE("GPL");
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

--
Dmitry

2009-04-14 16:15:07

by Mark Lord

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

Dmitry Torokhov wrote:
> Hi Mark,
>
> On Wednesday 08 April 2009 10:28:09 Mark Lord wrote:
>> Dmitry,
>>
>> I briefly had access to a Twinhan remote control (for Mythtv et al.)
>> and cobbled something together quickly to make it work.
>>
>> But I really don't understand the new hid/input stuff,
>> so this is undoubtedly a total abomination to your eyes. :)
>>
>
> Actually HID is Juri's baby so let's see what he says ;). From my POV
> we need to update keymap to make it emit proper codes instead of Myth
> specific ones, but that is a lesser issue.
..

That's one thing I haven't figured out: how to make this compatible
with the userspace intput-kbd interface for loading new key maps and stuff.

Some direct hints would be very welcome.

Cheers

2009-04-14 16:45:59

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Tuesday 14 April 2009 09:14:48 Mark Lord wrote:
> Dmitry Torokhov wrote:
> > Hi Mark,
> >
> > On Wednesday 08 April 2009 10:28:09 Mark Lord wrote:
> >> Dmitry,
> >>
> >> I briefly had access to a Twinhan remote control (for Mythtv et al.)
> >> and cobbled something together quickly to make it work.
> >>
> >> But I really don't understand the new hid/input stuff,
> >> so this is undoubtedly a total abomination to your eyes. :)
> >
> > Actually HID is Juri's baby so let's see what he says ;). From my POV
> > we need to update keymap to make it emit proper codes instead of Myth
> > specific ones, but that is a lesser issue.
>
> ..
>
> That's one thing I haven't figured out: how to make this compatible
> with the userspace intput-kbd interface for loading new key maps and stuff.
>

You will need to convert your patch into proper hid_driver and
implement drv->input_mapping() method instead of overriding emitted
events. Then, once HID core is aware about proper mapping, normal
EVIOCGKEYCODE/EVIOCSKEYCODE will work and will allow adjusting
keymap from user space.

I think if you take drivers/hid/hid-belkin.c as a template the
conversion will take you no time.

--
Dmitry

2009-04-14 17:37:32

by Mark Lord

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

Dmitry Torokhov wrote:
> On Tuesday 14 April 2009 09:14:48 Mark Lord wrote:
>> Dmitry Torokhov wrote:
>>> Hi Mark,
>>>
>>> On Wednesday 08 April 2009 10:28:09 Mark Lord wrote:
>>>> Dmitry,
>>>>
>>>> I briefly had access to a Twinhan remote control (for Mythtv et al.)
>>>> and cobbled something together quickly to make it work.
>>>>
>>>> But I really don't understand the new hid/input stuff,
>>>> so this is undoubtedly a total abomination to your eyes. :)
>>> Actually HID is Juri's baby so let's see what he says ;). From my POV
>>> we need to update keymap to make it emit proper codes instead of Myth
>>> specific ones, but that is a lesser issue.
>> ..
>>
>> That's one thing I haven't figured out: how to make this compatible
>> with the userspace intput-kbd interface for loading new key maps and stuff.
>>
>
> You will need to convert your patch into proper hid_driver and
> implement drv->input_mapping() method instead of overriding emitted
> events. Then, once HID core is aware about proper mapping, normal
> EVIOCGKEYCODE/EVIOCSKEYCODE will work and will allow adjusting
> keymap from user space.
..

I tried that earlier, but input-kbd only ever listed a single (wrong)
key in the keymap, and wouldn't allow changing anything.
Obviously there's more to it somewhere, I guess.

> I think if you take drivers/hid/hid-belkin.c as a template the
> conversion will take you no time.
..

Okay, I can have a look at that one. Thanks.

2009-04-15 08:24:13

by Jiri Kosina

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Tue, 14 Apr 2009, Mark Lord wrote:

> > I think if you take drivers/hid/hid-belkin.c as a template the
> > conversion will take you no time.
> Okay, I can have a look at that one. Thanks.

Yes, hid-belking is a good example of trivial driver that sits on a HID
bus for you, as it utilizes the ->input_mapping() callback, which is
probably the only callback from HID core you'd need.

If you encounter any difficulties implementing your driver as a HID bus
driver, please let me know.

--
Jiri Kosina
SUSE Labs

2009-04-15 14:10:49

by Mark Lord

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

Jiri Kosina wrote:
> On Tue, 14 Apr 2009, Mark Lord wrote:
>
>>> I think if you take drivers/hid/hid-belkin.c as a template the
>>> conversion will take you no time.
>> Okay, I can have a look at that one. Thanks.
>
> Yes, hid-belking is a good example of trivial driver that sits on a HID
> bus for you, as it utilizes the ->input_mapping() callback, which is
> probably the only callback from HID core you'd need.
..

Actually, the input-mapping() alone won't do the job here.

This Twinhan remote control sends single-byte codes for most buttons,
but some buttons send multi-byte codes, and we have to discard the
extraneous bytes somehow.

Cheers

2009-04-16 09:24:54

by Jiri Kosina

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Wed, 15 Apr 2009, Mark Lord wrote:

> > Yes, hid-belking is a good example of trivial driver that sits on a HID bus
> > for you, as it utilizes the ->input_mapping() callback, which is probably
> > the only callback from HID core you'd need.
> Actually, the input-mapping() alone won't do the job here.
> This Twinhan remote control sends single-byte codes for most buttons,
> but some buttons send multi-byte codes, and we have to discard the
> extraneous bytes somehow.

If the usages make it through the generic HID layer (depends on the report
descriptor of the device), then just registering hid_driver with ->event()
set to your callback and fixing this on the fly could be enough.

--
Jiri Kosina
SUSE Labs

2009-07-12 16:27:55

by Bruno Prémont

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Thu, 16 April 2009 Jiri Kosina <[email protected]> wrote:
> On Wed, 15 Apr 2009, Mark Lord wrote:
> > > Yes, hid-belking is a good example of trivial driver that sits on
> > > a HID bus for you, as it utilizes the ->input_mapping() callback,
> > > which is probably the only callback from HID core you'd need.
> > Actually, the input-mapping() alone won't do the job here.
> > This Twinhan remote control sends single-byte codes for most
> > buttons, but some buttons send multi-byte codes, and we have to
> > discard the extraneous bytes somehow.
>
> If the usages make it through the generic HID layer (depends on the
> report descriptor of the device), then just registering hid_driver
> with ->event() set to your callback and fixing this on the fly could
> be enough.

I do have such a remote around.

I wrote the below patch to adjust it's key mappings, though I'm not
sure if/how I should deal with the number keys (0..9) with regard to
keyboard layout and/or numlock key.

I tried with KEY_0..KEY_9 (default) as well as KEY_KP0..KEY_KP9 but
neither produces optimal results on my machine (laptop with numlock
disabled and belgian keyboard layout, e.g. KEY_1 => '&' unless shift
is down)

KEY_NUMERIC_0..KEY_NUMERIC_9 are not recognized by Linux console (don't
know if/how userspace understands them)


To disable the dummy ctrl/alt/meta keys the remote sends all the time
as release events (and as press event around power and volume keys)
I do return -1 in input_mapping() and 1 in event(), looking at what
reaches listener on event device this seems to work.
Possibly the whole event() callback is not even needed.


If someone has a better idea for the mapping of some of the keys,
please tell me, especially for the following keys I just took what
did look like eventually matching:
Recall -> KEY_RESTART
Capture -> KEY_PRINT
Record List -> KEY_LIST
Preview -> KEY_PROGRAM
Teletext -> KEY_TEXT

Bruno

---
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7831a03..d972c7d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -152,6 +152,13 @@ config HID_GYRATION
---help---
Support for Gyration remote control.

+config HID_TWINHAN
+ tristate "Twinhan" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for Twinhan IR remote control.
+
config HID_KENSINGTON
tristate "Kensington" if EMBEDDED
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index db35151..9b9271d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
+obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_WACOM) += hid-wacom.o

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f2c21d5..ed8766f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1312,6 +1312,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 6301010..a20fef8 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -403,6 +403,9 @@
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201

+#define USB_VENDOR_ID_TWINHAN 0x6253
+#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
+
#define USB_VENDOR_ID_UCLOGIC 0x5543
#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042

diff --git a/drivers/hid/hid-twinhan.c b/drivers/hid/hid-twinhan.c
new file mode 100644
index 0000000..6f00a67
--- /dev/null
+++ b/drivers/hid/hid-twinhan.c
@@ -0,0 +1,170 @@
+/*
+ * HID driver for TwinHan IR remote control
+ *
+ * Based on hid-gyration.c
+ *
+ * Copyright (c) 2009 Bruno Prémont <[email protected]>
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Remote control key layout + listing:
+ *
+ * Full Screen Power
+ * KEY_SCREEN KEY_POWER2
+ *
+ * 1 2 3
+ * KEY_1 KEY_2 KEY_3
+ *
+ * 4 5 6
+ * KEY_4 KEY_5 KEY_6
+ *
+ * 7 8 9
+ * KEY_7 KEY_8 KEY_9
+ *
+ * REC 0 Favorite
+ * KEY_RECORD KEY_0 KEY_FAVORITES
+ *
+ * Rewind Forward
+ * KEY_REWIND CH+ KEY_FORWARD
+ * KEY_CHANNELUP
+ *
+ * VOL- > VOL+
+ * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP
+ *
+ * CH-
+ * KEY_CHANNELDOWN
+ * Recall Stop
+ * KEY_RESTART KEY_STOP
+ *
+ * Timeshift/Pause Mute Cancel
+ * KEY_PAUSE KEY_MUTE KEY_CANCEL
+ *
+ * Capture Preview EPG
+ * KEY_PRINT KEY_PROGRAM KEY_EPG
+ *
+ * Record List Tab Teletext
+ * KEY_LIST KEY_TAB KEY_TEXT
+ */
+
+#define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
+ return 0;
+
+ // set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ /* Kill the extra keys used for multi-key "power" and "volume" keys
+ * as well as continuously to release CTRL,ALT,META,... keys */
+ case 0x0e0:
+ case 0x0e1:
+ case 0x0e2:
+ case 0x0e3:
+ case 0x0e4:
+ case 0x0e5:
+ case 0x0e6:
+ case 0x0e7:
+ return -1;
+
+ /* Map all keys from Twinhan Remote */
+ case 0x01d: th_map_key_clear(KEY_SCREEN); break;
+ case 0x01e: th_map_key_clear(KEY_KP1); break;
+ case 0x01f: th_map_key_clear(KEY_KP2); break;
+ case 0x020: th_map_key_clear(KEY_KP3); break;
+ case 0x021: th_map_key_clear(KEY_KP4); break;
+ case 0x022: th_map_key_clear(KEY_KP5); break;
+ case 0x023: th_map_key_clear(KEY_KP6); break;
+ case 0x024: th_map_key_clear(KEY_KP7); break;
+ case 0x025: th_map_key_clear(KEY_KP8); break;
+ case 0x026: th_map_key_clear(KEY_KP9); break;
+ case 0x027: th_map_key_clear(KEY_KP0); break;
+ case 0x04a: th_map_key_clear(KEY_RECORD); break;
+ case 0x019: th_map_key_clear(KEY_FAVORITES); break;
+ case 0x00c: th_map_key_clear(KEY_REWIND); break;
+ case 0x011: th_map_key_clear(KEY_FORWARD); break;
+ case 0x04b: th_map_key_clear(KEY_CHANNELUP); break;
+ case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break;
+ case 0x028: th_map_key_clear(KEY_PLAY); break;
+ case 0x006: th_map_key_clear(KEY_RESTART); break;
+ case 0x04d: th_map_key_clear(KEY_STOP); break;
+ case 0x017: th_map_key_clear(KEY_PAUSE); break;
+ case 0x010: th_map_key_clear(KEY_MUTE); break;
+ case 0x029: th_map_key_clear(KEY_CANCEL); break;
+ case 0x013: th_map_key_clear(KEY_PRINT); break;
+ case 0x00e: th_map_key_clear(KEY_PROGRAM); break;
+ case 0x008: th_map_key_clear(KEY_EPG); break;
+ case 0x00f: th_map_key_clear(KEY_LIST); break;
+ case 0x02b: th_map_key_clear(KEY_TAB); break;
+ case 0x004: th_map_key_clear(KEY_TEXT); break;
+ /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */
+ case 0x03f: th_map_key_clear(KEY_POWER2); break;
+ /* Volume down = 0x0e1 + 0x051 */
+ case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break;
+ /* Volume up = 0x0e1 + 0x052 */
+ case 0x052: th_map_key_clear(KEY_VOLUMEUP); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int twinhan_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD)
+ switch (usage->hid & HID_USAGE) {
+ case 0x0e0:
+ case 0x0e1:
+ case 0x0e2:
+ case 0x0e3:
+ case 0x0e4:
+ case 0x0e5:
+ case 0x0e6:
+ case 0x0e7:
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id twinhan_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, twinhan_devices);
+
+static struct hid_driver twinhan_driver = {
+ .name = "twinhan",
+ .id_table = twinhan_devices,
+ .input_mapping = twinhan_input_mapping,
+ .event = twinhan_event,
+};
+
+static int twinhan_init(void)
+{
+ return hid_register_driver(&twinhan_driver);
+}
+
+static void twinhan_exit(void)
+{
+ hid_unregister_driver(&twinhan_driver);
+}
+
+module_init(twinhan_init);
+module_exit(twinhan_exit);
+MODULE_LICENSE("GPL");

2009-07-13 03:42:09

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Sun, Jul 12, 2009 at 06:20:26PM +0200, Bruno Pr?mont wrote:
> On Thu, 16 April 2009 Jiri Kosina <[email protected]> wrote:
> > On Wed, 15 Apr 2009, Mark Lord wrote:
> > > > Yes, hid-belking is a good example of trivial driver that sits on
> > > > a HID bus for you, as it utilizes the ->input_mapping() callback,
> > > > which is probably the only callback from HID core you'd need.
> > > Actually, the input-mapping() alone won't do the job here.
> > > This Twinhan remote control sends single-byte codes for most
> > > buttons, but some buttons send multi-byte codes, and we have to
> > > discard the extraneous bytes somehow.
> >
> > If the usages make it through the generic HID layer (depends on the
> > report descriptor of the device), then just registering hid_driver
> > with ->event() set to your callback and fixing this on the fly could
> > be enough.
>
> I do have such a remote around.
>
> I wrote the below patch to adjust it's key mappings, though I'm not
> sure if/how I should deal with the number keys (0..9) with regard to
> keyboard layout and/or numlock key.
>
> I tried with KEY_0..KEY_9 (default) as well as KEY_KP0..KEY_KP9 but
> neither produces optimal results on my machine (laptop with numlock
> disabled and belgian keyboard layout, e.g. KEY_1 => '&' unless shift
> is down)
> i

That was the reason KEY_NUMERIC_* keycodes were intriduced - they
shuppsed to be unaffected by labuguage keymap or numlock state.

> KEY_NUMERIC_0..KEY_NUMERIC_9 are not recognized by Linux console (don't
> know if/how userspace understands them)
>

They just probably missing from the installed keymap, that's all.

--
Dmitry

2009-07-13 08:53:19

by Jiri Kosina

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Sun, 12 Jul 2009, Bruno Prémont wrote:

> I wrote the below patch to adjust it's key mappings, though I'm not
> sure if/how I should deal with the number keys (0..9) with regard to
> keyboard layout and/or numlock key.
>
> I tried with KEY_0..KEY_9 (default) as well as KEY_KP0..KEY_KP9 but
> neither produces optimal results on my machine (laptop with numlock
> disabled and belgian keyboard layout, e.g. KEY_1 => '&' unless shift
> is down)
>
> KEY_NUMERIC_0..KEY_NUMERIC_9 are not recognized by Linux console (don't
> know if/how userspace understands them)

Are they incorporated in the keymap you have loaded?

> + // set_bit(EV_REP, hi->input->evbit);

Why is this commented out?

Otherwise the patch looks good, so if you send it with proper
Signed-off-by line, I am OK with merging it.

Do you have any idea whether lirc folks have plans to integrate support
for this device to lirc eventually?

Thanks,

--
Jiri Kosina
SUSE Labs

2009-07-13 09:39:23

by Bruno Prémont

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Mon, 13 July 2009 Jiri Kosina <[email protected]> wrote:
> On Sun, 12 Jul 2009, Bruno Prémont wrote:
>
> > I wrote the below patch to adjust it's key mappings, though I'm not
> > sure if/how I should deal with the number keys (0..9) with regard to
> > keyboard layout and/or numlock key.
> >
> > I tried with KEY_0..KEY_9 (default) as well as KEY_KP0..KEY_KP9 but
> > neither produces optimal results on my machine (laptop with numlock
> > disabled and belgian keyboard layout, e.g. KEY_1 => '&' unless shift
> > is down)
> >
> > KEY_NUMERIC_0..KEY_NUMERIC_9 are not recognized by Linux console
> > (don't know if/how userspace understands them)
>
> Are they incorporated in the keymap you have loaded?

Probably not though I have not checked (using be-latin1 from
sys-apps/kbd-1.13-r1, Gentoo) Possibly this kbd version is too old to
know about those keys.

> > + // set_bit(EV_REP, hi->input->evbit);
>
> Why is this commented out?

That was a remaining line from basing on hid-gyration.c
Don't know what it does, looks like related to key repeating but I've
not read enough of HID/Input code to find out. (all my tests were run
with it commented out, so I will drop it unless there is a good reason
to uncomment it)

> Otherwise the patch looks good, so if you send it with proper
> Signed-off-by line, I am OK with merging it.

Will do, using KEY_NUMERIC_*.

> Do you have any idea whether lirc folks have plans to integrate
> support for this device to lirc eventually?

I don't know


With my patch it seems the mappings don't show up for EVIOCGKEYCODE:

int codes[2];
for (codes[0] = 0; codes[0] < 1024; codes[0]++)
if (ioctl(evdev, EVIOCGKEYCODE, codes) >= 0) {
// display
} else
break;

Code block above only displays for codes[0] == 0:
codes = { 0, 388 /* KEY_TEXT */ }

For all other values of codes[0] ioctl returns EINVAL.

Is this expected or should complete mapping table be returned
as it is for generic PS2 PC keyboard (if so, what changes does the
patch need for it)?

Bruno

2009-07-13 11:21:26

by Jiri Kosina

[permalink] [raw]
Subject: Re: Input driver for Twinhan USB 6253:0100 remote control

On Mon, 13 Jul 2009, Bruno Pr?mont wrote:

> > > + // set_bit(EV_REP, hi->input->evbit);
> > Why is this commented out?
> That was a remaining line from basing on hid-gyration.c Don't know what
> it does, looks like related to key repeating but I've not read enough of
> HID/Input code to find out. (all my tests were run with it commented
> out, so I will drop it unless there is a good reason to uncomment it)

Yes, EV_REP is a flag which signals whether the keys produced by the
device in question should be auto-repreated.

> With my patch it seems the mappings don't show up for EVIOCGKEYCODE:
>
> int codes[2];
> for (codes[0] = 0; codes[0] < 1024; codes[0]++)
> if (ioctl(evdev, EVIOCGKEYCODE, codes) >= 0) {
> // display
> } else
> break;
>
> Code block above only displays for codes[0] == 0:
> codes = { 0, 388 /* KEY_TEXT */ }
>
> For all other values of codes[0] ioctl returns EINVAL.
>
> Is this expected or should complete mapping table be returned
> as it is for generic PS2 PC keyboard (if so, what changes does the
> patch need for it)?

The HID core's perception of scancode is the actual HID usage as reported
by the device, inlcuding the page number.

I.e. for your device, the usages would be in 0x70004 - 0x70052 range, not
0-1024 (which is what your current code is checking for).

Also, looking at the patch again -- could you please keep the usage
numbers sorted in the switch-case in twinhan_input_mapping(), so that it's
more readable and compatible with other drivers?

Thanks,

--
Jiri Kosina
SUSE Labs

2009-07-13 12:20:15

by Bruno Prémont

[permalink] [raw]
Subject: [PATCH] HID: Input driver for Twinhan USB 6253:0100 remote control

Add explicit key mappings for TwinHan USB HID remote control.

All dummy Ctrl, Alt, Meta, ... key press/release events generated
by the remote are silenced by "unmapping" them. This makes Power and
Volume keys single-key and strips the regular (even while idle) key
release events for Ctrl, Alt, Meta, ...

Signed-off-by: Bruno Prémont <[email protected]>
---

On Mon, 13 July 2009 Jiri Kosina <[email protected]> wrote:
> > > > + // set_bit(EV_REP, hi->input->evbit);
> > > Why is this commented out?
> > That was a remaining line from basing on hid-gyration.c Don't know
> > what it does, looks like related to key repeating but I've not read
> > enough of HID/Input code to find out. (all my tests were run with
> > it commented out, so I will drop it unless there is a good reason
> > to uncomment it)
>
> Yes, EV_REP is a flag which signals whether the keys produced by the
> device in question should be auto-repreated.

Remote always sends press/release events (and does send them again
repeatedly if the key remains pressed), so this has no effect anyhow,
dropped

> > With my patch it seems the mappings don't show up for EVIOCGKEYCODE:
> >
> > int codes[2];
> > for (codes[0] = 0; codes[0] < 1024; codes[0]++)
> > if (ioctl(evdev, EVIOCGKEYCODE, codes) >= 0) {
> > // display
> > } else
> > break;
> >
> > Code block above only displays for codes[0] == 0:
> > codes = { 0, 388 /* KEY_TEXT */ }
> >
> > For all other values of codes[0] ioctl returns EINVAL.
> >
> > Is this expected or should complete mapping table be returned
> > as it is for generic PS2 PC keyboard (if so, what changes does the
> > patch need for it)?
>
> The HID core's perception of scancode is the actual HID usage as
> reported by the device, inlcuding the page number.
>
> I.e. for your device, the usages would be in 0x70004 - 0x70052 range,
> not 0-1024 (which is what your current code is checking for).

Ok, with the range changed it's fine

> Also, looking at the patch again -- could you please keep the usage
> numbers sorted in the switch-case in twinhan_input_mapping(), so that
> it's more readable and compatible with other drivers?

I sorted them and now return -1 for all keys not present on the remote,
this way the mapping table is "clean" and does not contain default
keyboard keys.


Note: checkpatch complains about the break at line-end but I ignored
those errors as that's common practice for all hid drivers I looked into.


drivers/hid/Kconfig | 7 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-ids.h | 3 +
drivers/hid/hid-twinhan.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 159 insertions(+), 0 deletions(-)
---
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7831a03..d972c7d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -152,6 +152,13 @@ config HID_GYRATION
---help---
Support for Gyration remote control.

+config HID_TWINHAN
+ tristate "Twinhan" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for Twinhan IR remote control.
+
config HID_KENSINGTON
tristate "Kensington" if EMBEDDED
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index db35151..9b9271d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
+obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_WACOM) += hid-wacom.o

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f2c21d5..ed8766f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1312,6 +1312,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 6301010..a20fef8 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -403,6 +403,9 @@
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201

+#define USB_VENDOR_ID_TWINHAN 0x6253
+#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
+
#define USB_VENDOR_ID_UCLOGIC 0x5543
#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042

diff --git a/drivers/hid/hid-twinhan.c b/drivers/hid/hid-twinhan.c
new file mode 100644
index 0000000..0d33c61
--- /dev/null
+++ b/drivers/hid/hid-twinhan.c
@@ -0,0 +1,147 @@
+/*
+ * HID driver for TwinHan IR remote control
+ *
+ * Based on hid-gyration.c
+ *
+ * Copyright (c) 2009 Bruno Prémont <[email protected]>
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Remote control key layout + listing:
+ *
+ * Full Screen Power
+ * KEY_SCREEN KEY_POWER2
+ *
+ * 1 2 3
+ * KEY_NUMERIC_1 KEY_NUMERIC_2 KEY_NUMERIC_3
+ *
+ * 4 5 6
+ * KEY_NUMERIC_4 KEY_NUMERIC_5 KEY_NUMERIC_6
+ *
+ * 7 8 9
+ * KEY_NUMERIC_7 KEY_NUMERIC_8 KEY_NUMERIC_9
+ *
+ * REC 0 Favorite
+ * KEY_RECORD KEY_NUMERIC_0 KEY_FAVORITES
+ *
+ * Rewind Forward
+ * KEY_REWIND CH+ KEY_FORWARD
+ * KEY_CHANNELUP
+ *
+ * VOL- > VOL+
+ * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP
+ *
+ * CH-
+ * KEY_CHANNELDOWN
+ * Recall Stop
+ * KEY_RESTART KEY_STOP
+ *
+ * Timeshift/Pause Mute Cancel
+ * KEY_PAUSE KEY_MUTE KEY_CANCEL
+ *
+ * Capture Preview EPG
+ * KEY_PRINT KEY_PROGRAM KEY_EPG
+ *
+ * Record List Tab Teletext
+ * KEY_LIST KEY_TAB KEY_TEXT
+ */
+
+#define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ /* Map all keys from Twinhan Remote */
+ case 0x004: th_map_key_clear(KEY_TEXT); break;
+ case 0x006: th_map_key_clear(KEY_RESTART); break;
+ case 0x008: th_map_key_clear(KEY_EPG); break;
+ case 0x00c: th_map_key_clear(KEY_REWIND); break;
+ case 0x00e: th_map_key_clear(KEY_PROGRAM); break;
+ case 0x00f: th_map_key_clear(KEY_LIST); break;
+ case 0x010: th_map_key_clear(KEY_MUTE); break;
+ case 0x011: th_map_key_clear(KEY_FORWARD); break;
+ case 0x013: th_map_key_clear(KEY_PRINT); break;
+ case 0x017: th_map_key_clear(KEY_PAUSE); break;
+ case 0x019: th_map_key_clear(KEY_FAVORITES); break;
+ case 0x01d: th_map_key_clear(KEY_SCREEN); break;
+ case 0x01e: th_map_key_clear(KEY_NUMERIC_1); break;
+ case 0x01f: th_map_key_clear(KEY_NUMERIC_2); break;
+ case 0x020: th_map_key_clear(KEY_NUMERIC_3); break;
+ case 0x021: th_map_key_clear(KEY_NUMERIC_4); break;
+ case 0x022: th_map_key_clear(KEY_NUMERIC_5); break;
+ case 0x023: th_map_key_clear(KEY_NUMERIC_6); break;
+ case 0x024: th_map_key_clear(KEY_NUMERIC_7); break;
+ case 0x025: th_map_key_clear(KEY_NUMERIC_8); break;
+ case 0x026: th_map_key_clear(KEY_NUMERIC_9); break;
+ case 0x027: th_map_key_clear(KEY_NUMERIC_0); break;
+ case 0x028: th_map_key_clear(KEY_PLAY); break;
+ case 0x029: th_map_key_clear(KEY_CANCEL); break;
+ case 0x02b: th_map_key_clear(KEY_TAB); break;
+ /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */
+ case 0x03f: th_map_key_clear(KEY_POWER2); break;
+ case 0x04a: th_map_key_clear(KEY_RECORD); break;
+ case 0x04b: th_map_key_clear(KEY_CHANNELUP); break;
+ case 0x04d: th_map_key_clear(KEY_STOP); break;
+ case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break;
+ /* Volume down = 0x0e1 + 0x051 */
+ case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break;
+ /* Volume up = 0x0e1 + 0x052 */
+ case 0x052: th_map_key_clear(KEY_VOLUMEUP); break;
+ /* Kill the extra keys used for multi-key "power" and "volume" keys
+ * as well as continuously to release CTRL,ALT,META,... keys */
+ case 0x0e0:
+ case 0x0e1:
+ case 0x0e2:
+ case 0x0e3:
+ case 0x0e4:
+ case 0x0e5:
+ case 0x0e6:
+ case 0x0e7:
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+static const struct hid_device_id twinhan_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, twinhan_devices);
+
+static struct hid_driver twinhan_driver = {
+ .name = "twinhan",
+ .id_table = twinhan_devices,
+ .input_mapping = twinhan_input_mapping,
+};
+
+static int twinhan_init(void)
+{
+ return hid_register_driver(&twinhan_driver);
+}
+
+static void twinhan_exit(void)
+{
+ hid_unregister_driver(&twinhan_driver);
+}
+
+module_init(twinhan_init);
+module_exit(twinhan_exit);
+MODULE_LICENSE("GPL");

2009-07-14 15:05:26

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] HID: Input driver for Twinhan USB 6253:0100 remote control

On Mon, 13 Jul 2009, Bruno Prémont wrote:

> All dummy Ctrl, Alt, Meta, ... key press/release events generated
> by the remote are silenced by "unmapping" them. This makes Power and
> Volume keys single-key and strips the regular (even while idle) key
> release events for Ctrl, Alt, Meta, ...
>
> Signed-off-by: Bruno Prémont <[email protected]>

Applied, thanks Bruno.

--
Jiri Kosina
SUSE Labs

2009-07-18 14:50:27

by Mark Lord

[permalink] [raw]
Subject: Re: [PATCH] HID: Input driver for Twinhan USB 6253:0100 remote control

Good work, Bruno (and Jiri and Dmitry)!

I know of three people locally that are using my original driver,
and when they next upgrade kernels, they now have Bruno's version
to replace that with.

Thanks!