aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-sony.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2013-06-13 06:03:49 -0400
committerJiri Kosina <jkosina@suse.cz>2013-06-13 06:03:49 -0400
commit078328da5d5dfbd2b1333eb545bd89d6dfa984ef (patch)
treef27e524bca2e6631f788b0ebbf0e44ae03db5d5d /drivers/hid/hid-sony.c
parent40e32ee6e475852f532c847ed1804b87f6531a67 (diff)
HID: fold ps3remote driver into generic Sony driver
Let's follow the structure we are trying to keep for most of the specific HID drivers, and let the separation follow the producing vendor. Merge functionality provided by ps3remote driver into hid-sony. Tested-by: David Dillow <dave@thedillows.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-sony.c')
-rw-r--r--drivers/hid/hid-sony.c184
1 files changed, 182 insertions, 2 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index f1c906176615..ecbc74923d06 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1,11 +1,12 @@
1/* 1/*
2 * HID driver for some sony "special" devices 2 * HID driver for Sony / PS2 / PS3 BD devices.
3 * 3 *
4 * Copyright (c) 1999 Andreas Gal 4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7 * Copyright (c) 2008 Jiri Slaby 7 * Copyright (c) 2008 Jiri Slaby
8 * Copyright (c) 2006-2008 Jiri Kosina 8 * Copyright (c) 2012 David Dillow <dave@thedillows.org>
9 * Copyright (c) 2006-2013 Jiri Kosina
9 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> 10 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
10 */ 11 */
11 12
@@ -16,6 +17,13 @@
16 * any later version. 17 * any later version.
17 */ 18 */
18 19
20/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
21 * a Bluetooth host, the key combination Start+Enter has to be kept pressed
22 * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
23 *
24 * There will be no PIN request from the device.
25 */
26
19#include <linux/device.h> 27#include <linux/device.h>
20#include <linux/hid.h> 28#include <linux/hid.h>
21#include <linux/module.h> 29#include <linux/module.h>
@@ -29,6 +37,7 @@
29#define SIXAXIS_CONTROLLER_USB (1 << 1) 37#define SIXAXIS_CONTROLLER_USB (1 << 1)
30#define SIXAXIS_CONTROLLER_BT (1 << 2) 38#define SIXAXIS_CONTROLLER_BT (1 << 2)
31#define BUZZ_CONTROLLER (1 << 3) 39#define BUZZ_CONTROLLER (1 << 3)
40#define PS3REMOTE (1 << 4)
32 41
33static const u8 sixaxis_rdesc_fixup[] = { 42static const u8 sixaxis_rdesc_fixup[] = {
34 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 43 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
@@ -58,6 +67,122 @@ static const u8 sixaxis_rdesc_fixup2[] = {
58 0xb1, 0x02, 0xc0, 0xc0, 67 0xb1, 0x02, 0xc0, 0xc0,
59}; 68};
60 69
70static __u8 ps3remote_rdesc[] = {
71 0x05, 0x01, /* GUsagePage Generic Desktop */
72 0x09, 0x05, /* LUsage 0x05 [Game Pad] */
73 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */
74
75 /* Use collection 1 for joypad buttons */
76 0xA1, 0x02, /* MCollection Logical (interrelated data) */
77
78 /* Ignore the 1st byte, maybe it is used for a controller
79 * number but it's not needed for correct operation */
80 0x75, 0x08, /* GReportSize 0x08 [8] */
81 0x95, 0x01, /* GReportCount 0x01 [1] */
82 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
83
84 /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
85 * buttons multiple keypresses are allowed */
86 0x05, 0x09, /* GUsagePage Button */
87 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
88 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
89 0x14, /* GLogicalMinimum [0] */
90 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
91 0x75, 0x01, /* GReportSize 0x01 [1] */
92 0x95, 0x18, /* GReportCount 0x18 [24] */
93 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
94
95 0xC0, /* MEndCollection */
96
97 /* Use collection 2 for remote control buttons */
98 0xA1, 0x02, /* MCollection Logical (interrelated data) */
99
100 /* 5th byte is used for remote control buttons */
101 0x05, 0x09, /* GUsagePage Button */
102 0x18, /* LUsageMinimum [No button pressed] */
103 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */
104 0x14, /* GLogicalMinimum [0] */
105 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */
106 0x75, 0x08, /* GReportSize 0x08 [8] */
107 0x95, 0x01, /* GReportCount 0x01 [1] */
108 0x80, /* MInput */
109
110 /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
111 * 0xff and 11th is for press indication */
112 0x75, 0x08, /* GReportSize 0x08 [8] */
113 0x95, 0x06, /* GReportCount 0x06 [6] */
114 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
115
116 /* 12th byte is for battery strength */
117 0x05, 0x06, /* GUsagePage Generic Device Controls */
118 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */
119 0x14, /* GLogicalMinimum [0] */
120 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */
121 0x75, 0x08, /* GReportSize 0x08 [8] */
122 0x95, 0x01, /* GReportCount 0x01 [1] */
123 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
124
125 0xC0, /* MEndCollection */
126
127 0xC0 /* MEndCollection [Game Pad] */
128};
129
130static const unsigned int ps3remote_keymap_joypad_buttons[] = {
131 [0x01] = KEY_SELECT,
132 [0x02] = BTN_THUMBL, /* L3 */
133 [0x03] = BTN_THUMBR, /* R3 */
134 [0x04] = BTN_START,
135 [0x05] = KEY_UP,
136 [0x06] = KEY_RIGHT,
137 [0x07] = KEY_DOWN,
138 [0x08] = KEY_LEFT,
139 [0x09] = BTN_TL2, /* L2 */
140 [0x0a] = BTN_TR2, /* R2 */
141 [0x0b] = BTN_TL, /* L1 */
142 [0x0c] = BTN_TR, /* R1 */
143 [0x0d] = KEY_OPTION, /* options/triangle */
144 [0x0e] = KEY_BACK, /* back/circle */
145 [0x0f] = BTN_0, /* cross */
146 [0x10] = KEY_SCREEN, /* view/square */
147 [0x11] = KEY_HOMEPAGE, /* PS button */
148 [0x14] = KEY_ENTER,
149};
150static const unsigned int ps3remote_keymap_remote_buttons[] = {
151 [0x00] = KEY_1,
152 [0x01] = KEY_2,
153 [0x02] = KEY_3,
154 [0x03] = KEY_4,
155 [0x04] = KEY_5,
156 [0x05] = KEY_6,
157 [0x06] = KEY_7,
158 [0x07] = KEY_8,
159 [0x08] = KEY_9,
160 [0x09] = KEY_0,
161 [0x0e] = KEY_ESC, /* return */
162 [0x0f] = KEY_CLEAR,
163 [0x16] = KEY_EJECTCD,
164 [0x1a] = KEY_MENU, /* top menu */
165 [0x28] = KEY_TIME,
166 [0x30] = KEY_PREVIOUS,
167 [0x31] = KEY_NEXT,
168 [0x32] = KEY_PLAY,
169 [0x33] = KEY_REWIND, /* scan back */
170 [0x34] = KEY_FORWARD, /* scan forward */
171 [0x38] = KEY_STOP,
172 [0x39] = KEY_PAUSE,
173 [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
174 [0x60] = KEY_FRAMEBACK, /* slow/step back */
175 [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
176 [0x63] = KEY_SUBTITLE,
177 [0x64] = KEY_AUDIO,
178 [0x65] = KEY_ANGLE,
179 [0x70] = KEY_INFO, /* display */
180 [0x80] = KEY_BLUE,
181 [0x81] = KEY_RED,
182 [0x82] = KEY_GREEN,
183 [0x83] = KEY_YELLOW,
184};
185
61static const unsigned int buzz_keymap[] = { 186static const unsigned int buzz_keymap[] = {
62 /* The controller has 4 remote buzzers, each with one LED and 5 187 /* The controller has 4 remote buzzers, each with one LED and 5
63 * buttons. 188 * buttons.
@@ -108,6 +233,48 @@ struct buzz_extra {
108 struct led_classdev *leds[4]; 233 struct led_classdev *leds[4];
109}; 234};
110 235
236static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
237 unsigned int *rsize)
238{
239 *rsize = sizeof(ps3remote_rdesc);
240 return ps3remote_rdesc;
241}
242
243static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
244 struct hid_field *field, struct hid_usage *usage,
245 unsigned long **bit, int *max)
246{
247 unsigned int key = usage->hid & HID_USAGE;
248
249 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
250 return -1;
251
252 switch (usage->collection_index) {
253 case 1:
254 if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
255 return -1;
256
257 key = ps3remote_keymap_joypad_buttons[key];
258 if (!key)
259 return -1;
260 break;
261 case 2:
262 if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
263 return -1;
264
265 key = ps3remote_keymap_remote_buttons[key];
266 if (!key)
267 return -1;
268 break;
269 default:
270 return -1;
271 }
272
273 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
274 return 1;
275}
276
277
111/* Sony Vaio VGX has wrongly mouse pointer declared as constant */ 278/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
112static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 279static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
113 unsigned int *rsize) 280 unsigned int *rsize)
@@ -144,6 +311,10 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
144 *rsize = sizeof(sixaxis_rdesc_fixup2); 311 *rsize = sizeof(sixaxis_rdesc_fixup2);
145 memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); 312 memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
146 } 313 }
314
315 if (sc->quirks & PS3REMOTE)
316 return ps3remote_fixup(hdev, rdesc, rsize);
317
147 return rdesc; 318 return rdesc;
148} 319}
149 320
@@ -195,6 +366,9 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
195 return 1; 366 return 1;
196 } 367 }
197 368
369 if (sc->quirks & PS3REMOTE)
370 return ps3remote_mapping(hdev, hi, field, usage, bit, max);
371
198 return -1; 372 return -1;
199} 373}
200 374
@@ -527,6 +701,12 @@ static const struct hid_device_id sony_devices[] = {
527 .driver_data = BUZZ_CONTROLLER }, 701 .driver_data = BUZZ_CONTROLLER },
528 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), 702 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
529 .driver_data = BUZZ_CONTROLLER }, 703 .driver_data = BUZZ_CONTROLLER },
704 /* PS3 BD Remote Control */
705 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
706 .driver_data = PS3REMOTE },
707 /* Logitech Harmony Adapter for PS3 */
708 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
709 .driver_data = PS3REMOTE },
530 { } 710 { }
531}; 711};
532MODULE_DEVICE_TABLE(hid, sony_devices); 712MODULE_DEVICE_TABLE(hid, sony_devices);