Jarod Wilson f4da561
[PATCH] hid: support for bluetooth tivo slide remote and usb dongle
Jarod Wilson f4da561
Jarod Wilson f4da561
This patch adds full support for the TiVo Slide Remote, primarily by way
Jarod Wilson f4da561
of extending the existing generic HID support. Only four keys are not
Jarod Wilson f4da561
usages within a standard usage page, but they're easily handled by the
Jarod Wilson f4da561
addition of a HID_UP_TIVOVENDOR usage page. Note that the UP is 0xffff,
Jarod Wilson f4da561
which matches the mask, but its also a valid vendor-specific UP, according
Jarod Wilson f4da561
to the spec.
Jarod Wilson f4da561
Jarod Wilson f4da561
What's actually connected to the computer is a Broadcom-made usb dongle,
Jarod Wilson f4da561
which has an embedded hub, bluetooth adapter, mouse and keyboard devices.
Jarod Wilson f4da561
You pair with the dongle, then the remote sends data that its converted
Jarod Wilson f4da561
into HID on the keyboard interface (the mouse interface doesn't do anything
Jarod Wilson f4da561
interesting right now, so far as I can tell).
Jarod Wilson f4da561
Jarod Wilson f4da561
lsusb for this device:
Jarod Wilson f4da561
Bus 004 Device 005: ID 0a5c:2190 Broadcom Corp.
Jarod Wilson f4da561
Bus 004 Device 004: ID 0a5c:4503 Broadcom Corp.
Jarod Wilson f4da561
Bus 004 Device 003: ID 150a:1201
Jarod Wilson f4da561
Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)
Jarod Wilson f4da561
Jarod Wilson f4da561
Speaking of the keyboard interface, the remote actually does contain a
Jarod Wilson f4da561
keyboard as well. The top slides away, revealing a reasonably functional
Jarod Wilson f4da561
qwerty keyboard (not unlike many slide cell phones), thus the product
Jarod Wilson f4da561
name.
Jarod Wilson f4da561
Jarod Wilson f4da561
Now for some caveats... This device seems to report 0xc (consumer usage
Jarod Wilson f4da561
page) 0x20 ("+10") after most key presses. At the moment, this will simply
Jarod Wilson f4da561
be ignored, but if a mapping for that usage is added, the remote behaves
Jarod Wilson f4da561
very badly (we end up w/a repeating/stuck key until another key is pressed).
Jarod Wilson f4da561
Not quite sure what to do about that one, if that usage does get mapped. I
Jarod Wilson f4da561
guess a device-specific quirk to just ignore it would work.
Jarod Wilson f4da561
Jarod Wilson f4da561
Anyway, the thing is working 100% as expected with this patch right now.
Jarod Wilson f4da561
Jarod Wilson f4da561
Three more things to note... This patch fixes an incorrect mapping of 0xc 0x45,
Jarod Wilson f4da561
which was mapped to KEY_RADIO, which is definitely wrong, but may cause some
Jarod Wilson f4da561
existing device to now report KEY_RIGHT there. Second, there's also an
Jarod Wilson f4da561
unrelated fix for a redundant KERN_DEBUG in a dbg_hid call. Third, the
Jarod Wilson f4da561
additions to HID_UP_GENDESK aren't strictly needed by the remote, but the
Jarod Wilson f4da561
dongle does try to register those, and they're all technically correct, so
Jarod Wilson f4da561
I've included them for the benefit of a device that comes along and
Jarod Wilson f4da561
actually does try to use them.
Jarod Wilson f4da561
Jarod Wilson f4da561
Applies cleanly to hid master, tested w/a 2.6.35.4-based Fedora kernel.
Jarod Wilson f4da561
Jarod Wilson f4da561
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Jarod Wilson f4da561
Jarod Wilson f4da561
---
Jarod Wilson f4da561
 drivers/hid/hid-input.c |   45 ++++++++++++++++++++++++++++++++++++++++-----
Jarod Wilson f4da561
 include/linux/hid.h     |    1 +
Jarod Wilson f4da561
 2 files changed, 41 insertions(+), 5 deletions(-)
Jarod Wilson f4da561
Jarod Wilson f4da561
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
Jarod Wilson f4da561
index 6c03dcc..bd1479e 100644
Jarod Wilson f4da561
--- a/drivers/hid/hid-input.c
Jarod Wilson f4da561
+++ b/drivers/hid/hid-input.c
Jarod Wilson f4da561
@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = {
Jarod Wilson f4da561
 	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
Jarod Wilson f4da561
 	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
Jarod Wilson f4da561
 	115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
Jarod Wilson f4da561
-	122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
+	122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
Jarod Wilson f4da561
 	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
 	unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
 	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
+	unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
Jarod Wilson f4da561
 	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
Jarod Wilson f4da561
 	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
Jarod Wilson f4da561
 };
Jarod Wilson f4da561
@@ -136,7 +136,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
Jarod Wilson f4da561
 
Jarod Wilson f4da561
 		clear_bit(old_keycode, dev->keybit);
Jarod Wilson f4da561
 		set_bit(usage->code, dev->keybit);
Jarod Wilson f4da561
-		dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
Jarod Wilson f4da561
+		dbg_hid("Assigned keycode %d to HID usage code %x\n", keycode, scancode);
Jarod Wilson f4da561
 		/* Set the keybit for the old keycode if the old keycode is used
Jarod Wilson f4da561
 		 * by another key */
Jarod Wilson f4da561
 		if (hidinput_find_key (hid, 0, old_keycode))
Jarod Wilson f4da561
@@ -235,6 +235,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
Jarod Wilson f4da561
 			case 0x1: map_key_clear(KEY_POWER);  break;
Jarod Wilson f4da561
 			case 0x2: map_key_clear(KEY_SLEEP);  break;
Jarod Wilson f4da561
 			case 0x3: map_key_clear(KEY_WAKEUP); break;
Jarod Wilson f4da561
+			case 0x4: map_key_clear(KEY_CONTEXT_MENU); break;
Jarod Wilson f4da561
+			case 0x5: map_key_clear(KEY_MENU); break;
Jarod Wilson f4da561
+			case 0x6: map_key_clear(KEY_PROG1); break;
Jarod Wilson f4da561
+			case 0x7: map_key_clear(KEY_HELP); break;
Jarod Wilson f4da561
+			case 0x8: map_key_clear(KEY_EXIT); break;
Jarod Wilson f4da561
+			case 0x9: map_key_clear(KEY_SELECT); break;
Jarod Wilson f4da561
+			case 0xa: map_key_clear(KEY_RIGHT); break;
Jarod Wilson f4da561
+			case 0xb: map_key_clear(KEY_LEFT); break;
Jarod Wilson f4da561
+			case 0xc: map_key_clear(KEY_UP); break;
Jarod Wilson f4da561
+			case 0xd: map_key_clear(KEY_DOWN); break;
Jarod Wilson f4da561
+			case 0xe: map_key_clear(KEY_POWER2); break;
Jarod Wilson f4da561
+			case 0xf: map_key_clear(KEY_RESTART); break;
Jarod Wilson f4da561
 			default: goto unknown;
Jarod Wilson f4da561
 			}
Jarod Wilson f4da561
 			break;
Jarod Wilson f4da561
@@ -343,12 +355,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
Jarod Wilson f4da561
 	case HID_UP_CONSUMER:	/* USB HUT v1.1, pages 56-62 */
Jarod Wilson f4da561
 		switch (usage->hid & HID_USAGE) {
Jarod Wilson f4da561
 		case 0x000: goto ignore;
Jarod Wilson f4da561
+		case 0x030: map_key_clear(KEY_POWER);		break;
Jarod Wilson f4da561
 		case 0x034: map_key_clear(KEY_SLEEP);		break;
Jarod Wilson f4da561
 		case 0x036: map_key_clear(BTN_MISC);		break;
Jarod Wilson f4da561
 
Jarod Wilson f4da561
 		case 0x040: map_key_clear(KEY_MENU);		break;
Jarod Wilson f4da561
-		case 0x045: map_key_clear(KEY_RADIO);		break;
Jarod Wilson f4da561
-
Jarod Wilson f4da561
+		case 0x041: map_key_clear(KEY_SELECT);		break;
Jarod Wilson f4da561
+		case 0x042: map_key_clear(KEY_UP);		break;
Jarod Wilson f4da561
+		case 0x043: map_key_clear(KEY_DOWN);		break;
Jarod Wilson f4da561
+		case 0x044: map_key_clear(KEY_LEFT);		break;
Jarod Wilson f4da561
+		case 0x045: map_key_clear(KEY_RIGHT);		break;
Jarod Wilson f4da561
+
Jarod Wilson f4da561
+		case 0x069: map_key_clear(KEY_RED);		break;
Jarod Wilson f4da561
+		case 0x06a: map_key_clear(KEY_GREEN);		break;
Jarod Wilson f4da561
+		case 0x06b: map_key_clear(KEY_BLUE);		break;
Jarod Wilson f4da561
+		case 0x06c: map_key_clear(KEY_YELLOW);		break;
Jarod Wilson f4da561
+		case 0x06d: map_key_clear(KEY_ZOOM);		break;
Jarod Wilson f4da561
+
Jarod Wilson f4da561
+		case 0x082: map_key_clear(KEY_VIDEO_NEXT);	break;
Jarod Wilson f4da561
 		case 0x083: map_key_clear(KEY_LAST);		break;
Jarod Wilson f4da561
 		case 0x088: map_key_clear(KEY_PC);		break;
Jarod Wilson f4da561
 		case 0x089: map_key_clear(KEY_TV);		break;
Jarod Wilson f4da561
@@ -390,6 +414,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
Jarod Wilson f4da561
 		case 0x0e5: map_key_clear(KEY_BASSBOOST);	break;
Jarod Wilson f4da561
 		case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
Jarod Wilson f4da561
 		case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
Jarod Wilson f4da561
+		case 0x0f5: map_key_clear(KEY_SLOW);		break;
Jarod Wilson f4da561
 
Jarod Wilson f4da561
 		case 0x182: map_key_clear(KEY_BOOKMARKS);	break;
Jarod Wilson f4da561
 		case 0x183: map_key_clear(KEY_CONFIG);		break;
Jarod Wilson f4da561
@@ -491,6 +516,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
Jarod Wilson f4da561
 		}
Jarod Wilson f4da561
 		break;
Jarod Wilson f4da561
 
Jarod Wilson f4da561
+	case HID_UP_TIVOVENDOR:
Jarod Wilson f4da561
+		switch (usage->hid & HID_USAGE) {
Jarod Wilson f4da561
+		case 0x3d: map_key_clear(KEY_PROG1);	break;
Jarod Wilson f4da561
+		case 0x3e: map_key_clear(KEY_TV);	break;
Jarod Wilson f4da561
+		case 0x41: map_key_clear(KEY_PAGEDOWN);	break;
Jarod Wilson f4da561
+		case 0x42: map_key_clear(KEY_PAGEUP);	break;
Jarod Wilson f4da561
+		default: goto unknown;
Jarod Wilson f4da561
+		}
Jarod Wilson f4da561
+		break;
Jarod Wilson f4da561
+
Jarod Wilson f4da561
 	default:
Jarod Wilson f4da561
 	unknown:
Jarod Wilson f4da561
 		if (field->report_size == 1) {
Jarod Wilson f4da561
diff --git a/include/linux/hid.h b/include/linux/hid.h
Jarod Wilson f4da561
index 42a0f1d..083cfb2 100644
Jarod Wilson f4da561
--- a/include/linux/hid.h
Jarod Wilson f4da561
+++ b/include/linux/hid.h
Jarod Wilson f4da561
@@ -200,6 +200,7 @@ struct hid_item {
Jarod Wilson f4da561
 #define HID_UP_MSVENDOR		0xff000000
Jarod Wilson f4da561
 #define HID_UP_CUSTOM		0x00ff0000
Jarod Wilson f4da561
 #define HID_UP_LOGIVENDOR	0xffbc0000
Jarod Wilson f4da561
+#define HID_UP_TIVOVENDOR	0xffff0000
Jarod Wilson f4da561
 
Jarod Wilson f4da561
 #define HID_USAGE		0x0000ffff
Jarod Wilson f4da561