blob: 8020d10ce70389c503517d7b4c6c819802bff0e2 [file] [log] [blame]
Jiri Slabybd28ce02008-06-25 23:47:04 +02001/*
Jiri Kosina078328d2013-06-13 12:03:49 +02002 * HID driver for Sony / PS2 / PS3 BD devices.
Jiri Slabybd28ce02008-06-25 23:47:04 +02003 *
4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
Jiri Slabybd28ce02008-06-25 23:47:04 +02007 * Copyright (c) 2008 Jiri Slaby
Jiri Kosina078328d2013-06-13 12:03:49 +02008 * Copyright (c) 2012 David Dillow <dave@thedillows.org>
9 * Copyright (c) 2006-2013 Jiri Kosina
Colin Leitnerf04d5142013-05-27 23:41:05 +020010 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
Jiri Slabybd28ce02008-06-25 23:47:04 +020011 */
12
13/*
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
17 * any later version.
18 */
19
Jiri Kosina078328d2013-06-13 12:03:49 +020020/* 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
Jiri Slabybd28ce02008-06-25 23:47:04 +020027#include <linux/device.h>
28#include <linux/hid.h>
29#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
Jiri Slabybd28ce02008-06-25 23:47:04 +020031#include <linux/usb.h>
Jiri Kosina40e32ee2013-05-28 11:22:09 +020032#include <linux/leds.h>
Jiri Slabybd28ce02008-06-25 23:47:04 +020033
34#include "hid-ids.h"
35
Sven Eckelmannf1c458c2013-11-19 20:26:29 +010036#define VAIO_RDESC_CONSTANT BIT(0)
37#define SIXAXIS_CONTROLLER_USB BIT(1)
38#define SIXAXIS_CONTROLLER_BT BIT(2)
39#define BUZZ_CONTROLLER BIT(3)
40#define PS3REMOTE BIT(4)
Frank Praznik0bd88dd2014-01-11 15:12:42 -050041#define DUALSHOCK4_CONTROLLER BIT(5)
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +020042
Sven Eckelmann0a286ef2013-11-19 20:26:32 +010043#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER)
44
Simon Wood61ab44b2011-06-10 12:00:26 +020045static const u8 sixaxis_rdesc_fixup[] = {
46 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
47 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
48 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
49};
50
Mauro Carvalho Chehabe57a67d2012-12-14 20:57:34 -020051static const u8 sixaxis_rdesc_fixup2[] = {
52 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02,
53 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00,
54 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
55 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45,
56 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81,
57 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff,
58 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
59 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95,
60 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30,
61 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02,
62 0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81,
63 0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95,
64 0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09,
65 0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02,
66 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02,
67 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95,
68 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
69 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
70 0xb1, 0x02, 0xc0, 0xc0,
71};
72
Jiri Kosina078328d2013-06-13 12:03:49 +020073static __u8 ps3remote_rdesc[] = {
74 0x05, 0x01, /* GUsagePage Generic Desktop */
75 0x09, 0x05, /* LUsage 0x05 [Game Pad] */
76 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */
77
78 /* Use collection 1 for joypad buttons */
79 0xA1, 0x02, /* MCollection Logical (interrelated data) */
80
81 /* Ignore the 1st byte, maybe it is used for a controller
82 * number but it's not needed for correct operation */
83 0x75, 0x08, /* GReportSize 0x08 [8] */
84 0x95, 0x01, /* GReportCount 0x01 [1] */
85 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
86
87 /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
88 * buttons multiple keypresses are allowed */
89 0x05, 0x09, /* GUsagePage Button */
90 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
91 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
92 0x14, /* GLogicalMinimum [0] */
93 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
94 0x75, 0x01, /* GReportSize 0x01 [1] */
95 0x95, 0x18, /* GReportCount 0x18 [24] */
96 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
97
98 0xC0, /* MEndCollection */
99
100 /* Use collection 2 for remote control buttons */
101 0xA1, 0x02, /* MCollection Logical (interrelated data) */
102
103 /* 5th byte is used for remote control buttons */
104 0x05, 0x09, /* GUsagePage Button */
105 0x18, /* LUsageMinimum [No button pressed] */
106 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */
107 0x14, /* GLogicalMinimum [0] */
108 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */
109 0x75, 0x08, /* GReportSize 0x08 [8] */
110 0x95, 0x01, /* GReportCount 0x01 [1] */
111 0x80, /* MInput */
112
113 /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
114 * 0xff and 11th is for press indication */
115 0x75, 0x08, /* GReportSize 0x08 [8] */
116 0x95, 0x06, /* GReportCount 0x06 [6] */
117 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
118
119 /* 12th byte is for battery strength */
120 0x05, 0x06, /* GUsagePage Generic Device Controls */
121 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */
122 0x14, /* GLogicalMinimum [0] */
123 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */
124 0x75, 0x08, /* GReportSize 0x08 [8] */
125 0x95, 0x01, /* GReportCount 0x01 [1] */
126 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
127
128 0xC0, /* MEndCollection */
129
130 0xC0 /* MEndCollection [Game Pad] */
131};
132
133static const unsigned int ps3remote_keymap_joypad_buttons[] = {
134 [0x01] = KEY_SELECT,
135 [0x02] = BTN_THUMBL, /* L3 */
136 [0x03] = BTN_THUMBR, /* R3 */
137 [0x04] = BTN_START,
138 [0x05] = KEY_UP,
139 [0x06] = KEY_RIGHT,
140 [0x07] = KEY_DOWN,
141 [0x08] = KEY_LEFT,
142 [0x09] = BTN_TL2, /* L2 */
143 [0x0a] = BTN_TR2, /* R2 */
144 [0x0b] = BTN_TL, /* L1 */
145 [0x0c] = BTN_TR, /* R1 */
146 [0x0d] = KEY_OPTION, /* options/triangle */
147 [0x0e] = KEY_BACK, /* back/circle */
148 [0x0f] = BTN_0, /* cross */
149 [0x10] = KEY_SCREEN, /* view/square */
150 [0x11] = KEY_HOMEPAGE, /* PS button */
151 [0x14] = KEY_ENTER,
152};
153static const unsigned int ps3remote_keymap_remote_buttons[] = {
154 [0x00] = KEY_1,
155 [0x01] = KEY_2,
156 [0x02] = KEY_3,
157 [0x03] = KEY_4,
158 [0x04] = KEY_5,
159 [0x05] = KEY_6,
160 [0x06] = KEY_7,
161 [0x07] = KEY_8,
162 [0x08] = KEY_9,
163 [0x09] = KEY_0,
164 [0x0e] = KEY_ESC, /* return */
165 [0x0f] = KEY_CLEAR,
166 [0x16] = KEY_EJECTCD,
167 [0x1a] = KEY_MENU, /* top menu */
168 [0x28] = KEY_TIME,
169 [0x30] = KEY_PREVIOUS,
170 [0x31] = KEY_NEXT,
171 [0x32] = KEY_PLAY,
172 [0x33] = KEY_REWIND, /* scan back */
173 [0x34] = KEY_FORWARD, /* scan forward */
174 [0x38] = KEY_STOP,
175 [0x39] = KEY_PAUSE,
176 [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
177 [0x60] = KEY_FRAMEBACK, /* slow/step back */
178 [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
179 [0x63] = KEY_SUBTITLE,
180 [0x64] = KEY_AUDIO,
181 [0x65] = KEY_ANGLE,
182 [0x70] = KEY_INFO, /* display */
183 [0x80] = KEY_BLUE,
184 [0x81] = KEY_RED,
185 [0x82] = KEY_GREEN,
186 [0x83] = KEY_YELLOW,
187};
188
Colin Leitnerf04d5142013-05-27 23:41:05 +0200189static const unsigned int buzz_keymap[] = {
190 /* The controller has 4 remote buzzers, each with one LED and 5
191 * buttons.
192 *
193 * We use the mapping chosen by the controller, which is:
194 *
195 * Key Offset
196 * -------------------
197 * Buzz 1
198 * Blue 5
199 * Orange 4
200 * Green 3
201 * Yellow 2
202 *
203 * So, for example, the orange button on the third buzzer is mapped to
204 * BTN_TRIGGER_HAPPY14
205 */
206 [ 1] = BTN_TRIGGER_HAPPY1,
207 [ 2] = BTN_TRIGGER_HAPPY2,
208 [ 3] = BTN_TRIGGER_HAPPY3,
209 [ 4] = BTN_TRIGGER_HAPPY4,
210 [ 5] = BTN_TRIGGER_HAPPY5,
211 [ 6] = BTN_TRIGGER_HAPPY6,
212 [ 7] = BTN_TRIGGER_HAPPY7,
213 [ 8] = BTN_TRIGGER_HAPPY8,
214 [ 9] = BTN_TRIGGER_HAPPY9,
215 [10] = BTN_TRIGGER_HAPPY10,
216 [11] = BTN_TRIGGER_HAPPY11,
217 [12] = BTN_TRIGGER_HAPPY12,
218 [13] = BTN_TRIGGER_HAPPY13,
219 [14] = BTN_TRIGGER_HAPPY14,
220 [15] = BTN_TRIGGER_HAPPY15,
221 [16] = BTN_TRIGGER_HAPPY16,
222 [17] = BTN_TRIGGER_HAPPY17,
223 [18] = BTN_TRIGGER_HAPPY18,
224 [19] = BTN_TRIGGER_HAPPY19,
225 [20] = BTN_TRIGGER_HAPPY20,
226};
227
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200228struct sony_sc {
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100229 struct hid_device *hdev;
Sven Eckelmann2251b852013-11-19 20:26:31 +0100230 struct led_classdev *leds[4];
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200231 unsigned long quirks;
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100232 struct work_struct state_worker;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200233
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100234#ifdef CONFIG_SONY_FF
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100235 __u8 left;
236 __u8 right;
237#endif
238
Sven Eckelmann2251b852013-11-19 20:26:31 +0100239 __u8 led_state;
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200240};
241
Jiri Kosina078328d2013-06-13 12:03:49 +0200242static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
243 unsigned int *rsize)
244{
245 *rsize = sizeof(ps3remote_rdesc);
246 return ps3remote_rdesc;
247}
248
249static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
250 struct hid_field *field, struct hid_usage *usage,
251 unsigned long **bit, int *max)
252{
253 unsigned int key = usage->hid & HID_USAGE;
254
255 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
256 return -1;
257
258 switch (usage->collection_index) {
259 case 1:
260 if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
261 return -1;
262
263 key = ps3remote_keymap_joypad_buttons[key];
264 if (!key)
265 return -1;
266 break;
267 case 2:
268 if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
269 return -1;
270
271 key = ps3remote_keymap_remote_buttons[key];
272 if (!key)
273 return -1;
274 break;
275 default:
276 return -1;
277 }
278
279 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
280 return 1;
281}
282
283
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200284/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
Nikolai Kondrashov73e40082010-08-06 23:03:06 +0400285static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
286 unsigned int *rsize)
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200287{
288 struct sony_sc *sc = hid_get_drvdata(hdev);
289
Fernando Luis Vázquez Cao99d24902013-01-22 15:20:38 +0900290 /*
291 * Some Sony RF receivers wrongly declare the mouse pointer as a
292 * a constant non-data variable.
293 */
294 if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
295 /* usage page: generic desktop controls */
296 /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
297 /* usage: mouse */
298 rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
299 /* input (usage page for x,y axes): constant, variable, relative */
300 rdesc[54] == 0x81 && rdesc[55] == 0x07) {
Fernando Luis Vázquez Caoa46491842013-01-15 19:40:48 +0900301 hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
Fernando Luis Vázquez Cao99d24902013-01-22 15:20:38 +0900302 /* input: data, variable, relative */
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200303 rdesc[55] = 0x06;
304 }
Simon Wood61ab44b2011-06-10 12:00:26 +0200305
306 /* The HID descriptor exposed over BT has a trailing zero byte */
307 if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
308 ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
309 rdesc[83] == 0x75) {
310 hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
311 memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
312 sizeof(sixaxis_rdesc_fixup));
Mauro Carvalho Chehabe57a67d2012-12-14 20:57:34 -0200313 } else if (sc->quirks & SIXAXIS_CONTROLLER_USB &&
314 *rsize > sizeof(sixaxis_rdesc_fixup2)) {
315 hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n",
316 *rsize, (int)sizeof(sixaxis_rdesc_fixup2));
317 *rsize = sizeof(sixaxis_rdesc_fixup2);
318 memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
Simon Wood61ab44b2011-06-10 12:00:26 +0200319 }
Jiri Kosina078328d2013-06-13 12:03:49 +0200320
321 if (sc->quirks & PS3REMOTE)
322 return ps3remote_fixup(hdev, rdesc, rsize);
323
Nikolai Kondrashov73e40082010-08-06 23:03:06 +0400324 return rdesc;
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200325}
326
Simon Woodc9e4d872011-06-10 12:00:27 +0200327static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
328 __u8 *rd, int size)
329{
330 struct sony_sc *sc = hid_get_drvdata(hdev);
331
332 /* Sixaxis HID report has acclerometers/gyro with MSByte first, this
333 * has to be BYTE_SWAPPED before passing up to joystick interface
334 */
335 if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
336 rd[0] == 0x01 && size == 49) {
337 swap(rd[41], rd[42]);
338 swap(rd[43], rd[44]);
339 swap(rd[45], rd[46]);
340 swap(rd[47], rd[48]);
341 }
342
343 return 0;
344}
345
Colin Leitnerf04d5142013-05-27 23:41:05 +0200346static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
347 struct hid_field *field, struct hid_usage *usage,
348 unsigned long **bit, int *max)
349{
350 struct sony_sc *sc = hid_get_drvdata(hdev);
351
352 if (sc->quirks & BUZZ_CONTROLLER) {
353 unsigned int key = usage->hid & HID_USAGE;
354
355 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
356 return -1;
357
358 switch (usage->collection_index) {
359 case 1:
360 if (key >= ARRAY_SIZE(buzz_keymap))
361 return -1;
362
363 key = buzz_keymap[key];
364 if (!key)
365 return -1;
366 break;
367 default:
368 return -1;
369 }
370
371 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
372 return 1;
373 }
374
Jiri Kosina078328d2013-06-13 12:03:49 +0200375 if (sc->quirks & PS3REMOTE)
376 return ps3remote_mapping(hdev, hi, field, usage, bit, max);
377
Benjamin Tissoires6f498012013-07-24 16:53:07 +0200378 /* Let hid-core decide for the others */
379 return 0;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200380}
381
Antonio Ospite5710fab2011-02-20 18:26:45 +0100382/*
383 * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
384 * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
385 * so we need to override that forcing HID Output Reports on the Control EP.
386 *
387 * There is also another issue about HID Output Reports via USB, the Sixaxis
388 * does not want the report_id as part of the data packet, so we have to
389 * discard buf[0] when sending the actual control message, even for numbered
390 * reports, humpf!
391 */
Antonio Ospite569b10a2010-10-19 16:13:10 +0200392static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
393 size_t count, unsigned char report_type)
394{
395 struct usb_interface *intf = to_usb_interface(hid->dev.parent);
396 struct usb_device *dev = interface_to_usbdev(intf);
397 struct usb_host_interface *interface = intf->cur_altsetting;
398 int report_id = buf[0];
399 int ret;
400
Antonio Ospite5710fab2011-02-20 18:26:45 +0100401 if (report_type == HID_OUTPUT_REPORT) {
402 /* Don't send the Report ID */
403 buf++;
404 count--;
405 }
406
Antonio Ospite569b10a2010-10-19 16:13:10 +0200407 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
408 HID_REQ_SET_REPORT,
409 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
410 ((report_type + 1) << 8) | report_id,
411 interface->desc.bInterfaceNumber, buf, count,
412 USB_CTRL_SET_TIMEOUT);
413
Antonio Ospite5710fab2011-02-20 18:26:45 +0100414 /* Count also the Report ID, in case of an Output report. */
415 if (ret > 0 && report_type == HID_OUTPUT_REPORT)
416 ret++;
417
Antonio Ospite569b10a2010-10-19 16:13:10 +0200418 return ret;
419}
420
Jiri Slabybd28ce02008-06-25 23:47:04 +0200421/*
422 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
423 * to "operational". Without this, the ps3 controller will not report any
424 * events.
425 */
Antonio Ospite816651a2010-05-03 22:15:55 +0200426static int sixaxis_set_operational_usb(struct hid_device *hdev)
Jiri Slabybd28ce02008-06-25 23:47:04 +0200427{
Jiri Slabybd28ce02008-06-25 23:47:04 +0200428 int ret;
429 char *buf = kmalloc(18, GFP_KERNEL);
430
431 if (!buf)
432 return -ENOMEM;
433
Benjamin Tissoiresf204828a2013-09-11 22:12:25 +0200434 ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT);
435
Jiri Slabybd28ce02008-06-25 23:47:04 +0200436 if (ret < 0)
Joe Perches4291ee32010-12-09 19:29:03 -0800437 hid_err(hdev, "can't set operational mode\n");
Jiri Slabybd28ce02008-06-25 23:47:04 +0200438
439 kfree(buf);
440
441 return ret;
442}
443
Antonio Ospite816651a2010-05-03 22:15:55 +0200444static int sixaxis_set_operational_bt(struct hid_device *hdev)
Bastien Noceraf9ce7c22010-01-20 12:01:53 +0000445{
Antonio Ospitefddb33f2010-05-03 17:19:03 +0200446 unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
Bastien Noceraf9ce7c22010-01-20 12:01:53 +0000447 return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
448}
449
Colin Leitnerf04d5142013-05-27 23:41:05 +0200450static void buzz_set_leds(struct hid_device *hdev, int leds)
451{
452 struct list_head *report_list =
453 &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
454 struct hid_report *report = list_entry(report_list->next,
455 struct hid_report, list);
456 __s32 *value = report->field[0]->value;
457
458 value[0] = 0x00;
459 value[1] = (leds & 1) ? 0xff : 0x00;
460 value[2] = (leds & 2) ? 0xff : 0x00;
461 value[3] = (leds & 4) ? 0xff : 0x00;
462 value[4] = (leds & 8) ? 0xff : 0x00;
463 value[5] = 0x00;
464 value[6] = 0x00;
465 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
466}
467
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100468static void sony_set_leds(struct hid_device *hdev, __u8 leds)
469{
470 struct sony_sc *drv_data = hid_get_drvdata(hdev);
471
472 if (drv_data->quirks & BUZZ_CONTROLLER) {
473 buzz_set_leds(hdev, leds);
474 } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) {
475 drv_data->led_state = leds;
476 schedule_work(&drv_data->state_worker);
477 }
478}
479
Sven Eckelmannc5382512013-11-19 20:26:30 +0100480static void sony_led_set_brightness(struct led_classdev *led,
Colin Leitnerf04d5142013-05-27 23:41:05 +0200481 enum led_brightness value)
482{
483 struct device *dev = led->dev->parent;
484 struct hid_device *hdev = container_of(dev, struct hid_device, dev);
485 struct sony_sc *drv_data;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200486
487 int n;
488
489 drv_data = hid_get_drvdata(hdev);
Sven Eckelmann2251b852013-11-19 20:26:31 +0100490 if (!drv_data) {
Colin Leitnerf04d5142013-05-27 23:41:05 +0200491 hid_err(hdev, "No device data\n");
492 return;
493 }
Colin Leitnerf04d5142013-05-27 23:41:05 +0200494
495 for (n = 0; n < 4; n++) {
Sven Eckelmann2251b852013-11-19 20:26:31 +0100496 if (led == drv_data->leds[n]) {
497 int on = !!(drv_data->led_state & (1 << n));
Colin Leitnerf04d5142013-05-27 23:41:05 +0200498 if (value == LED_OFF && on) {
Sven Eckelmann2251b852013-11-19 20:26:31 +0100499 drv_data->led_state &= ~(1 << n);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100500 sony_set_leds(hdev, drv_data->led_state);
Colin Leitnerf04d5142013-05-27 23:41:05 +0200501 } else if (value != LED_OFF && !on) {
Sven Eckelmann2251b852013-11-19 20:26:31 +0100502 drv_data->led_state |= (1 << n);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100503 sony_set_leds(hdev, drv_data->led_state);
Colin Leitnerf04d5142013-05-27 23:41:05 +0200504 }
505 break;
506 }
507 }
508}
509
Sven Eckelmannc5382512013-11-19 20:26:30 +0100510static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
Colin Leitnerf04d5142013-05-27 23:41:05 +0200511{
512 struct device *dev = led->dev->parent;
513 struct hid_device *hdev = container_of(dev, struct hid_device, dev);
514 struct sony_sc *drv_data;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200515
516 int n;
517 int on = 0;
518
519 drv_data = hid_get_drvdata(hdev);
Sven Eckelmann2251b852013-11-19 20:26:31 +0100520 if (!drv_data) {
Colin Leitnerf04d5142013-05-27 23:41:05 +0200521 hid_err(hdev, "No device data\n");
522 return LED_OFF;
523 }
Colin Leitnerf04d5142013-05-27 23:41:05 +0200524
525 for (n = 0; n < 4; n++) {
Sven Eckelmann2251b852013-11-19 20:26:31 +0100526 if (led == drv_data->leds[n]) {
527 on = !!(drv_data->led_state & (1 << n));
Colin Leitnerf04d5142013-05-27 23:41:05 +0200528 break;
529 }
530 }
531
532 return on ? LED_FULL : LED_OFF;
533}
Colin Leitnerf04d5142013-05-27 23:41:05 +0200534
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100535static void sony_leds_remove(struct hid_device *hdev)
536{
537 struct sony_sc *drv_data;
538 struct led_classdev *led;
539 int n;
540
541 drv_data = hid_get_drvdata(hdev);
542 BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
543
544 for (n = 0; n < 4; n++) {
545 led = drv_data->leds[n];
546 drv_data->leds[n] = NULL;
547 if (!led)
548 continue;
549 led_classdev_unregister(led);
550 kfree(led);
551 }
552}
553
Sven Eckelmannc5382512013-11-19 20:26:30 +0100554static int sony_leds_init(struct hid_device *hdev)
Colin Leitnerf04d5142013-05-27 23:41:05 +0200555{
556 struct sony_sc *drv_data;
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200557 int n, ret = 0;
558 struct led_classdev *led;
559 size_t name_sz;
560 char *name;
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100561 size_t name_len;
562 const char *name_fmt;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200563
564 drv_data = hid_get_drvdata(hdev);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100565 BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
Colin Leitnerf04d5142013-05-27 23:41:05 +0200566
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100567 if (drv_data->quirks & BUZZ_CONTROLLER) {
568 name_len = strlen("::buzz#");
569 name_fmt = "%s::buzz%d";
570 /* Validate expected report characteristics. */
571 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
572 return -ENODEV;
573 } else {
574 name_len = strlen("::sony#");
575 name_fmt = "%s::sony%d";
576 }
Kees Cook9446edb2013-09-11 21:56:52 +0200577
Colin Leitnerf04d5142013-05-27 23:41:05 +0200578 /* Clear LEDs as we have no way of reading their initial state. This is
579 * only relevant if the driver is loaded after somebody actively set the
580 * LEDs to on */
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100581 sony_set_leds(hdev, 0x00);
Colin Leitnerf04d5142013-05-27 23:41:05 +0200582
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100583 name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200584
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200585 for (n = 0; n < 4; n++) {
586 led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
587 if (!led) {
588 hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
Julia Lawall8cd5fcd2013-12-29 23:47:27 +0100589 ret = -ENOMEM;
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200590 goto error_leds;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200591 }
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200592
593 name = (void *)(&led[1]);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100594 snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200595 led->name = name;
596 led->brightness = 0;
597 led->max_brightness = 1;
Sven Eckelmannc5382512013-11-19 20:26:30 +0100598 led->brightness_get = sony_led_get_brightness;
599 led->brightness_set = sony_led_set_brightness;
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200600
Julia Lawall8cd5fcd2013-12-29 23:47:27 +0100601 ret = led_classdev_register(&hdev->dev, led);
602 if (ret) {
Jiri Kosina40e32ee2013-05-28 11:22:09 +0200603 hid_err(hdev, "Failed to register LED %d\n", n);
604 kfree(led);
605 goto error_leds;
606 }
607
Sven Eckelmann2251b852013-11-19 20:26:31 +0100608 drv_data->leds[n] = led;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200609 }
Colin Leitnerf04d5142013-05-27 23:41:05 +0200610
611 return ret;
612
Colin Leitnerf04d5142013-05-27 23:41:05 +0200613error_leds:
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100614 sony_leds_remove(hdev);
Colin Leitnerf04d5142013-05-27 23:41:05 +0200615
Colin Leitnerf04d5142013-05-27 23:41:05 +0200616 return ret;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200617}
618
Sven Eckelmann92b5c412013-11-19 20:26:28 +0100619static void sony_state_worker(struct work_struct *work)
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100620{
Sven Eckelmann92b5c412013-11-19 20:26:28 +0100621 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100622 unsigned char buf[] = {
623 0x01,
624 0x00, 0xff, 0x00, 0xff, 0x00,
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100625 0x00, 0x00, 0x00, 0x00, 0x00,
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100626 0xff, 0x27, 0x10, 0x00, 0x32,
627 0xff, 0x27, 0x10, 0x00, 0x32,
628 0xff, 0x27, 0x10, 0x00, 0x32,
629 0xff, 0x27, 0x10, 0x00, 0x32,
630 0x00, 0x00, 0x00, 0x00, 0x00
631 };
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100632
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100633#ifdef CONFIG_SONY_FF
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500634 buf[3] = sc->right ? 1 : 0;
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100635 buf[5] = sc->left;
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100636#endif
637
638 buf[10] |= (sc->led_state & 0xf) << 1;
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100639
640 sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
641 HID_OUTPUT_REPORT);
642}
643
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500644static void dualshock4_state_worker(struct work_struct *work)
645{
646 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
647 unsigned char buf[] = {
648 0x05,
649 0x03, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00,
656 };
657
658#ifdef CONFIG_SONY_FF
659 buf[4] = sc->right;
660 buf[5] = sc->left;
661#endif
662
663 sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
664 HID_OUTPUT_REPORT);
665}
666
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100667#ifdef CONFIG_SONY_FF
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100668static int sony_play_effect(struct input_dev *dev, void *data,
669 struct ff_effect *effect)
670{
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100671 struct hid_device *hid = input_get_drvdata(dev);
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100672 struct sony_sc *sc = hid_get_drvdata(hid);
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100673
674 if (effect->type != FF_RUMBLE)
675 return 0;
676
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100677 sc->left = effect->u.rumble.strong_magnitude / 256;
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500678 sc->right = effect->u.rumble.weak_magnitude / 256;
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100679
Sven Eckelmann92b5c412013-11-19 20:26:28 +0100680 schedule_work(&sc->state_worker);
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100681 return 0;
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100682}
683
684static int sony_init_ff(struct hid_device *hdev)
685{
686 struct hid_input *hidinput = list_entry(hdev->inputs.next,
687 struct hid_input, list);
688 struct input_dev *input_dev = hidinput->input;
689
690 input_set_capability(input_dev, EV_FF, FF_RUMBLE);
691 return input_ff_create_memless(input_dev, NULL, sony_play_effect);
692}
693
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100694static void sony_destroy_ff(struct hid_device *hdev)
695{
696 struct sony_sc *sc = hid_get_drvdata(hdev);
697
Sven Eckelmann92b5c412013-11-19 20:26:28 +0100698 cancel_work_sync(&sc->state_worker);
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100699}
700
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100701#else
702static int sony_init_ff(struct hid_device *hdev)
703{
704 return 0;
705}
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100706
707static void sony_destroy_ff(struct hid_device *hdev)
708{
709}
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100710#endif
711
Jiri Slabybd28ce02008-06-25 23:47:04 +0200712static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
713{
714 int ret;
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200715 unsigned long quirks = id->driver_data;
716 struct sony_sc *sc;
Colin Leitnerf04d5142013-05-27 23:41:05 +0200717 unsigned int connect_mask = HID_CONNECT_DEFAULT;
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200718
Benjamin Tissoiresabf832b2013-07-24 19:38:04 +0200719 sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200720 if (sc == NULL) {
Joe Perches4291ee32010-12-09 19:29:03 -0800721 hid_err(hdev, "can't alloc sony descriptor\n");
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200722 return -ENOMEM;
723 }
724
725 sc->quirks = quirks;
726 hid_set_drvdata(hdev, sc);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100727 sc->hdev = hdev;
Jiri Slabybd28ce02008-06-25 23:47:04 +0200728
Jiri Slabybd28ce02008-06-25 23:47:04 +0200729 ret = hid_parse(hdev);
730 if (ret) {
Joe Perches4291ee32010-12-09 19:29:03 -0800731 hid_err(hdev, "parse failed\n");
Benjamin Tissoiresabf832b2013-07-24 19:38:04 +0200732 return ret;
Jiri Slabybd28ce02008-06-25 23:47:04 +0200733 }
734
Colin Leitnerf04d5142013-05-27 23:41:05 +0200735 if (sc->quirks & VAIO_RDESC_CONSTANT)
736 connect_mask |= HID_CONNECT_HIDDEV_FORCE;
737 else if (sc->quirks & SIXAXIS_CONTROLLER_USB)
738 connect_mask |= HID_CONNECT_HIDDEV_FORCE;
739 else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
740 connect_mask |= HID_CONNECT_HIDDEV_FORCE;
741
742 ret = hid_hw_start(hdev, connect_mask);
Jiri Slabybd28ce02008-06-25 23:47:04 +0200743 if (ret) {
Joe Perches4291ee32010-12-09 19:29:03 -0800744 hid_err(hdev, "hw start failed\n");
Benjamin Tissoiresabf832b2013-07-24 19:38:04 +0200745 return ret;
Jiri Slabybd28ce02008-06-25 23:47:04 +0200746 }
747
Antonio Ospite569b10a2010-10-19 16:13:10 +0200748 if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
749 hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
Antonio Ospite816651a2010-05-03 22:15:55 +0200750 ret = sixaxis_set_operational_usb(hdev);
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100751 INIT_WORK(&sc->state_worker, sony_state_worker);
Antonio Ospite569b10a2010-10-19 16:13:10 +0200752 }
Antonio Ospite816651a2010-05-03 22:15:55 +0200753 else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
754 ret = sixaxis_set_operational_bt(hdev);
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500755 else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
Bastien Noceraf9ce7c22010-01-20 12:01:53 +0000756 ret = 0;
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500757 INIT_WORK(&sc->state_worker, dualshock4_state_worker);
758 } else {
759 ret = 0;
760 }
Bastien Noceraf9ce7c22010-01-20 12:01:53 +0000761
Jiri Kosina4dfdc462008-12-30 00:49:59 +0100762 if (ret < 0)
Jiri Slabybd28ce02008-06-25 23:47:04 +0200763 goto err_stop;
764
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100765 if (sc->quirks & SONY_LED_SUPPORT) {
766 ret = sony_leds_init(hdev);
767 if (ret < 0)
768 goto err_stop;
769 }
770
Sven Eckelmanna08c22c2013-11-09 19:25:57 +0100771 ret = sony_init_ff(hdev);
772 if (ret < 0)
773 goto err_stop;
774
Jiri Slabybd28ce02008-06-25 23:47:04 +0200775 return 0;
776err_stop:
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100777 if (sc->quirks & SONY_LED_SUPPORT)
778 sony_leds_remove(hdev);
Jiri Slabybd28ce02008-06-25 23:47:04 +0200779 hid_hw_stop(hdev);
Jiri Slabybd28ce02008-06-25 23:47:04 +0200780 return ret;
781}
782
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200783static void sony_remove(struct hid_device *hdev)
784{
Colin Leitnerf04d5142013-05-27 23:41:05 +0200785 struct sony_sc *sc = hid_get_drvdata(hdev);
786
Sven Eckelmann0a286ef2013-11-19 20:26:32 +0100787 if (sc->quirks & SONY_LED_SUPPORT)
Sven Eckelmannc5382512013-11-19 20:26:30 +0100788 sony_leds_remove(hdev);
Colin Leitnerf04d5142013-05-27 23:41:05 +0200789
Sven Eckelmann9f323b62013-11-17 20:38:21 +0100790 sony_destroy_ff(hdev);
791
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200792 hid_hw_stop(hdev);
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200793}
794
Jiri Slabybd28ce02008-06-25 23:47:04 +0200795static const struct hid_device_id sony_devices[] = {
Antonio Ospite816651a2010-05-03 22:15:55 +0200796 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
797 .driver_data = SIXAXIS_CONTROLLER_USB },
Jiri Kosina35dca5b2011-04-28 15:43:13 +0200798 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
799 .driver_data = SIXAXIS_CONTROLLER_USB },
Antonio Ospite816651a2010-05-03 22:15:55 +0200800 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
801 .driver_data = SIXAXIS_CONTROLLER_BT },
Jiri Kosinacc6e0bb2008-10-23 12:58:38 +0200802 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
803 .driver_data = VAIO_RDESC_CONSTANT },
Fernando Luis Vázquez Caoa46491842013-01-15 19:40:48 +0900804 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
805 .driver_data = VAIO_RDESC_CONSTANT },
Colin Leitnerf04d5142013-05-27 23:41:05 +0200806 /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
807 * Logitech joystick from the device descriptor. */
808 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
809 .driver_data = BUZZ_CONTROLLER },
810 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
811 .driver_data = BUZZ_CONTROLLER },
Jiri Kosina078328d2013-06-13 12:03:49 +0200812 /* PS3 BD Remote Control */
813 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
814 .driver_data = PS3REMOTE },
815 /* Logitech Harmony Adapter for PS3 */
816 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
817 .driver_data = PS3REMOTE },
Frank Praznik0bd88dd2014-01-11 15:12:42 -0500818 /* Sony Dualshock 4 controllers for PS4 */
819 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
820 .driver_data = DUALSHOCK4_CONTROLLER },
821 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
822 .driver_data = DUALSHOCK4_CONTROLLER },
Jiri Slabybd28ce02008-06-25 23:47:04 +0200823 { }
824};
825MODULE_DEVICE_TABLE(hid, sony_devices);
826
827static struct hid_driver sony_driver = {
Colin Leitnerf04d5142013-05-27 23:41:05 +0200828 .name = "sony",
829 .id_table = sony_devices,
830 .input_mapping = sony_mapping,
831 .probe = sony_probe,
832 .remove = sony_remove,
833 .report_fixup = sony_report_fixup,
834 .raw_event = sony_raw_event
Jiri Slabybd28ce02008-06-25 23:47:04 +0200835};
H Hartley Sweetenf4254582012-12-17 15:28:26 -0700836module_hid_driver(sony_driver);
Jiri Slabybd28ce02008-06-25 23:47:04 +0200837
Jiri Slabybd28ce02008-06-25 23:47:04 +0200838MODULE_LICENSE("GPL");