aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Dillow <dave@thedillows.org>2012-09-25 17:02:27 -0400
committerJiri Kosina <jkosina@suse.cz>2012-10-01 04:11:48 -0400
commit5844c1cdb630b537a2ecdf74dab2985e51dc1bd9 (patch)
tree7374a3cc5379f68a4c0c95a430bb300f2f7cda44 /drivers/hid
parentcead24c1181ad199354bd08013d0f9d08b66691b (diff)
HID: Add support for Sony PS3 BD Remote Control
The Sony PS3 Blue-ray Disc Remote Control used to be supported by the BlueZ project's user space, but the code that handled it was recently removed as its functionality conflicted with a real HSP implementation and the mapping was thought to be better handled in the kernel. This is a port of the mapping logic from the fakehid driver by Marcel Holtmann to the in-kernel HID layer. We also add support for the Logitech Harmony Adapter for PS3, which emulates the BD Remote. Signed-off-by: David Dillow <dave@thedillows.org> Signed-off-by: Antonio Ospite <ospite@studenti.unina.it> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig13
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c2
-rw-r--r--drivers/hid/hid-ids.h2
-rw-r--r--drivers/hid/hid-ps3remote.c215
5 files changed, 232 insertions, 1 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf49503508d..378be0bdc997 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -534,6 +534,15 @@ config HID_PRIMAX
534 Support for Primax devices that are not fully compliant with the 534 Support for Primax devices that are not fully compliant with the
535 HID standard. 535 HID standard.
536 536
537config HID_PS3REMOTE
538 tristate "Sony PS3 BD Remote Control"
539 depends on BT_HIDP
540 ---help---
541 Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
542 Harmony Adapter for PS3, which connect over Bluetooth.
543
544 Support for the 6-axis controllers is provided by HID_SONY.
545
537config HID_ROCCAT 546config HID_ROCCAT
538 tristate "Roccat device support" 547 tristate "Roccat device support"
539 depends on USB_HID 548 depends on USB_HID
@@ -561,7 +570,9 @@ config HID_SONY
561 tristate "Sony PS3 controller" 570 tristate "Sony PS3 controller"
562 depends on USB_HID 571 depends on USB_HID
563 ---help--- 572 ---help---
564 Support for Sony PS3 controller. 573 Support for Sony PS3 6-axis controllers.
574
575 Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE.
565 576
566config HID_SPEEDLINK 577config HID_SPEEDLINK
567 tristate "Speedlink VAD Cezanne mouse support" 578 tristate "Speedlink VAD Cezanne mouse support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485f88b2..333ed6c961c5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
70obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o 70obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
71obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o 71obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
72obj-$(CONFIG_HID_PRIMAX) += hid-primax.o 72obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
73obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o
73obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ 74obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
74 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ 75 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
75 hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \ 76 hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8bcd168fffae..e4275d4934e4 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1566,6 +1566,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1566 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, 1566 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
1567 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, 1567 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
1568 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, 1568 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
1569 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
1569 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, 1570 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
1570 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, 1571 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
1571 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, 1572 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
@@ -1639,6 +1640,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1639 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, 1640 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
1640 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, 1641 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
1641 { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, 1642 { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
1643 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
1642 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 1644 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
1643 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, 1645 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
1644 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 1646 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1dcb76ff51e3..40411c9d88f0 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -496,6 +496,7 @@
496#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 496#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
497#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 497#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
498#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f 498#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
499#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
499#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a 500#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a
500#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 501#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211
501#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 502#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
@@ -683,6 +684,7 @@
683 684
684#define USB_VENDOR_ID_SONY 0x054c 685#define USB_VENDOR_ID_SONY 0x054c
685#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b 686#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
687#define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306
686#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 688#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
687#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f 689#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
688 690
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
new file mode 100644
index 000000000000..03811e539d71
--- /dev/null
+++ b/drivers/hid/hid-ps3remote.c
@@ -0,0 +1,215 @@
1/*
2 * HID driver for Sony PS3 BD Remote Control
3 *
4 * Copyright (c) 2012 David Dillow <dave@thedillows.org>
5 * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann
6 * and other kernel HID drivers.
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 */
15
16/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
17 * a Bluetooth host, the key combination Start+Enter has to be kept pressed
18 * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
19 *
20 * There will be no PIN request from the device.
21 */
22
23#include <linux/device.h>
24#include <linux/hid.h>
25#include <linux/module.h>
26
27#include "hid-ids.h"
28
29static __u8 ps3remote_rdesc[] = {
30 0x05, 0x01, /* GUsagePage Generic Desktop */
31 0x09, 0x05, /* LUsage 0x05 [Game Pad] */
32 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */
33
34 /* Use collection 1 for joypad buttons */
35 0xA1, 0x02, /* MCollection Logical (interrelated data) */
36
37 /* Ignore the 1st byte, maybe it is used for a controller
38 * number but it's not needed for correct operation */
39 0x75, 0x08, /* GReportSize 0x08 [8] */
40 0x95, 0x01, /* GReportCount 0x01 [1] */
41 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
42
43 /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
44 * buttons multiple keypresses are allowed */
45 0x05, 0x09, /* GUsagePage Button */
46 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
47 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
48 0x14, /* GLogicalMinimum [0] */
49 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
50 0x75, 0x01, /* GReportSize 0x01 [1] */
51 0x95, 0x18, /* GReportCount 0x18 [24] */
52 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
53
54 0xC0, /* MEndCollection */
55
56 /* Use collection 2 for remote control buttons */
57 0xA1, 0x02, /* MCollection Logical (interrelated data) */
58
59 /* 5th byte is used for remote control buttons */
60 0x05, 0x09, /* GUsagePage Button */
61 0x18, /* LUsageMinimum [No button pressed] */
62 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */
63 0x14, /* GLogicalMinimum [0] */
64 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */
65 0x75, 0x08, /* GReportSize 0x08 [8] */
66 0x95, 0x01, /* GReportCount 0x01 [1] */
67 0x80, /* MInput */
68
69 /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
70 * 0xff and 11th is for press indication */
71 0x75, 0x08, /* GReportSize 0x08 [8] */
72 0x95, 0x06, /* GReportCount 0x06 [6] */
73 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
74
75 /* 12th byte is for battery strength */
76 0x05, 0x06, /* GUsagePage Generic Device Controls */
77 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */
78 0x14, /* GLogicalMinimum [0] */
79 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */
80 0x75, 0x08, /* GReportSize 0x08 [8] */
81 0x95, 0x01, /* GReportCount 0x01 [1] */
82 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
83
84 0xC0, /* MEndCollection */
85
86 0xC0 /* MEndCollection [Game Pad] */
87};
88
89static const unsigned int ps3remote_keymap_joypad_buttons[] = {
90 [0x01] = KEY_SELECT,
91 [0x02] = BTN_THUMBL, /* L3 */
92 [0x03] = BTN_THUMBR, /* R3 */
93 [0x04] = BTN_START,
94 [0x05] = KEY_UP,
95 [0x06] = KEY_RIGHT,
96 [0x07] = KEY_DOWN,
97 [0x08] = KEY_LEFT,
98 [0x09] = BTN_TL2, /* L2 */
99 [0x0a] = BTN_TR2, /* R2 */
100 [0x0b] = BTN_TL, /* L1 */
101 [0x0c] = BTN_TR, /* R1 */
102 [0x0d] = KEY_OPTION, /* options/triangle */
103 [0x0e] = KEY_BACK, /* back/circle */
104 [0x0f] = BTN_0, /* cross */
105 [0x10] = KEY_SCREEN, /* view/square */
106 [0x11] = KEY_HOMEPAGE, /* PS button */
107 [0x14] = KEY_ENTER,
108};
109static const unsigned int ps3remote_keymap_remote_buttons[] = {
110 [0x00] = KEY_1,
111 [0x01] = KEY_2,
112 [0x02] = KEY_3,
113 [0x03] = KEY_4,
114 [0x04] = KEY_5,
115 [0x05] = KEY_6,
116 [0x06] = KEY_7,
117 [0x07] = KEY_8,
118 [0x08] = KEY_9,
119 [0x09] = KEY_0,
120 [0x0e] = KEY_ESC, /* return */
121 [0x0f] = KEY_CLEAR,
122 [0x16] = KEY_EJECTCD,
123 [0x1a] = KEY_MENU, /* top menu */
124 [0x28] = KEY_TIME,
125 [0x30] = KEY_PREVIOUS,
126 [0x31] = KEY_NEXT,
127 [0x32] = KEY_PLAY,
128 [0x33] = KEY_REWIND, /* scan back */
129 [0x34] = KEY_FORWARD, /* scan forward */
130 [0x38] = KEY_STOP,
131 [0x39] = KEY_PAUSE,
132 [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
133 [0x60] = KEY_FRAMEBACK, /* slow/step back */
134 [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
135 [0x63] = KEY_SUBTITLE,
136 [0x64] = KEY_AUDIO,
137 [0x65] = KEY_ANGLE,
138 [0x70] = KEY_INFO, /* display */
139 [0x80] = KEY_BLUE,
140 [0x81] = KEY_RED,
141 [0x82] = KEY_GREEN,
142 [0x83] = KEY_YELLOW,
143};
144
145static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
146 unsigned int *rsize)
147{
148 *rsize = sizeof(ps3remote_rdesc);
149 return ps3remote_rdesc;
150}
151
152static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
153 struct hid_field *field, struct hid_usage *usage,
154 unsigned long **bit, int *max)
155{
156 unsigned int key = usage->hid & HID_USAGE;
157
158 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
159 return -1;
160
161 switch (usage->collection_index) {
162 case 1:
163 if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
164 return -1;
165
166 key = ps3remote_keymap_joypad_buttons[key];
167 if (!key)
168 return -1;
169 break;
170 case 2:
171 if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
172 return -1;
173
174 key = ps3remote_keymap_remote_buttons[key];
175 if (!key)
176 return -1;
177 break;
178 default:
179 return -1;
180 }
181
182 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
183 return 1;
184}
185
186static const struct hid_device_id ps3remote_devices[] = {
187 /* PS3 BD Remote Control */
188 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
189 /* Logitech Harmony Adapter for PS3 */
190 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
191 { }
192};
193MODULE_DEVICE_TABLE(hid, ps3remote_devices);
194
195static struct hid_driver ps3remote_driver = {
196 .name = "ps3_remote",
197 .id_table = ps3remote_devices,
198 .report_fixup = ps3remote_fixup,
199 .input_mapping = ps3remote_mapping,
200};
201
202static int __init ps3remote_init(void)
203{
204 return hid_register_driver(&ps3remote_driver);
205}
206
207static void __exit ps3remote_exit(void)
208{
209 hid_unregister_driver(&ps3remote_driver);
210}
211
212module_init(ps3remote_init);
213module_exit(ps3remote_exit);
214MODULE_LICENSE("GPL");
215MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>");