1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * X-Box gamepad driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
6*4882a593Smuzhiyun * 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
7*4882a593Smuzhiyun * Steven Toth <steve@toth.demon.co.uk>,
8*4882a593Smuzhiyun * Franz Lehner <franz@caos.at>,
9*4882a593Smuzhiyun * Ivan Hawkes <blackhawk@ivanhawkes.com>
10*4882a593Smuzhiyun * 2005 Dominic Cerquetti <binary1230@yahoo.com>
11*4882a593Smuzhiyun * 2006 Adam Buchbinder <adam.buchbinder@gmail.com>
12*4882a593Smuzhiyun * 2007 Jan Kratochvil <honza@jikos.cz>
13*4882a593Smuzhiyun * 2010 Christoph Fritz <chf.fritz@googlemail.com>
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * This driver is based on:
16*4882a593Smuzhiyun * - information from http://euc.jp/periphs/xbox-controller.ja.html
17*4882a593Smuzhiyun * - the iForce driver drivers/char/joystick/iforce.c
18*4882a593Smuzhiyun * - the skeleton-driver drivers/usb/usb-skeleton.c
19*4882a593Smuzhiyun * - Xbox 360 information http://www.free60.org/wiki/Gamepad
20*4882a593Smuzhiyun * - Xbox One information https://github.com/quantus/xbox-one-controller-protocol
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Thanks to:
23*4882a593Smuzhiyun * - ITO Takayuki for providing essential xpad information on his website
24*4882a593Smuzhiyun * - Vojtech Pavlik - iforce driver / input subsystem
25*4882a593Smuzhiyun * - Greg Kroah-Hartman - usb-skeleton driver
26*4882a593Smuzhiyun * - XBOX Linux project - extra USB id's
27*4882a593Smuzhiyun * - Pekka Pöyry (quantus) - Xbox One controller reverse engineering
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * TODO:
30*4882a593Smuzhiyun * - fine tune axes (especially trigger axes)
31*4882a593Smuzhiyun * - fix "analog" buttons (reported as digital now)
32*4882a593Smuzhiyun * - get rumble working
33*4882a593Smuzhiyun * - need USB IDs for other dance pads
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * History:
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * 2002-06-27 - 0.0.1 : first version, just said "XBOX HID controller"
38*4882a593Smuzhiyun *
39*4882a593Smuzhiyun * 2002-07-02 - 0.0.2 : basic working version
40*4882a593Smuzhiyun * - all axes and 9 of the 10 buttons work (german InterAct device)
41*4882a593Smuzhiyun * - the black button does not work
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * 2002-07-14 - 0.0.3 : rework by Vojtech Pavlik
44*4882a593Smuzhiyun * - indentation fixes
45*4882a593Smuzhiyun * - usb + input init sequence fixes
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * 2002-07-16 - 0.0.4 : minor changes, merge with Vojtech's v0.0.3
48*4882a593Smuzhiyun * - verified the lack of HID and report descriptors
49*4882a593Smuzhiyun * - verified that ALL buttons WORK
50*4882a593Smuzhiyun * - fixed d-pad to axes mapping
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * 2002-07-17 - 0.0.5 : simplified d-pad handling
53*4882a593Smuzhiyun *
54*4882a593Smuzhiyun * 2004-10-02 - 0.0.6 : DDR pad support
55*4882a593Smuzhiyun * - borrowed from the XBOX linux kernel
56*4882a593Smuzhiyun * - USB id's for commonly used dance pads are present
57*4882a593Smuzhiyun * - dance pads will map D-PAD to buttons, not axes
58*4882a593Smuzhiyun * - pass the module paramater 'dpad_to_buttons' to force
59*4882a593Smuzhiyun * the D-PAD to map to buttons if your pad is not detected
60*4882a593Smuzhiyun *
61*4882a593Smuzhiyun * Later changes can be tracked in SCM.
62*4882a593Smuzhiyun */
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #include <linux/kernel.h>
65*4882a593Smuzhiyun #include <linux/input.h>
66*4882a593Smuzhiyun #include <linux/rcupdate.h>
67*4882a593Smuzhiyun #include <linux/slab.h>
68*4882a593Smuzhiyun #include <linux/stat.h>
69*4882a593Smuzhiyun #include <linux/module.h>
70*4882a593Smuzhiyun #include <linux/usb/input.h>
71*4882a593Smuzhiyun #include <linux/usb/quirks.h>
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define XPAD_PKT_LEN 64
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun * xbox d-pads should map to buttons, as is required for DDR pads
77*4882a593Smuzhiyun * but we map them to axes when possible to simplify things
78*4882a593Smuzhiyun */
79*4882a593Smuzhiyun #define MAP_DPAD_TO_BUTTONS (1 << 0)
80*4882a593Smuzhiyun #define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
81*4882a593Smuzhiyun #define MAP_STICKS_TO_NULL (1 << 2)
82*4882a593Smuzhiyun #define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
83*4882a593Smuzhiyun MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun #define XTYPE_XBOX 0
86*4882a593Smuzhiyun #define XTYPE_XBOX360 1
87*4882a593Smuzhiyun #define XTYPE_XBOX360W 2
88*4882a593Smuzhiyun #define XTYPE_XBOXONE 3
89*4882a593Smuzhiyun #define XTYPE_UNKNOWN 4
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun static bool dpad_to_buttons;
92*4882a593Smuzhiyun module_param(dpad_to_buttons, bool, S_IRUGO);
93*4882a593Smuzhiyun MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun static bool triggers_to_buttons;
96*4882a593Smuzhiyun module_param(triggers_to_buttons, bool, S_IRUGO);
97*4882a593Smuzhiyun MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads");
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun static bool sticks_to_null;
100*4882a593Smuzhiyun module_param(sticks_to_null, bool, S_IRUGO);
101*4882a593Smuzhiyun MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun static bool auto_poweroff = true;
104*4882a593Smuzhiyun module_param(auto_poweroff, bool, S_IWUSR | S_IRUGO);
105*4882a593Smuzhiyun MODULE_PARM_DESC(auto_poweroff, "Power off wireless controllers on suspend");
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun static const struct xpad_device {
108*4882a593Smuzhiyun u16 idVendor;
109*4882a593Smuzhiyun u16 idProduct;
110*4882a593Smuzhiyun char *name;
111*4882a593Smuzhiyun u8 mapping;
112*4882a593Smuzhiyun u8 xtype;
113*4882a593Smuzhiyun } xpad_device[] = {
114*4882a593Smuzhiyun { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
115*4882a593Smuzhiyun { 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 },
116*4882a593Smuzhiyun { 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 },
117*4882a593Smuzhiyun { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX },
118*4882a593Smuzhiyun { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX },
119*4882a593Smuzhiyun { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
120*4882a593Smuzhiyun { 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX },
121*4882a593Smuzhiyun { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 },
122*4882a593Smuzhiyun { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX },
123*4882a593Smuzhiyun { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
124*4882a593Smuzhiyun { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
125*4882a593Smuzhiyun { 0x045e, 0x0288, "Microsoft Xbox Controller S v2", 0, XTYPE_XBOX },
126*4882a593Smuzhiyun { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
127*4882a593Smuzhiyun { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
128*4882a593Smuzhiyun { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 },
129*4882a593Smuzhiyun { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
130*4882a593Smuzhiyun { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
131*4882a593Smuzhiyun { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
132*4882a593Smuzhiyun { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
133*4882a593Smuzhiyun { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
134*4882a593Smuzhiyun { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
135*4882a593Smuzhiyun { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
136*4882a593Smuzhiyun { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
137*4882a593Smuzhiyun { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
138*4882a593Smuzhiyun { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
139*4882a593Smuzhiyun { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
140*4882a593Smuzhiyun { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX },
141*4882a593Smuzhiyun { 0x046d, 0xca8a, "Logitech Precision Vibration Feedback Wheel", 0, XTYPE_XBOX },
142*4882a593Smuzhiyun { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel", 0, XTYPE_XBOX360 },
143*4882a593Smuzhiyun { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 },
144*4882a593Smuzhiyun { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
145*4882a593Smuzhiyun { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX },
146*4882a593Smuzhiyun { 0x05fe, 0x3030, "Chic Controller", 0, XTYPE_XBOX },
147*4882a593Smuzhiyun { 0x05fe, 0x3031, "Chic Controller", 0, XTYPE_XBOX },
148*4882a593Smuzhiyun { 0x062a, 0x0020, "Logic3 Xbox GamePad", 0, XTYPE_XBOX },
149*4882a593Smuzhiyun { 0x062a, 0x0033, "Competition Pro Steering Wheel", 0, XTYPE_XBOX },
150*4882a593Smuzhiyun { 0x06a3, 0x0200, "Saitek Racing Wheel", 0, XTYPE_XBOX },
151*4882a593Smuzhiyun { 0x06a3, 0x0201, "Saitek Adrenalin", 0, XTYPE_XBOX },
152*4882a593Smuzhiyun { 0x06a3, 0xf51a, "Saitek P3600", 0, XTYPE_XBOX360 },
153*4882a593Smuzhiyun { 0x0738, 0x4506, "Mad Catz 4506 Wireless Controller", 0, XTYPE_XBOX },
154*4882a593Smuzhiyun { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX },
155*4882a593Smuzhiyun { 0x0738, 0x4520, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX },
156*4882a593Smuzhiyun { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX },
157*4882a593Smuzhiyun { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX },
158*4882a593Smuzhiyun { 0x0738, 0x4530, "Mad Catz Universal MC2 Racing Wheel and Pedals", 0, XTYPE_XBOX },
159*4882a593Smuzhiyun { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX },
160*4882a593Smuzhiyun { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
161*4882a593Smuzhiyun { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX },
162*4882a593Smuzhiyun { 0x0738, 0x4586, "Mad Catz MicroCon Wireless Controller", 0, XTYPE_XBOX },
163*4882a593Smuzhiyun { 0x0738, 0x4588, "Mad Catz Blaster", 0, XTYPE_XBOX },
164*4882a593Smuzhiyun { 0x0738, 0x45ff, "Mad Catz Beat Pad (w/ Handle)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
165*4882a593Smuzhiyun { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
166*4882a593Smuzhiyun { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE", 0, XTYPE_XBOX360 },
167*4882a593Smuzhiyun { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
168*4882a593Smuzhiyun { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
169*4882a593Smuzhiyun { 0x0738, 0x4736, "Mad Catz MicroCon Gamepad", 0, XTYPE_XBOX360 },
170*4882a593Smuzhiyun { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
171*4882a593Smuzhiyun { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 },
172*4882a593Smuzhiyun { 0x0738, 0x4743, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
173*4882a593Smuzhiyun { 0x0738, 0x4758, "Mad Catz Arcade Game Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
174*4882a593Smuzhiyun { 0x0738, 0x4a01, "Mad Catz FightStick TE 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
175*4882a593Smuzhiyun { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
176*4882a593Smuzhiyun { 0x0738, 0x9871, "Mad Catz Portable Drum", 0, XTYPE_XBOX360 },
177*4882a593Smuzhiyun { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 },
178*4882a593Smuzhiyun { 0x0738, 0xb738, "Mad Catz MVC2TE Stick 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
179*4882a593Smuzhiyun { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 },
180*4882a593Smuzhiyun { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 },
181*4882a593Smuzhiyun { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 },
182*4882a593Smuzhiyun { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 },
183*4882a593Smuzhiyun { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 },
184*4882a593Smuzhiyun { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 },
185*4882a593Smuzhiyun { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX },
186*4882a593Smuzhiyun { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX },
187*4882a593Smuzhiyun { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
188*4882a593Smuzhiyun { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX },
189*4882a593Smuzhiyun { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
190*4882a593Smuzhiyun { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
191*4882a593Smuzhiyun { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
192*4882a593Smuzhiyun { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
193*4882a593Smuzhiyun { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
194*4882a593Smuzhiyun { 0x0e4c, 0x1103, "Radica Gamester Reflex", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX },
195*4882a593Smuzhiyun { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
196*4882a593Smuzhiyun { 0x0e4c, 0x3510, "Radica Gamester", 0, XTYPE_XBOX },
197*4882a593Smuzhiyun { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
198*4882a593Smuzhiyun { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX },
199*4882a593Smuzhiyun { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX },
200*4882a593Smuzhiyun { 0x0e6f, 0x0008, "After Glow Pro Controller", 0, XTYPE_XBOX },
201*4882a593Smuzhiyun { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
202*4882a593Smuzhiyun { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
203*4882a593Smuzhiyun { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller", 0, XTYPE_XBOX360 },
204*4882a593Smuzhiyun { 0x0e6f, 0x0131, "PDP EA Sports Controller", 0, XTYPE_XBOX360 },
205*4882a593Smuzhiyun { 0x0e6f, 0x0133, "Xbox 360 Wired Controller", 0, XTYPE_XBOX360 },
206*4882a593Smuzhiyun { 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
207*4882a593Smuzhiyun { 0x0e6f, 0x013a, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
208*4882a593Smuzhiyun { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE },
209*4882a593Smuzhiyun { 0x0e6f, 0x0147, "PDP Marvel Xbox One Controller", 0, XTYPE_XBOXONE },
210*4882a593Smuzhiyun { 0x0e6f, 0x015c, "PDP Xbox One Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
211*4882a593Smuzhiyun { 0x0e6f, 0x0161, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
212*4882a593Smuzhiyun { 0x0e6f, 0x0162, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
213*4882a593Smuzhiyun { 0x0e6f, 0x0163, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
214*4882a593Smuzhiyun { 0x0e6f, 0x0164, "PDP Battlefield One", 0, XTYPE_XBOXONE },
215*4882a593Smuzhiyun { 0x0e6f, 0x0165, "PDP Titanfall 2", 0, XTYPE_XBOXONE },
216*4882a593Smuzhiyun { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
217*4882a593Smuzhiyun { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
218*4882a593Smuzhiyun { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
219*4882a593Smuzhiyun { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE },
220*4882a593Smuzhiyun { 0x0e6f, 0x02a0, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
221*4882a593Smuzhiyun { 0x0e6f, 0x02a1, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
222*4882a593Smuzhiyun { 0x0e6f, 0x02a2, "PDP Wired Controller for Xbox One - Crimson Red", 0, XTYPE_XBOXONE },
223*4882a593Smuzhiyun { 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
224*4882a593Smuzhiyun { 0x0e6f, 0x02a6, "PDP Wired Controller for Xbox One - Camo Series", 0, XTYPE_XBOXONE },
225*4882a593Smuzhiyun { 0x0e6f, 0x02a7, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
226*4882a593Smuzhiyun { 0x0e6f, 0x02a8, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
227*4882a593Smuzhiyun { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
228*4882a593Smuzhiyun { 0x0e6f, 0x02ad, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
229*4882a593Smuzhiyun { 0x0e6f, 0x02b3, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
230*4882a593Smuzhiyun { 0x0e6f, 0x02b8, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
231*4882a593Smuzhiyun { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
232*4882a593Smuzhiyun { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE },
233*4882a593Smuzhiyun { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
234*4882a593Smuzhiyun { 0x0e6f, 0x0413, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
235*4882a593Smuzhiyun { 0x0e6f, 0x0501, "PDP Xbox 360 Controller", 0, XTYPE_XBOX360 },
236*4882a593Smuzhiyun { 0x0e6f, 0xf900, "PDP Afterglow AX.1", 0, XTYPE_XBOX360 },
237*4882a593Smuzhiyun { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX },
238*4882a593Smuzhiyun { 0x0e8f, 0x3008, "Generic xbox control (dealextreme)", 0, XTYPE_XBOX },
239*4882a593Smuzhiyun { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 },
240*4882a593Smuzhiyun { 0x0f0d, 0x000c, "Hori PadEX Turbo", 0, XTYPE_XBOX360 },
241*4882a593Smuzhiyun { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
242*4882a593Smuzhiyun { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
243*4882a593Smuzhiyun { 0x0f0d, 0x001b, "Hori Real Arcade Pro VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
244*4882a593Smuzhiyun { 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
245*4882a593Smuzhiyun { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE },
246*4882a593Smuzhiyun { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
247*4882a593Smuzhiyun { 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
248*4882a593Smuzhiyun { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX },
249*4882a593Smuzhiyun { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
250*4882a593Smuzhiyun { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
251*4882a593Smuzhiyun { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
252*4882a593Smuzhiyun { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
253*4882a593Smuzhiyun { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
254*4882a593Smuzhiyun { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
255*4882a593Smuzhiyun { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
256*4882a593Smuzhiyun { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
257*4882a593Smuzhiyun { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
258*4882a593Smuzhiyun { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
259*4882a593Smuzhiyun { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
260*4882a593Smuzhiyun { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
261*4882a593Smuzhiyun { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
262*4882a593Smuzhiyun { 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 },
263*4882a593Smuzhiyun { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
264*4882a593Smuzhiyun { 0x146b, 0x0604, "Bigben Interactive DAIJA Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
265*4882a593Smuzhiyun { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
266*4882a593Smuzhiyun { 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
267*4882a593Smuzhiyun { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
268*4882a593Smuzhiyun { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
269*4882a593Smuzhiyun { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
270*4882a593Smuzhiyun { 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
271*4882a593Smuzhiyun { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 },
272*4882a593Smuzhiyun { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 },
273*4882a593Smuzhiyun { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 },
274*4882a593Smuzhiyun { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 },
275*4882a593Smuzhiyun { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
276*4882a593Smuzhiyun { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
277*4882a593Smuzhiyun { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
278*4882a593Smuzhiyun { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
279*4882a593Smuzhiyun { 0x1bad, 0xf018, "Mad Catz Street Fighter IV SE Fighting Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
280*4882a593Smuzhiyun { 0x1bad, 0xf019, "Mad Catz Brawlstick for Xbox 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
281*4882a593Smuzhiyun { 0x1bad, 0xf021, "Mad Cats Ghost Recon FS GamePad", 0, XTYPE_XBOX360 },
282*4882a593Smuzhiyun { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)", 0, XTYPE_XBOX360 },
283*4882a593Smuzhiyun { 0x1bad, 0xf025, "Mad Catz Call Of Duty", 0, XTYPE_XBOX360 },
284*4882a593Smuzhiyun { 0x1bad, 0xf027, "Mad Catz FPS Pro", 0, XTYPE_XBOX360 },
285*4882a593Smuzhiyun { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 },
286*4882a593Smuzhiyun { 0x1bad, 0xf02e, "Mad Catz Fightpad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
287*4882a593Smuzhiyun { 0x1bad, 0xf030, "Mad Catz Xbox 360 MC2 MicroCon Racing Wheel", 0, XTYPE_XBOX360 },
288*4882a593Smuzhiyun { 0x1bad, 0xf036, "Mad Catz MicroCon GamePad Pro", 0, XTYPE_XBOX360 },
289*4882a593Smuzhiyun { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 },
290*4882a593Smuzhiyun { 0x1bad, 0xf039, "Mad Catz MvC2 TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
291*4882a593Smuzhiyun { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
292*4882a593Smuzhiyun { 0x1bad, 0xf03d, "Street Fighter IV Arcade Stick TE - Chun Li", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
293*4882a593Smuzhiyun { 0x1bad, 0xf03e, "Mad Catz MLG FightStick TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
294*4882a593Smuzhiyun { 0x1bad, 0xf03f, "Mad Catz FightStick SoulCaliber", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
295*4882a593Smuzhiyun { 0x1bad, 0xf042, "Mad Catz FightStick TES+", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
296*4882a593Smuzhiyun { 0x1bad, 0xf080, "Mad Catz FightStick TE2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
297*4882a593Smuzhiyun { 0x1bad, 0xf501, "HoriPad EX2 Turbo", 0, XTYPE_XBOX360 },
298*4882a593Smuzhiyun { 0x1bad, 0xf502, "Hori Real Arcade Pro.VX SA", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
299*4882a593Smuzhiyun { 0x1bad, 0xf503, "Hori Fighting Stick VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
300*4882a593Smuzhiyun { 0x1bad, 0xf504, "Hori Real Arcade Pro. EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
301*4882a593Smuzhiyun { 0x1bad, 0xf505, "Hori Fighting Stick EX2B", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
302*4882a593Smuzhiyun { 0x1bad, 0xf506, "Hori Real Arcade Pro.EX Premium VLX", 0, XTYPE_XBOX360 },
303*4882a593Smuzhiyun { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 },
304*4882a593Smuzhiyun { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 },
305*4882a593Smuzhiyun { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 },
306*4882a593Smuzhiyun { 0x1bad, 0xf904, "PDP Versus Fighting Pad", 0, XTYPE_XBOX360 },
307*4882a593Smuzhiyun { 0x1bad, 0xf906, "MortalKombat FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
308*4882a593Smuzhiyun { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 },
309*4882a593Smuzhiyun { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
310*4882a593Smuzhiyun { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
311*4882a593Smuzhiyun { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
312*4882a593Smuzhiyun { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
313*4882a593Smuzhiyun { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
314*4882a593Smuzhiyun { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
315*4882a593Smuzhiyun { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
316*4882a593Smuzhiyun { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
317*4882a593Smuzhiyun { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
318*4882a593Smuzhiyun { 0x24c6, 0x530a, "Xbox 360 Pro EX Controller", 0, XTYPE_XBOX360 },
319*4882a593Smuzhiyun { 0x24c6, 0x531a, "PowerA Pro Ex", 0, XTYPE_XBOX360 },
320*4882a593Smuzhiyun { 0x24c6, 0x5397, "FUS1ON Tournament Controller", 0, XTYPE_XBOX360 },
321*4882a593Smuzhiyun { 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE },
322*4882a593Smuzhiyun { 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE },
323*4882a593Smuzhiyun { 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE },
324*4882a593Smuzhiyun { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 },
325*4882a593Smuzhiyun { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 },
326*4882a593Smuzhiyun { 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
327*4882a593Smuzhiyun { 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
328*4882a593Smuzhiyun { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
329*4882a593Smuzhiyun { 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
330*4882a593Smuzhiyun { 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 },
331*4882a593Smuzhiyun { 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
332*4882a593Smuzhiyun { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE },
333*4882a593Smuzhiyun { 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE },
334*4882a593Smuzhiyun { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
335*4882a593Smuzhiyun { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 },
336*4882a593Smuzhiyun { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
337*4882a593Smuzhiyun { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
338*4882a593Smuzhiyun { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
339*4882a593Smuzhiyun { 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 },
340*4882a593Smuzhiyun { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
341*4882a593Smuzhiyun { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
342*4882a593Smuzhiyun { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 },
343*4882a593Smuzhiyun { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 },
344*4882a593Smuzhiyun { 0x31e3, 0x1220, "Wooting Two HE", 0, XTYPE_XBOX360 },
345*4882a593Smuzhiyun { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 },
346*4882a593Smuzhiyun { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 },
347*4882a593Smuzhiyun { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 },
348*4882a593Smuzhiyun { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
349*4882a593Smuzhiyun { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
350*4882a593Smuzhiyun { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
351*4882a593Smuzhiyun };
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* buttons shared with xbox and xbox360 */
354*4882a593Smuzhiyun static const signed short xpad_common_btn[] = {
355*4882a593Smuzhiyun BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */
356*4882a593Smuzhiyun BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
357*4882a593Smuzhiyun -1 /* terminating entry */
358*4882a593Smuzhiyun };
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /* original xbox controllers only */
361*4882a593Smuzhiyun static const signed short xpad_btn[] = {
362*4882a593Smuzhiyun BTN_C, BTN_Z, /* "analog" buttons */
363*4882a593Smuzhiyun -1 /* terminating entry */
364*4882a593Smuzhiyun };
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /* used when dpad is mapped to buttons */
367*4882a593Smuzhiyun static const signed short xpad_btn_pad[] = {
368*4882a593Smuzhiyun BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2, /* d-pad left, right */
369*4882a593Smuzhiyun BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* d-pad up, down */
370*4882a593Smuzhiyun -1 /* terminating entry */
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /* used when triggers are mapped to buttons */
374*4882a593Smuzhiyun static const signed short xpad_btn_triggers[] = {
375*4882a593Smuzhiyun BTN_TL2, BTN_TR2, /* triggers left/right */
376*4882a593Smuzhiyun -1
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun static const signed short xpad360_btn[] = { /* buttons for x360 controller */
380*4882a593Smuzhiyun BTN_TL, BTN_TR, /* Button LB/RB */
381*4882a593Smuzhiyun BTN_MODE, /* The big X button */
382*4882a593Smuzhiyun -1
383*4882a593Smuzhiyun };
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun static const signed short xpad_abs[] = {
386*4882a593Smuzhiyun ABS_X, ABS_Y, /* left stick */
387*4882a593Smuzhiyun ABS_RX, ABS_RY, /* right stick */
388*4882a593Smuzhiyun -1 /* terminating entry */
389*4882a593Smuzhiyun };
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* used when dpad is mapped to axes */
392*4882a593Smuzhiyun static const signed short xpad_abs_pad[] = {
393*4882a593Smuzhiyun ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */
394*4882a593Smuzhiyun -1 /* terminating entry */
395*4882a593Smuzhiyun };
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /* used when triggers are mapped to axes */
398*4882a593Smuzhiyun static const signed short xpad_abs_triggers[] = {
399*4882a593Smuzhiyun ABS_Z, ABS_RZ, /* triggers left/right */
400*4882a593Smuzhiyun -1
401*4882a593Smuzhiyun };
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /*
404*4882a593Smuzhiyun * Xbox 360 has a vendor-specific class, so we cannot match it with only
405*4882a593Smuzhiyun * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
406*4882a593Smuzhiyun * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
407*4882a593Smuzhiyun * wireless controllers have protocol 129.
408*4882a593Smuzhiyun */
409*4882a593Smuzhiyun #define XPAD_XBOX360_VENDOR_PROTOCOL(vend, pr) \
410*4882a593Smuzhiyun .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
411*4882a593Smuzhiyun .idVendor = (vend), \
412*4882a593Smuzhiyun .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
413*4882a593Smuzhiyun .bInterfaceSubClass = 93, \
414*4882a593Smuzhiyun .bInterfaceProtocol = (pr)
415*4882a593Smuzhiyun #define XPAD_XBOX360_VENDOR(vend) \
416*4882a593Smuzhiyun { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 1) }, \
417*4882a593Smuzhiyun { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 129) }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* The Xbox One controller uses subclass 71 and protocol 208. */
420*4882a593Smuzhiyun #define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \
421*4882a593Smuzhiyun .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
422*4882a593Smuzhiyun .idVendor = (vend), \
423*4882a593Smuzhiyun .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
424*4882a593Smuzhiyun .bInterfaceSubClass = 71, \
425*4882a593Smuzhiyun .bInterfaceProtocol = (pr)
426*4882a593Smuzhiyun #define XPAD_XBOXONE_VENDOR(vend) \
427*4882a593Smuzhiyun { XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun static const struct usb_device_id xpad_table[] = {
430*4882a593Smuzhiyun { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
431*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */
432*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */
433*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */
434*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
435*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
436*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
437*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */
438*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */
439*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
440*4882a593Smuzhiyun { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
441*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */
442*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */
443*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */
444*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
445*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
446*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
447*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
448*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
449*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
450*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
451*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
452*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
453*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
454*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */
455*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */
456*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */
457*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
458*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
459*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
460*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */
461*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */
462*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
463*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
464*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */
465*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */
466*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */
467*4882a593Smuzhiyun XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */
468*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */
469*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */
470*4882a593Smuzhiyun XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */
471*4882a593Smuzhiyun { }
472*4882a593Smuzhiyun };
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, xpad_table);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun struct xboxone_init_packet {
477*4882a593Smuzhiyun u16 idVendor;
478*4882a593Smuzhiyun u16 idProduct;
479*4882a593Smuzhiyun const u8 *data;
480*4882a593Smuzhiyun u8 len;
481*4882a593Smuzhiyun };
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun #define XBOXONE_INIT_PKT(_vid, _pid, _data) \
484*4882a593Smuzhiyun { \
485*4882a593Smuzhiyun .idVendor = (_vid), \
486*4882a593Smuzhiyun .idProduct = (_pid), \
487*4882a593Smuzhiyun .data = (_data), \
488*4882a593Smuzhiyun .len = ARRAY_SIZE(_data), \
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /*
493*4882a593Smuzhiyun * This packet is required for all Xbox One pads with 2015
494*4882a593Smuzhiyun * or later firmware installed (or present from the factory).
495*4882a593Smuzhiyun */
496*4882a593Smuzhiyun static const u8 xboxone_fw2015_init[] = {
497*4882a593Smuzhiyun 0x05, 0x20, 0x00, 0x01, 0x00
498*4882a593Smuzhiyun };
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun /*
501*4882a593Smuzhiyun * This packet is required for Xbox One S (0x045e:0x02ea)
502*4882a593Smuzhiyun * and Xbox One Elite Series 2 (0x045e:0x0b00) pads to
503*4882a593Smuzhiyun * initialize the controller that was previously used in
504*4882a593Smuzhiyun * Bluetooth mode.
505*4882a593Smuzhiyun */
506*4882a593Smuzhiyun static const u8 xboxone_s_init[] = {
507*4882a593Smuzhiyun 0x05, 0x20, 0x00, 0x0f, 0x06
508*4882a593Smuzhiyun };
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /*
511*4882a593Smuzhiyun * This packet is required for the Titanfall 2 Xbox One pads
512*4882a593Smuzhiyun * (0x0e6f:0x0165) to finish initialization and for Hori pads
513*4882a593Smuzhiyun * (0x0f0d:0x0067) to make the analog sticks work.
514*4882a593Smuzhiyun */
515*4882a593Smuzhiyun static const u8 xboxone_hori_init[] = {
516*4882a593Smuzhiyun 0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
517*4882a593Smuzhiyun 0x00, 0x00, 0x00, 0x80, 0x00
518*4882a593Smuzhiyun };
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /*
521*4882a593Smuzhiyun * This packet is required for most (all?) of the PDP pads to start
522*4882a593Smuzhiyun * sending input reports. These pads include: (0x0e6f:0x02ab),
523*4882a593Smuzhiyun * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun static const u8 xboxone_pdp_init1[] = {
526*4882a593Smuzhiyun 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
527*4882a593Smuzhiyun };
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /*
530*4882a593Smuzhiyun * This packet is required for most (all?) of the PDP pads to start
531*4882a593Smuzhiyun * sending input reports. These pads include: (0x0e6f:0x02ab),
532*4882a593Smuzhiyun * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
533*4882a593Smuzhiyun */
534*4882a593Smuzhiyun static const u8 xboxone_pdp_init2[] = {
535*4882a593Smuzhiyun 0x06, 0x20, 0x00, 0x02, 0x01, 0x00
536*4882a593Smuzhiyun };
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /*
539*4882a593Smuzhiyun * A specific rumble packet is required for some PowerA pads to start
540*4882a593Smuzhiyun * sending input reports. One of those pads is (0x24c6:0x543a).
541*4882a593Smuzhiyun */
542*4882a593Smuzhiyun static const u8 xboxone_rumblebegin_init[] = {
543*4882a593Smuzhiyun 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
544*4882a593Smuzhiyun 0x1D, 0x1D, 0xFF, 0x00, 0x00
545*4882a593Smuzhiyun };
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /*
548*4882a593Smuzhiyun * A rumble packet with zero FF intensity will immediately
549*4882a593Smuzhiyun * terminate the rumbling required to init PowerA pads.
550*4882a593Smuzhiyun * This should happen fast enough that the motors don't
551*4882a593Smuzhiyun * spin up to enough speed to actually vibrate the gamepad.
552*4882a593Smuzhiyun */
553*4882a593Smuzhiyun static const u8 xboxone_rumbleend_init[] = {
554*4882a593Smuzhiyun 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
555*4882a593Smuzhiyun 0x00, 0x00, 0x00, 0x00, 0x00
556*4882a593Smuzhiyun };
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun /*
559*4882a593Smuzhiyun * This specifies the selection of init packets that a gamepad
560*4882a593Smuzhiyun * will be sent on init *and* the order in which they will be
561*4882a593Smuzhiyun * sent. The correct sequence number will be added when the
562*4882a593Smuzhiyun * packet is going to be sent.
563*4882a593Smuzhiyun */
564*4882a593Smuzhiyun static const struct xboxone_init_packet xboxone_init_packets[] = {
565*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
566*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
567*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
568*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x045e, 0x02ea, xboxone_s_init),
569*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init),
570*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1),
571*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2),
572*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
573*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
574*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
575*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumbleend_init),
576*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumbleend_init),
577*4882a593Smuzhiyun XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init),
578*4882a593Smuzhiyun };
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun struct xpad_output_packet {
581*4882a593Smuzhiyun u8 data[XPAD_PKT_LEN];
582*4882a593Smuzhiyun u8 len;
583*4882a593Smuzhiyun bool pending;
584*4882a593Smuzhiyun };
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun #define XPAD_OUT_CMD_IDX 0
587*4882a593Smuzhiyun #define XPAD_OUT_FF_IDX 1
588*4882a593Smuzhiyun #define XPAD_OUT_LED_IDX (1 + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF))
589*4882a593Smuzhiyun #define XPAD_NUM_OUT_PACKETS (1 + \
590*4882a593Smuzhiyun IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF) + \
591*4882a593Smuzhiyun IS_ENABLED(CONFIG_JOYSTICK_XPAD_LEDS))
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun struct usb_xpad {
594*4882a593Smuzhiyun struct input_dev *dev; /* input device interface */
595*4882a593Smuzhiyun struct input_dev __rcu *x360w_dev;
596*4882a593Smuzhiyun struct usb_device *udev; /* usb device */
597*4882a593Smuzhiyun struct usb_interface *intf; /* usb interface */
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun bool pad_present;
600*4882a593Smuzhiyun bool input_created;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun struct urb *irq_in; /* urb for interrupt in report */
603*4882a593Smuzhiyun unsigned char *idata; /* input data */
604*4882a593Smuzhiyun dma_addr_t idata_dma;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun struct urb *irq_out; /* urb for interrupt out report */
607*4882a593Smuzhiyun struct usb_anchor irq_out_anchor;
608*4882a593Smuzhiyun bool irq_out_active; /* we must not use an active URB */
609*4882a593Smuzhiyun u8 odata_serial; /* serial number for xbox one protocol */
610*4882a593Smuzhiyun unsigned char *odata; /* output data */
611*4882a593Smuzhiyun dma_addr_t odata_dma;
612*4882a593Smuzhiyun spinlock_t odata_lock;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS];
615*4882a593Smuzhiyun int last_out_packet;
616*4882a593Smuzhiyun int init_seq;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
619*4882a593Smuzhiyun struct xpad_led *led;
620*4882a593Smuzhiyun #endif
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun char phys[64]; /* physical device path */
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun int mapping; /* map d-pad to buttons or to axes */
625*4882a593Smuzhiyun int xtype; /* type of xbox device */
626*4882a593Smuzhiyun int pad_nr; /* the order x360 pads were attached */
627*4882a593Smuzhiyun const char *name; /* name of the device */
628*4882a593Smuzhiyun struct work_struct work; /* init/remove device from callback */
629*4882a593Smuzhiyun };
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun static int xpad_init_input(struct usb_xpad *xpad);
632*4882a593Smuzhiyun static void xpad_deinit_input(struct usb_xpad *xpad);
633*4882a593Smuzhiyun static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /*
636*4882a593Smuzhiyun * xpad_process_packet
637*4882a593Smuzhiyun *
638*4882a593Smuzhiyun * Completes a request by converting the data into events for the
639*4882a593Smuzhiyun * input subsystem.
640*4882a593Smuzhiyun *
641*4882a593Smuzhiyun * The used report descriptor was taken from ITO Takayukis website:
642*4882a593Smuzhiyun * http://euc.jp/periphs/xbox-controller.ja.html
643*4882a593Smuzhiyun */
xpad_process_packet(struct usb_xpad * xpad,u16 cmd,unsigned char * data)644*4882a593Smuzhiyun static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun struct input_dev *dev = xpad->dev;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
649*4882a593Smuzhiyun /* left stick */
650*4882a593Smuzhiyun input_report_abs(dev, ABS_X,
651*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 12)));
652*4882a593Smuzhiyun input_report_abs(dev, ABS_Y,
653*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 14)));
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /* right stick */
656*4882a593Smuzhiyun input_report_abs(dev, ABS_RX,
657*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 16)));
658*4882a593Smuzhiyun input_report_abs(dev, ABS_RY,
659*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 18)));
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun /* triggers left/right */
663*4882a593Smuzhiyun if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
664*4882a593Smuzhiyun input_report_key(dev, BTN_TL2, data[10]);
665*4882a593Smuzhiyun input_report_key(dev, BTN_TR2, data[11]);
666*4882a593Smuzhiyun } else {
667*4882a593Smuzhiyun input_report_abs(dev, ABS_Z, data[10]);
668*4882a593Smuzhiyun input_report_abs(dev, ABS_RZ, data[11]);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun /* digital pad */
672*4882a593Smuzhiyun if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
673*4882a593Smuzhiyun /* dpad as buttons (left, right, up, down) */
674*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
675*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
676*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
677*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
678*4882a593Smuzhiyun } else {
679*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0X,
680*4882a593Smuzhiyun !!(data[2] & 0x08) - !!(data[2] & 0x04));
681*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0Y,
682*4882a593Smuzhiyun !!(data[2] & 0x02) - !!(data[2] & 0x01));
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /* start/back buttons and stick press left/right */
686*4882a593Smuzhiyun input_report_key(dev, BTN_START, data[2] & 0x10);
687*4882a593Smuzhiyun input_report_key(dev, BTN_SELECT, data[2] & 0x20);
688*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
689*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun /* "analog" buttons A, B, X, Y */
692*4882a593Smuzhiyun input_report_key(dev, BTN_A, data[4]);
693*4882a593Smuzhiyun input_report_key(dev, BTN_B, data[5]);
694*4882a593Smuzhiyun input_report_key(dev, BTN_X, data[6]);
695*4882a593Smuzhiyun input_report_key(dev, BTN_Y, data[7]);
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun /* "analog" buttons black, white */
698*4882a593Smuzhiyun input_report_key(dev, BTN_C, data[8]);
699*4882a593Smuzhiyun input_report_key(dev, BTN_Z, data[9]);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun input_sync(dev);
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun /*
705*4882a593Smuzhiyun * xpad360_process_packet
706*4882a593Smuzhiyun *
707*4882a593Smuzhiyun * Completes a request by converting the data into events for the
708*4882a593Smuzhiyun * input subsystem. It is version for xbox 360 controller
709*4882a593Smuzhiyun *
710*4882a593Smuzhiyun * The used report descriptor was taken from:
711*4882a593Smuzhiyun * http://www.free60.org/wiki/Gamepad
712*4882a593Smuzhiyun */
713*4882a593Smuzhiyun
xpad360_process_packet(struct usb_xpad * xpad,struct input_dev * dev,u16 cmd,unsigned char * data)714*4882a593Smuzhiyun static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
715*4882a593Smuzhiyun u16 cmd, unsigned char *data)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun /* valid pad data */
718*4882a593Smuzhiyun if (data[0] != 0x00)
719*4882a593Smuzhiyun return;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* digital pad */
722*4882a593Smuzhiyun if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
723*4882a593Smuzhiyun /* dpad as buttons (left, right, up, down) */
724*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
725*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
726*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
727*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /*
731*4882a593Smuzhiyun * This should be a simple else block. However historically
732*4882a593Smuzhiyun * xbox360w has mapped DPAD to buttons while xbox360 did not. This
733*4882a593Smuzhiyun * made no sense, but now we can not just switch back and have to
734*4882a593Smuzhiyun * support both behaviors.
735*4882a593Smuzhiyun */
736*4882a593Smuzhiyun if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
737*4882a593Smuzhiyun xpad->xtype == XTYPE_XBOX360W) {
738*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0X,
739*4882a593Smuzhiyun !!(data[2] & 0x08) - !!(data[2] & 0x04));
740*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0Y,
741*4882a593Smuzhiyun !!(data[2] & 0x02) - !!(data[2] & 0x01));
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun /* start/back buttons */
745*4882a593Smuzhiyun input_report_key(dev, BTN_START, data[2] & 0x10);
746*4882a593Smuzhiyun input_report_key(dev, BTN_SELECT, data[2] & 0x20);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* stick press left/right */
749*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
750*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun /* buttons A,B,X,Y,TL,TR and MODE */
753*4882a593Smuzhiyun input_report_key(dev, BTN_A, data[3] & 0x10);
754*4882a593Smuzhiyun input_report_key(dev, BTN_B, data[3] & 0x20);
755*4882a593Smuzhiyun input_report_key(dev, BTN_X, data[3] & 0x40);
756*4882a593Smuzhiyun input_report_key(dev, BTN_Y, data[3] & 0x80);
757*4882a593Smuzhiyun input_report_key(dev, BTN_TL, data[3] & 0x01);
758*4882a593Smuzhiyun input_report_key(dev, BTN_TR, data[3] & 0x02);
759*4882a593Smuzhiyun input_report_key(dev, BTN_MODE, data[3] & 0x04);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
762*4882a593Smuzhiyun /* left stick */
763*4882a593Smuzhiyun input_report_abs(dev, ABS_X,
764*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 6)));
765*4882a593Smuzhiyun input_report_abs(dev, ABS_Y,
766*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 8)));
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun /* right stick */
769*4882a593Smuzhiyun input_report_abs(dev, ABS_RX,
770*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 10)));
771*4882a593Smuzhiyun input_report_abs(dev, ABS_RY,
772*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun /* triggers left/right */
776*4882a593Smuzhiyun if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
777*4882a593Smuzhiyun input_report_key(dev, BTN_TL2, data[4]);
778*4882a593Smuzhiyun input_report_key(dev, BTN_TR2, data[5]);
779*4882a593Smuzhiyun } else {
780*4882a593Smuzhiyun input_report_abs(dev, ABS_Z, data[4]);
781*4882a593Smuzhiyun input_report_abs(dev, ABS_RZ, data[5]);
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun input_sync(dev);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
xpad_presence_work(struct work_struct * work)787*4882a593Smuzhiyun static void xpad_presence_work(struct work_struct *work)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun struct usb_xpad *xpad = container_of(work, struct usb_xpad, work);
790*4882a593Smuzhiyun int error;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun if (xpad->pad_present) {
793*4882a593Smuzhiyun error = xpad_init_input(xpad);
794*4882a593Smuzhiyun if (error) {
795*4882a593Smuzhiyun /* complain only, not much else we can do here */
796*4882a593Smuzhiyun dev_err(&xpad->dev->dev,
797*4882a593Smuzhiyun "unable to init device: %d\n", error);
798*4882a593Smuzhiyun } else {
799*4882a593Smuzhiyun rcu_assign_pointer(xpad->x360w_dev, xpad->dev);
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun } else {
802*4882a593Smuzhiyun RCU_INIT_POINTER(xpad->x360w_dev, NULL);
803*4882a593Smuzhiyun synchronize_rcu();
804*4882a593Smuzhiyun /*
805*4882a593Smuzhiyun * Now that we are sure xpad360w_process_packet is not
806*4882a593Smuzhiyun * using input device we can get rid of it.
807*4882a593Smuzhiyun */
808*4882a593Smuzhiyun xpad_deinit_input(xpad);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun /*
813*4882a593Smuzhiyun * xpad360w_process_packet
814*4882a593Smuzhiyun *
815*4882a593Smuzhiyun * Completes a request by converting the data into events for the
816*4882a593Smuzhiyun * input subsystem. It is version for xbox 360 wireless controller.
817*4882a593Smuzhiyun *
818*4882a593Smuzhiyun * Byte.Bit
819*4882a593Smuzhiyun * 00.1 - Status change: The controller or headset has connected/disconnected
820*4882a593Smuzhiyun * Bits 01.7 and 01.6 are valid
821*4882a593Smuzhiyun * 01.7 - Controller present
822*4882a593Smuzhiyun * 01.6 - Headset present
823*4882a593Smuzhiyun * 01.1 - Pad state (Bytes 4+) valid
824*4882a593Smuzhiyun *
825*4882a593Smuzhiyun */
xpad360w_process_packet(struct usb_xpad * xpad,u16 cmd,unsigned char * data)826*4882a593Smuzhiyun static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun struct input_dev *dev;
829*4882a593Smuzhiyun bool present;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun /* Presence change */
832*4882a593Smuzhiyun if (data[0] & 0x08) {
833*4882a593Smuzhiyun present = (data[1] & 0x80) != 0;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun if (xpad->pad_present != present) {
836*4882a593Smuzhiyun xpad->pad_present = present;
837*4882a593Smuzhiyun schedule_work(&xpad->work);
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun /* Valid pad data */
842*4882a593Smuzhiyun if (data[1] != 0x1)
843*4882a593Smuzhiyun return;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun rcu_read_lock();
846*4882a593Smuzhiyun dev = rcu_dereference(xpad->x360w_dev);
847*4882a593Smuzhiyun if (dev)
848*4882a593Smuzhiyun xpad360_process_packet(xpad, dev, cmd, &data[4]);
849*4882a593Smuzhiyun rcu_read_unlock();
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun /*
853*4882a593Smuzhiyun * xpadone_process_packet
854*4882a593Smuzhiyun *
855*4882a593Smuzhiyun * Completes a request by converting the data into events for the
856*4882a593Smuzhiyun * input subsystem. This version is for the Xbox One controller.
857*4882a593Smuzhiyun *
858*4882a593Smuzhiyun * The report format was gleaned from
859*4882a593Smuzhiyun * https://github.com/kylelemons/xbox/blob/master/xbox.go
860*4882a593Smuzhiyun */
xpadone_process_packet(struct usb_xpad * xpad,u16 cmd,unsigned char * data)861*4882a593Smuzhiyun static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun struct input_dev *dev = xpad->dev;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun /* the xbox button has its own special report */
866*4882a593Smuzhiyun if (data[0] == 0X07) {
867*4882a593Smuzhiyun /*
868*4882a593Smuzhiyun * The Xbox One S controller requires these reports to be
869*4882a593Smuzhiyun * acked otherwise it continues sending them forever and
870*4882a593Smuzhiyun * won't report further mode button events.
871*4882a593Smuzhiyun */
872*4882a593Smuzhiyun if (data[1] == 0x30)
873*4882a593Smuzhiyun xpadone_ack_mode_report(xpad, data[2]);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun input_report_key(dev, BTN_MODE, data[4] & 0x01);
876*4882a593Smuzhiyun input_sync(dev);
877*4882a593Smuzhiyun return;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun /* check invalid packet */
880*4882a593Smuzhiyun else if (data[0] != 0X20)
881*4882a593Smuzhiyun return;
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun /* menu/view buttons */
884*4882a593Smuzhiyun input_report_key(dev, BTN_START, data[4] & 0x04);
885*4882a593Smuzhiyun input_report_key(dev, BTN_SELECT, data[4] & 0x08);
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun /* buttons A,B,X,Y */
888*4882a593Smuzhiyun input_report_key(dev, BTN_A, data[4] & 0x10);
889*4882a593Smuzhiyun input_report_key(dev, BTN_B, data[4] & 0x20);
890*4882a593Smuzhiyun input_report_key(dev, BTN_X, data[4] & 0x40);
891*4882a593Smuzhiyun input_report_key(dev, BTN_Y, data[4] & 0x80);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun /* digital pad */
894*4882a593Smuzhiyun if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
895*4882a593Smuzhiyun /* dpad as buttons (left, right, up, down) */
896*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04);
897*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08);
898*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01);
899*4882a593Smuzhiyun input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02);
900*4882a593Smuzhiyun } else {
901*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0X,
902*4882a593Smuzhiyun !!(data[5] & 0x08) - !!(data[5] & 0x04));
903*4882a593Smuzhiyun input_report_abs(dev, ABS_HAT0Y,
904*4882a593Smuzhiyun !!(data[5] & 0x02) - !!(data[5] & 0x01));
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /* TL/TR */
908*4882a593Smuzhiyun input_report_key(dev, BTN_TL, data[5] & 0x10);
909*4882a593Smuzhiyun input_report_key(dev, BTN_TR, data[5] & 0x20);
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun /* stick press left/right */
912*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBL, data[5] & 0x40);
913*4882a593Smuzhiyun input_report_key(dev, BTN_THUMBR, data[5] & 0x80);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
916*4882a593Smuzhiyun /* left stick */
917*4882a593Smuzhiyun input_report_abs(dev, ABS_X,
918*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 10)));
919*4882a593Smuzhiyun input_report_abs(dev, ABS_Y,
920*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun /* right stick */
923*4882a593Smuzhiyun input_report_abs(dev, ABS_RX,
924*4882a593Smuzhiyun (__s16) le16_to_cpup((__le16 *)(data + 14)));
925*4882a593Smuzhiyun input_report_abs(dev, ABS_RY,
926*4882a593Smuzhiyun ~(__s16) le16_to_cpup((__le16 *)(data + 16)));
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun /* triggers left/right */
930*4882a593Smuzhiyun if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
931*4882a593Smuzhiyun input_report_key(dev, BTN_TL2,
932*4882a593Smuzhiyun (__u16) le16_to_cpup((__le16 *)(data + 6)));
933*4882a593Smuzhiyun input_report_key(dev, BTN_TR2,
934*4882a593Smuzhiyun (__u16) le16_to_cpup((__le16 *)(data + 8)));
935*4882a593Smuzhiyun } else {
936*4882a593Smuzhiyun input_report_abs(dev, ABS_Z,
937*4882a593Smuzhiyun (__u16) le16_to_cpup((__le16 *)(data + 6)));
938*4882a593Smuzhiyun input_report_abs(dev, ABS_RZ,
939*4882a593Smuzhiyun (__u16) le16_to_cpup((__le16 *)(data + 8)));
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun input_sync(dev);
943*4882a593Smuzhiyun }
944*4882a593Smuzhiyun
xpad_irq_in(struct urb * urb)945*4882a593Smuzhiyun static void xpad_irq_in(struct urb *urb)
946*4882a593Smuzhiyun {
947*4882a593Smuzhiyun struct usb_xpad *xpad = urb->context;
948*4882a593Smuzhiyun struct device *dev = &xpad->intf->dev;
949*4882a593Smuzhiyun int retval, status;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun status = urb->status;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun switch (status) {
954*4882a593Smuzhiyun case 0:
955*4882a593Smuzhiyun /* success */
956*4882a593Smuzhiyun break;
957*4882a593Smuzhiyun case -ECONNRESET:
958*4882a593Smuzhiyun case -ENOENT:
959*4882a593Smuzhiyun case -ESHUTDOWN:
960*4882a593Smuzhiyun /* this urb is terminated, clean up */
961*4882a593Smuzhiyun dev_dbg(dev, "%s - urb shutting down with status: %d\n",
962*4882a593Smuzhiyun __func__, status);
963*4882a593Smuzhiyun return;
964*4882a593Smuzhiyun default:
965*4882a593Smuzhiyun dev_dbg(dev, "%s - nonzero urb status received: %d\n",
966*4882a593Smuzhiyun __func__, status);
967*4882a593Smuzhiyun goto exit;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun switch (xpad->xtype) {
971*4882a593Smuzhiyun case XTYPE_XBOX360:
972*4882a593Smuzhiyun xpad360_process_packet(xpad, xpad->dev, 0, xpad->idata);
973*4882a593Smuzhiyun break;
974*4882a593Smuzhiyun case XTYPE_XBOX360W:
975*4882a593Smuzhiyun xpad360w_process_packet(xpad, 0, xpad->idata);
976*4882a593Smuzhiyun break;
977*4882a593Smuzhiyun case XTYPE_XBOXONE:
978*4882a593Smuzhiyun xpadone_process_packet(xpad, 0, xpad->idata);
979*4882a593Smuzhiyun break;
980*4882a593Smuzhiyun default:
981*4882a593Smuzhiyun xpad_process_packet(xpad, 0, xpad->idata);
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun exit:
985*4882a593Smuzhiyun retval = usb_submit_urb(urb, GFP_ATOMIC);
986*4882a593Smuzhiyun if (retval)
987*4882a593Smuzhiyun dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
988*4882a593Smuzhiyun __func__, retval);
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun /* Callers must hold xpad->odata_lock spinlock */
xpad_prepare_next_init_packet(struct usb_xpad * xpad)992*4882a593Smuzhiyun static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad)
993*4882a593Smuzhiyun {
994*4882a593Smuzhiyun const struct xboxone_init_packet *init_packet;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun if (xpad->xtype != XTYPE_XBOXONE)
997*4882a593Smuzhiyun return false;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun /* Perform initialization sequence for Xbox One pads that require it */
1000*4882a593Smuzhiyun while (xpad->init_seq < ARRAY_SIZE(xboxone_init_packets)) {
1001*4882a593Smuzhiyun init_packet = &xboxone_init_packets[xpad->init_seq++];
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun if (init_packet->idVendor != 0 &&
1004*4882a593Smuzhiyun init_packet->idVendor != xpad->dev->id.vendor)
1005*4882a593Smuzhiyun continue;
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun if (init_packet->idProduct != 0 &&
1008*4882a593Smuzhiyun init_packet->idProduct != xpad->dev->id.product)
1009*4882a593Smuzhiyun continue;
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun /* This packet applies to our device, so prepare to send it */
1012*4882a593Smuzhiyun memcpy(xpad->odata, init_packet->data, init_packet->len);
1013*4882a593Smuzhiyun xpad->irq_out->transfer_buffer_length = init_packet->len;
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun /* Update packet with current sequence number */
1016*4882a593Smuzhiyun xpad->odata[2] = xpad->odata_serial++;
1017*4882a593Smuzhiyun return true;
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun return false;
1021*4882a593Smuzhiyun }
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun /* Callers must hold xpad->odata_lock spinlock */
xpad_prepare_next_out_packet(struct usb_xpad * xpad)1024*4882a593Smuzhiyun static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad)
1025*4882a593Smuzhiyun {
1026*4882a593Smuzhiyun struct xpad_output_packet *pkt, *packet = NULL;
1027*4882a593Smuzhiyun int i;
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun /* We may have init packets to send before we can send user commands */
1030*4882a593Smuzhiyun if (xpad_prepare_next_init_packet(xpad))
1031*4882a593Smuzhiyun return true;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) {
1034*4882a593Smuzhiyun if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS)
1035*4882a593Smuzhiyun xpad->last_out_packet = 0;
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun pkt = &xpad->out_packets[xpad->last_out_packet];
1038*4882a593Smuzhiyun if (pkt->pending) {
1039*4882a593Smuzhiyun dev_dbg(&xpad->intf->dev,
1040*4882a593Smuzhiyun "%s - found pending output packet %d\n",
1041*4882a593Smuzhiyun __func__, xpad->last_out_packet);
1042*4882a593Smuzhiyun packet = pkt;
1043*4882a593Smuzhiyun break;
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun if (packet) {
1048*4882a593Smuzhiyun memcpy(xpad->odata, packet->data, packet->len);
1049*4882a593Smuzhiyun xpad->irq_out->transfer_buffer_length = packet->len;
1050*4882a593Smuzhiyun packet->pending = false;
1051*4882a593Smuzhiyun return true;
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun return false;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun /* Callers must hold xpad->odata_lock spinlock */
xpad_try_sending_next_out_packet(struct usb_xpad * xpad)1058*4882a593Smuzhiyun static int xpad_try_sending_next_out_packet(struct usb_xpad *xpad)
1059*4882a593Smuzhiyun {
1060*4882a593Smuzhiyun int error;
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) {
1063*4882a593Smuzhiyun usb_anchor_urb(xpad->irq_out, &xpad->irq_out_anchor);
1064*4882a593Smuzhiyun error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
1065*4882a593Smuzhiyun if (error) {
1066*4882a593Smuzhiyun dev_err(&xpad->intf->dev,
1067*4882a593Smuzhiyun "%s - usb_submit_urb failed with result %d\n",
1068*4882a593Smuzhiyun __func__, error);
1069*4882a593Smuzhiyun usb_unanchor_urb(xpad->irq_out);
1070*4882a593Smuzhiyun return -EIO;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun xpad->irq_out_active = true;
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun return 0;
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun
xpad_irq_out(struct urb * urb)1079*4882a593Smuzhiyun static void xpad_irq_out(struct urb *urb)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun struct usb_xpad *xpad = urb->context;
1082*4882a593Smuzhiyun struct device *dev = &xpad->intf->dev;
1083*4882a593Smuzhiyun int status = urb->status;
1084*4882a593Smuzhiyun int error;
1085*4882a593Smuzhiyun unsigned long flags;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun switch (status) {
1090*4882a593Smuzhiyun case 0:
1091*4882a593Smuzhiyun /* success */
1092*4882a593Smuzhiyun xpad->irq_out_active = xpad_prepare_next_out_packet(xpad);
1093*4882a593Smuzhiyun break;
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun case -ECONNRESET:
1096*4882a593Smuzhiyun case -ENOENT:
1097*4882a593Smuzhiyun case -ESHUTDOWN:
1098*4882a593Smuzhiyun /* this urb is terminated, clean up */
1099*4882a593Smuzhiyun dev_dbg(dev, "%s - urb shutting down with status: %d\n",
1100*4882a593Smuzhiyun __func__, status);
1101*4882a593Smuzhiyun xpad->irq_out_active = false;
1102*4882a593Smuzhiyun break;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun default:
1105*4882a593Smuzhiyun dev_dbg(dev, "%s - nonzero urb status received: %d\n",
1106*4882a593Smuzhiyun __func__, status);
1107*4882a593Smuzhiyun break;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun if (xpad->irq_out_active) {
1111*4882a593Smuzhiyun usb_anchor_urb(urb, &xpad->irq_out_anchor);
1112*4882a593Smuzhiyun error = usb_submit_urb(urb, GFP_ATOMIC);
1113*4882a593Smuzhiyun if (error) {
1114*4882a593Smuzhiyun dev_err(dev,
1115*4882a593Smuzhiyun "%s - usb_submit_urb failed with result %d\n",
1116*4882a593Smuzhiyun __func__, error);
1117*4882a593Smuzhiyun usb_unanchor_urb(urb);
1118*4882a593Smuzhiyun xpad->irq_out_active = false;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1123*4882a593Smuzhiyun }
1124*4882a593Smuzhiyun
xpad_init_output(struct usb_interface * intf,struct usb_xpad * xpad,struct usb_endpoint_descriptor * ep_irq_out)1125*4882a593Smuzhiyun static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
1126*4882a593Smuzhiyun struct usb_endpoint_descriptor *ep_irq_out)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun int error;
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun if (xpad->xtype == XTYPE_UNKNOWN)
1131*4882a593Smuzhiyun return 0;
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun init_usb_anchor(&xpad->irq_out_anchor);
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
1136*4882a593Smuzhiyun GFP_KERNEL, &xpad->odata_dma);
1137*4882a593Smuzhiyun if (!xpad->odata)
1138*4882a593Smuzhiyun return -ENOMEM;
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun spin_lock_init(&xpad->odata_lock);
1141*4882a593Smuzhiyun
1142*4882a593Smuzhiyun xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
1143*4882a593Smuzhiyun if (!xpad->irq_out) {
1144*4882a593Smuzhiyun error = -ENOMEM;
1145*4882a593Smuzhiyun goto err_free_coherent;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun usb_fill_int_urb(xpad->irq_out, xpad->udev,
1149*4882a593Smuzhiyun usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
1150*4882a593Smuzhiyun xpad->odata, XPAD_PKT_LEN,
1151*4882a593Smuzhiyun xpad_irq_out, xpad, ep_irq_out->bInterval);
1152*4882a593Smuzhiyun xpad->irq_out->transfer_dma = xpad->odata_dma;
1153*4882a593Smuzhiyun xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun return 0;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun err_free_coherent:
1158*4882a593Smuzhiyun usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
1159*4882a593Smuzhiyun return error;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun
xpad_stop_output(struct usb_xpad * xpad)1162*4882a593Smuzhiyun static void xpad_stop_output(struct usb_xpad *xpad)
1163*4882a593Smuzhiyun {
1164*4882a593Smuzhiyun if (xpad->xtype != XTYPE_UNKNOWN) {
1165*4882a593Smuzhiyun if (!usb_wait_anchor_empty_timeout(&xpad->irq_out_anchor,
1166*4882a593Smuzhiyun 5000)) {
1167*4882a593Smuzhiyun dev_warn(&xpad->intf->dev,
1168*4882a593Smuzhiyun "timed out waiting for output URB to complete, killing\n");
1169*4882a593Smuzhiyun usb_kill_anchored_urbs(&xpad->irq_out_anchor);
1170*4882a593Smuzhiyun }
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun
xpad_deinit_output(struct usb_xpad * xpad)1174*4882a593Smuzhiyun static void xpad_deinit_output(struct usb_xpad *xpad)
1175*4882a593Smuzhiyun {
1176*4882a593Smuzhiyun if (xpad->xtype != XTYPE_UNKNOWN) {
1177*4882a593Smuzhiyun usb_free_urb(xpad->irq_out);
1178*4882a593Smuzhiyun usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
1179*4882a593Smuzhiyun xpad->odata, xpad->odata_dma);
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun
xpad_inquiry_pad_presence(struct usb_xpad * xpad)1183*4882a593Smuzhiyun static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
1184*4882a593Smuzhiyun {
1185*4882a593Smuzhiyun struct xpad_output_packet *packet =
1186*4882a593Smuzhiyun &xpad->out_packets[XPAD_OUT_CMD_IDX];
1187*4882a593Smuzhiyun unsigned long flags;
1188*4882a593Smuzhiyun int retval;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun packet->data[0] = 0x08;
1193*4882a593Smuzhiyun packet->data[1] = 0x00;
1194*4882a593Smuzhiyun packet->data[2] = 0x0F;
1195*4882a593Smuzhiyun packet->data[3] = 0xC0;
1196*4882a593Smuzhiyun packet->data[4] = 0x00;
1197*4882a593Smuzhiyun packet->data[5] = 0x00;
1198*4882a593Smuzhiyun packet->data[6] = 0x00;
1199*4882a593Smuzhiyun packet->data[7] = 0x00;
1200*4882a593Smuzhiyun packet->data[8] = 0x00;
1201*4882a593Smuzhiyun packet->data[9] = 0x00;
1202*4882a593Smuzhiyun packet->data[10] = 0x00;
1203*4882a593Smuzhiyun packet->data[11] = 0x00;
1204*4882a593Smuzhiyun packet->len = 12;
1205*4882a593Smuzhiyun packet->pending = true;
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun /* Reset the sequence so we send out presence first */
1208*4882a593Smuzhiyun xpad->last_out_packet = -1;
1209*4882a593Smuzhiyun retval = xpad_try_sending_next_out_packet(xpad);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun return retval;
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun
xpad_start_xbox_one(struct usb_xpad * xpad)1216*4882a593Smuzhiyun static int xpad_start_xbox_one(struct usb_xpad *xpad)
1217*4882a593Smuzhiyun {
1218*4882a593Smuzhiyun unsigned long flags;
1219*4882a593Smuzhiyun int retval;
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun /*
1224*4882a593Smuzhiyun * Begin the init sequence by attempting to send a packet.
1225*4882a593Smuzhiyun * We will cycle through the init packet sequence before
1226*4882a593Smuzhiyun * sending any packets from the output ring.
1227*4882a593Smuzhiyun */
1228*4882a593Smuzhiyun xpad->init_seq = 0;
1229*4882a593Smuzhiyun retval = xpad_try_sending_next_out_packet(xpad);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun return retval;
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun
xpadone_ack_mode_report(struct usb_xpad * xpad,u8 seq_num)1236*4882a593Smuzhiyun static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
1237*4882a593Smuzhiyun {
1238*4882a593Smuzhiyun unsigned long flags;
1239*4882a593Smuzhiyun struct xpad_output_packet *packet =
1240*4882a593Smuzhiyun &xpad->out_packets[XPAD_OUT_CMD_IDX];
1241*4882a593Smuzhiyun static const u8 mode_report_ack[] = {
1242*4882a593Smuzhiyun 0x01, 0x20, 0x00, 0x09, 0x00, 0x07, 0x20, 0x02,
1243*4882a593Smuzhiyun 0x00, 0x00, 0x00, 0x00, 0x00
1244*4882a593Smuzhiyun };
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun packet->len = sizeof(mode_report_ack);
1249*4882a593Smuzhiyun memcpy(packet->data, mode_report_ack, packet->len);
1250*4882a593Smuzhiyun packet->data[2] = seq_num;
1251*4882a593Smuzhiyun packet->pending = true;
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun /* Reset the sequence so we send out the ack now */
1254*4882a593Smuzhiyun xpad->last_out_packet = -1;
1255*4882a593Smuzhiyun xpad_try_sending_next_out_packet(xpad);
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun #ifdef CONFIG_JOYSTICK_XPAD_FF
xpad_play_effect(struct input_dev * dev,void * data,struct ff_effect * effect)1261*4882a593Smuzhiyun static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
1262*4882a593Smuzhiyun {
1263*4882a593Smuzhiyun struct usb_xpad *xpad = input_get_drvdata(dev);
1264*4882a593Smuzhiyun struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX];
1265*4882a593Smuzhiyun __u16 strong;
1266*4882a593Smuzhiyun __u16 weak;
1267*4882a593Smuzhiyun int retval;
1268*4882a593Smuzhiyun unsigned long flags;
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun if (effect->type != FF_RUMBLE)
1271*4882a593Smuzhiyun return 0;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun strong = effect->u.rumble.strong_magnitude;
1274*4882a593Smuzhiyun weak = effect->u.rumble.weak_magnitude;
1275*4882a593Smuzhiyun
1276*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun switch (xpad->xtype) {
1279*4882a593Smuzhiyun case XTYPE_XBOX:
1280*4882a593Smuzhiyun packet->data[0] = 0x00;
1281*4882a593Smuzhiyun packet->data[1] = 0x06;
1282*4882a593Smuzhiyun packet->data[2] = 0x00;
1283*4882a593Smuzhiyun packet->data[3] = strong / 256; /* left actuator */
1284*4882a593Smuzhiyun packet->data[4] = 0x00;
1285*4882a593Smuzhiyun packet->data[5] = weak / 256; /* right actuator */
1286*4882a593Smuzhiyun packet->len = 6;
1287*4882a593Smuzhiyun packet->pending = true;
1288*4882a593Smuzhiyun break;
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun case XTYPE_XBOX360:
1291*4882a593Smuzhiyun packet->data[0] = 0x00;
1292*4882a593Smuzhiyun packet->data[1] = 0x08;
1293*4882a593Smuzhiyun packet->data[2] = 0x00;
1294*4882a593Smuzhiyun packet->data[3] = strong / 256; /* left actuator? */
1295*4882a593Smuzhiyun packet->data[4] = weak / 256; /* right actuator? */
1296*4882a593Smuzhiyun packet->data[5] = 0x00;
1297*4882a593Smuzhiyun packet->data[6] = 0x00;
1298*4882a593Smuzhiyun packet->data[7] = 0x00;
1299*4882a593Smuzhiyun packet->len = 8;
1300*4882a593Smuzhiyun packet->pending = true;
1301*4882a593Smuzhiyun break;
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun case XTYPE_XBOX360W:
1304*4882a593Smuzhiyun packet->data[0] = 0x00;
1305*4882a593Smuzhiyun packet->data[1] = 0x01;
1306*4882a593Smuzhiyun packet->data[2] = 0x0F;
1307*4882a593Smuzhiyun packet->data[3] = 0xC0;
1308*4882a593Smuzhiyun packet->data[4] = 0x00;
1309*4882a593Smuzhiyun packet->data[5] = strong / 256;
1310*4882a593Smuzhiyun packet->data[6] = weak / 256;
1311*4882a593Smuzhiyun packet->data[7] = 0x00;
1312*4882a593Smuzhiyun packet->data[8] = 0x00;
1313*4882a593Smuzhiyun packet->data[9] = 0x00;
1314*4882a593Smuzhiyun packet->data[10] = 0x00;
1315*4882a593Smuzhiyun packet->data[11] = 0x00;
1316*4882a593Smuzhiyun packet->len = 12;
1317*4882a593Smuzhiyun packet->pending = true;
1318*4882a593Smuzhiyun break;
1319*4882a593Smuzhiyun
1320*4882a593Smuzhiyun case XTYPE_XBOXONE:
1321*4882a593Smuzhiyun packet->data[0] = 0x09; /* activate rumble */
1322*4882a593Smuzhiyun packet->data[1] = 0x00;
1323*4882a593Smuzhiyun packet->data[2] = xpad->odata_serial++;
1324*4882a593Smuzhiyun packet->data[3] = 0x09;
1325*4882a593Smuzhiyun packet->data[4] = 0x00;
1326*4882a593Smuzhiyun packet->data[5] = 0x0F;
1327*4882a593Smuzhiyun packet->data[6] = 0x00;
1328*4882a593Smuzhiyun packet->data[7] = 0x00;
1329*4882a593Smuzhiyun packet->data[8] = strong / 512; /* left actuator */
1330*4882a593Smuzhiyun packet->data[9] = weak / 512; /* right actuator */
1331*4882a593Smuzhiyun packet->data[10] = 0xFF; /* on period */
1332*4882a593Smuzhiyun packet->data[11] = 0x00; /* off period */
1333*4882a593Smuzhiyun packet->data[12] = 0xFF; /* repeat count */
1334*4882a593Smuzhiyun packet->len = 13;
1335*4882a593Smuzhiyun packet->pending = true;
1336*4882a593Smuzhiyun break;
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun default:
1339*4882a593Smuzhiyun dev_dbg(&xpad->dev->dev,
1340*4882a593Smuzhiyun "%s - rumble command sent to unsupported xpad type: %d\n",
1341*4882a593Smuzhiyun __func__, xpad->xtype);
1342*4882a593Smuzhiyun retval = -EINVAL;
1343*4882a593Smuzhiyun goto out;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun retval = xpad_try_sending_next_out_packet(xpad);
1347*4882a593Smuzhiyun
1348*4882a593Smuzhiyun out:
1349*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1350*4882a593Smuzhiyun return retval;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun
xpad_init_ff(struct usb_xpad * xpad)1353*4882a593Smuzhiyun static int xpad_init_ff(struct usb_xpad *xpad)
1354*4882a593Smuzhiyun {
1355*4882a593Smuzhiyun if (xpad->xtype == XTYPE_UNKNOWN)
1356*4882a593Smuzhiyun return 0;
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
1359*4882a593Smuzhiyun
1360*4882a593Smuzhiyun return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
1361*4882a593Smuzhiyun }
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun #else
xpad_init_ff(struct usb_xpad * xpad)1364*4882a593Smuzhiyun static int xpad_init_ff(struct usb_xpad *xpad) { return 0; }
1365*4882a593Smuzhiyun #endif
1366*4882a593Smuzhiyun
1367*4882a593Smuzhiyun #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
1368*4882a593Smuzhiyun #include <linux/leds.h>
1369*4882a593Smuzhiyun #include <linux/idr.h>
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun static DEFINE_IDA(xpad_pad_seq);
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun struct xpad_led {
1374*4882a593Smuzhiyun char name[16];
1375*4882a593Smuzhiyun struct led_classdev led_cdev;
1376*4882a593Smuzhiyun struct usb_xpad *xpad;
1377*4882a593Smuzhiyun };
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun /**
1380*4882a593Smuzhiyun * set the LEDs on Xbox360 / Wireless Controllers
1381*4882a593Smuzhiyun * @param command
1382*4882a593Smuzhiyun * 0: off
1383*4882a593Smuzhiyun * 1: all blink, then previous setting
1384*4882a593Smuzhiyun * 2: 1/top-left blink, then on
1385*4882a593Smuzhiyun * 3: 2/top-right blink, then on
1386*4882a593Smuzhiyun * 4: 3/bottom-left blink, then on
1387*4882a593Smuzhiyun * 5: 4/bottom-right blink, then on
1388*4882a593Smuzhiyun * 6: 1/top-left on
1389*4882a593Smuzhiyun * 7: 2/top-right on
1390*4882a593Smuzhiyun * 8: 3/bottom-left on
1391*4882a593Smuzhiyun * 9: 4/bottom-right on
1392*4882a593Smuzhiyun * 10: rotate
1393*4882a593Smuzhiyun * 11: blink, based on previous setting
1394*4882a593Smuzhiyun * 12: slow blink, based on previous setting
1395*4882a593Smuzhiyun * 13: rotate with two lights
1396*4882a593Smuzhiyun * 14: persistent slow all blink
1397*4882a593Smuzhiyun * 15: blink once, then previous setting
1398*4882a593Smuzhiyun */
xpad_send_led_command(struct usb_xpad * xpad,int command)1399*4882a593Smuzhiyun static void xpad_send_led_command(struct usb_xpad *xpad, int command)
1400*4882a593Smuzhiyun {
1401*4882a593Smuzhiyun struct xpad_output_packet *packet =
1402*4882a593Smuzhiyun &xpad->out_packets[XPAD_OUT_LED_IDX];
1403*4882a593Smuzhiyun unsigned long flags;
1404*4882a593Smuzhiyun
1405*4882a593Smuzhiyun command %= 16;
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun switch (xpad->xtype) {
1410*4882a593Smuzhiyun case XTYPE_XBOX360:
1411*4882a593Smuzhiyun packet->data[0] = 0x01;
1412*4882a593Smuzhiyun packet->data[1] = 0x03;
1413*4882a593Smuzhiyun packet->data[2] = command;
1414*4882a593Smuzhiyun packet->len = 3;
1415*4882a593Smuzhiyun packet->pending = true;
1416*4882a593Smuzhiyun break;
1417*4882a593Smuzhiyun
1418*4882a593Smuzhiyun case XTYPE_XBOX360W:
1419*4882a593Smuzhiyun packet->data[0] = 0x00;
1420*4882a593Smuzhiyun packet->data[1] = 0x00;
1421*4882a593Smuzhiyun packet->data[2] = 0x08;
1422*4882a593Smuzhiyun packet->data[3] = 0x40 + command;
1423*4882a593Smuzhiyun packet->data[4] = 0x00;
1424*4882a593Smuzhiyun packet->data[5] = 0x00;
1425*4882a593Smuzhiyun packet->data[6] = 0x00;
1426*4882a593Smuzhiyun packet->data[7] = 0x00;
1427*4882a593Smuzhiyun packet->data[8] = 0x00;
1428*4882a593Smuzhiyun packet->data[9] = 0x00;
1429*4882a593Smuzhiyun packet->data[10] = 0x00;
1430*4882a593Smuzhiyun packet->data[11] = 0x00;
1431*4882a593Smuzhiyun packet->len = 12;
1432*4882a593Smuzhiyun packet->pending = true;
1433*4882a593Smuzhiyun break;
1434*4882a593Smuzhiyun }
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun xpad_try_sending_next_out_packet(xpad);
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1439*4882a593Smuzhiyun }
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun /*
1442*4882a593Smuzhiyun * Light up the segment corresponding to the pad number on
1443*4882a593Smuzhiyun * Xbox 360 Controllers.
1444*4882a593Smuzhiyun */
xpad_identify_controller(struct usb_xpad * xpad)1445*4882a593Smuzhiyun static void xpad_identify_controller(struct usb_xpad *xpad)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun led_set_brightness(&xpad->led->led_cdev, (xpad->pad_nr % 4) + 2);
1448*4882a593Smuzhiyun }
1449*4882a593Smuzhiyun
xpad_led_set(struct led_classdev * led_cdev,enum led_brightness value)1450*4882a593Smuzhiyun static void xpad_led_set(struct led_classdev *led_cdev,
1451*4882a593Smuzhiyun enum led_brightness value)
1452*4882a593Smuzhiyun {
1453*4882a593Smuzhiyun struct xpad_led *xpad_led = container_of(led_cdev,
1454*4882a593Smuzhiyun struct xpad_led, led_cdev);
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun xpad_send_led_command(xpad_led->xpad, value);
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
xpad_led_probe(struct usb_xpad * xpad)1459*4882a593Smuzhiyun static int xpad_led_probe(struct usb_xpad *xpad)
1460*4882a593Smuzhiyun {
1461*4882a593Smuzhiyun struct xpad_led *led;
1462*4882a593Smuzhiyun struct led_classdev *led_cdev;
1463*4882a593Smuzhiyun int error;
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W)
1466*4882a593Smuzhiyun return 0;
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL);
1469*4882a593Smuzhiyun if (!led)
1470*4882a593Smuzhiyun return -ENOMEM;
1471*4882a593Smuzhiyun
1472*4882a593Smuzhiyun xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
1473*4882a593Smuzhiyun if (xpad->pad_nr < 0) {
1474*4882a593Smuzhiyun error = xpad->pad_nr;
1475*4882a593Smuzhiyun goto err_free_mem;
1476*4882a593Smuzhiyun }
1477*4882a593Smuzhiyun
1478*4882a593Smuzhiyun snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr);
1479*4882a593Smuzhiyun led->xpad = xpad;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun led_cdev = &led->led_cdev;
1482*4882a593Smuzhiyun led_cdev->name = led->name;
1483*4882a593Smuzhiyun led_cdev->brightness_set = xpad_led_set;
1484*4882a593Smuzhiyun led_cdev->flags = LED_CORE_SUSPENDRESUME;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun error = led_classdev_register(&xpad->udev->dev, led_cdev);
1487*4882a593Smuzhiyun if (error)
1488*4882a593Smuzhiyun goto err_free_id;
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun xpad_identify_controller(xpad);
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun return 0;
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun err_free_id:
1495*4882a593Smuzhiyun ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
1496*4882a593Smuzhiyun err_free_mem:
1497*4882a593Smuzhiyun kfree(led);
1498*4882a593Smuzhiyun xpad->led = NULL;
1499*4882a593Smuzhiyun return error;
1500*4882a593Smuzhiyun }
1501*4882a593Smuzhiyun
xpad_led_disconnect(struct usb_xpad * xpad)1502*4882a593Smuzhiyun static void xpad_led_disconnect(struct usb_xpad *xpad)
1503*4882a593Smuzhiyun {
1504*4882a593Smuzhiyun struct xpad_led *xpad_led = xpad->led;
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun if (xpad_led) {
1507*4882a593Smuzhiyun led_classdev_unregister(&xpad_led->led_cdev);
1508*4882a593Smuzhiyun ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
1509*4882a593Smuzhiyun kfree(xpad_led);
1510*4882a593Smuzhiyun }
1511*4882a593Smuzhiyun }
1512*4882a593Smuzhiyun #else
xpad_led_probe(struct usb_xpad * xpad)1513*4882a593Smuzhiyun static int xpad_led_probe(struct usb_xpad *xpad) { return 0; }
xpad_led_disconnect(struct usb_xpad * xpad)1514*4882a593Smuzhiyun static void xpad_led_disconnect(struct usb_xpad *xpad) { }
1515*4882a593Smuzhiyun #endif
1516*4882a593Smuzhiyun
xpad_start_input(struct usb_xpad * xpad)1517*4882a593Smuzhiyun static int xpad_start_input(struct usb_xpad *xpad)
1518*4882a593Smuzhiyun {
1519*4882a593Smuzhiyun int error;
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
1522*4882a593Smuzhiyun return -EIO;
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOXONE) {
1525*4882a593Smuzhiyun error = xpad_start_xbox_one(xpad);
1526*4882a593Smuzhiyun if (error) {
1527*4882a593Smuzhiyun usb_kill_urb(xpad->irq_in);
1528*4882a593Smuzhiyun return error;
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun }
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun return 0;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun
xpad_stop_input(struct usb_xpad * xpad)1535*4882a593Smuzhiyun static void xpad_stop_input(struct usb_xpad *xpad)
1536*4882a593Smuzhiyun {
1537*4882a593Smuzhiyun usb_kill_urb(xpad->irq_in);
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun
xpad360w_poweroff_controller(struct usb_xpad * xpad)1540*4882a593Smuzhiyun static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
1541*4882a593Smuzhiyun {
1542*4882a593Smuzhiyun unsigned long flags;
1543*4882a593Smuzhiyun struct xpad_output_packet *packet =
1544*4882a593Smuzhiyun &xpad->out_packets[XPAD_OUT_CMD_IDX];
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun spin_lock_irqsave(&xpad->odata_lock, flags);
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun packet->data[0] = 0x00;
1549*4882a593Smuzhiyun packet->data[1] = 0x00;
1550*4882a593Smuzhiyun packet->data[2] = 0x08;
1551*4882a593Smuzhiyun packet->data[3] = 0xC0;
1552*4882a593Smuzhiyun packet->data[4] = 0x00;
1553*4882a593Smuzhiyun packet->data[5] = 0x00;
1554*4882a593Smuzhiyun packet->data[6] = 0x00;
1555*4882a593Smuzhiyun packet->data[7] = 0x00;
1556*4882a593Smuzhiyun packet->data[8] = 0x00;
1557*4882a593Smuzhiyun packet->data[9] = 0x00;
1558*4882a593Smuzhiyun packet->data[10] = 0x00;
1559*4882a593Smuzhiyun packet->data[11] = 0x00;
1560*4882a593Smuzhiyun packet->len = 12;
1561*4882a593Smuzhiyun packet->pending = true;
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun /* Reset the sequence so we send out poweroff now */
1564*4882a593Smuzhiyun xpad->last_out_packet = -1;
1565*4882a593Smuzhiyun xpad_try_sending_next_out_packet(xpad);
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun spin_unlock_irqrestore(&xpad->odata_lock, flags);
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun
xpad360w_start_input(struct usb_xpad * xpad)1570*4882a593Smuzhiyun static int xpad360w_start_input(struct usb_xpad *xpad)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun int error;
1573*4882a593Smuzhiyun
1574*4882a593Smuzhiyun error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
1575*4882a593Smuzhiyun if (error)
1576*4882a593Smuzhiyun return -EIO;
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun /*
1579*4882a593Smuzhiyun * Send presence packet.
1580*4882a593Smuzhiyun * This will force the controller to resend connection packets.
1581*4882a593Smuzhiyun * This is useful in the case we activate the module after the
1582*4882a593Smuzhiyun * adapter has been plugged in, as it won't automatically
1583*4882a593Smuzhiyun * send us info about the controllers.
1584*4882a593Smuzhiyun */
1585*4882a593Smuzhiyun error = xpad_inquiry_pad_presence(xpad);
1586*4882a593Smuzhiyun if (error) {
1587*4882a593Smuzhiyun usb_kill_urb(xpad->irq_in);
1588*4882a593Smuzhiyun return error;
1589*4882a593Smuzhiyun }
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun return 0;
1592*4882a593Smuzhiyun }
1593*4882a593Smuzhiyun
xpad360w_stop_input(struct usb_xpad * xpad)1594*4882a593Smuzhiyun static void xpad360w_stop_input(struct usb_xpad *xpad)
1595*4882a593Smuzhiyun {
1596*4882a593Smuzhiyun usb_kill_urb(xpad->irq_in);
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun /* Make sure we are done with presence work if it was scheduled */
1599*4882a593Smuzhiyun flush_work(&xpad->work);
1600*4882a593Smuzhiyun }
1601*4882a593Smuzhiyun
xpad_open(struct input_dev * dev)1602*4882a593Smuzhiyun static int xpad_open(struct input_dev *dev)
1603*4882a593Smuzhiyun {
1604*4882a593Smuzhiyun struct usb_xpad *xpad = input_get_drvdata(dev);
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun return xpad_start_input(xpad);
1607*4882a593Smuzhiyun }
1608*4882a593Smuzhiyun
xpad_close(struct input_dev * dev)1609*4882a593Smuzhiyun static void xpad_close(struct input_dev *dev)
1610*4882a593Smuzhiyun {
1611*4882a593Smuzhiyun struct usb_xpad *xpad = input_get_drvdata(dev);
1612*4882a593Smuzhiyun
1613*4882a593Smuzhiyun xpad_stop_input(xpad);
1614*4882a593Smuzhiyun }
1615*4882a593Smuzhiyun
xpad_set_up_abs(struct input_dev * input_dev,signed short abs)1616*4882a593Smuzhiyun static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
1617*4882a593Smuzhiyun {
1618*4882a593Smuzhiyun struct usb_xpad *xpad = input_get_drvdata(input_dev);
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun switch (abs) {
1621*4882a593Smuzhiyun case ABS_X:
1622*4882a593Smuzhiyun case ABS_Y:
1623*4882a593Smuzhiyun case ABS_RX:
1624*4882a593Smuzhiyun case ABS_RY: /* the two sticks */
1625*4882a593Smuzhiyun input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128);
1626*4882a593Smuzhiyun break;
1627*4882a593Smuzhiyun case ABS_Z:
1628*4882a593Smuzhiyun case ABS_RZ: /* the triggers (if mapped to axes) */
1629*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOXONE)
1630*4882a593Smuzhiyun input_set_abs_params(input_dev, abs, 0, 1023, 0, 0);
1631*4882a593Smuzhiyun else
1632*4882a593Smuzhiyun input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
1633*4882a593Smuzhiyun break;
1634*4882a593Smuzhiyun case ABS_HAT0X:
1635*4882a593Smuzhiyun case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
1636*4882a593Smuzhiyun input_set_abs_params(input_dev, abs, -1, 1, 0, 0);
1637*4882a593Smuzhiyun break;
1638*4882a593Smuzhiyun default:
1639*4882a593Smuzhiyun input_set_abs_params(input_dev, abs, 0, 0, 0, 0);
1640*4882a593Smuzhiyun break;
1641*4882a593Smuzhiyun }
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun
xpad_deinit_input(struct usb_xpad * xpad)1644*4882a593Smuzhiyun static void xpad_deinit_input(struct usb_xpad *xpad)
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun if (xpad->input_created) {
1647*4882a593Smuzhiyun xpad->input_created = false;
1648*4882a593Smuzhiyun xpad_led_disconnect(xpad);
1649*4882a593Smuzhiyun input_unregister_device(xpad->dev);
1650*4882a593Smuzhiyun }
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun
xpad_init_input(struct usb_xpad * xpad)1653*4882a593Smuzhiyun static int xpad_init_input(struct usb_xpad *xpad)
1654*4882a593Smuzhiyun {
1655*4882a593Smuzhiyun struct input_dev *input_dev;
1656*4882a593Smuzhiyun int i, error;
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun input_dev = input_allocate_device();
1659*4882a593Smuzhiyun if (!input_dev)
1660*4882a593Smuzhiyun return -ENOMEM;
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun xpad->dev = input_dev;
1663*4882a593Smuzhiyun input_dev->name = xpad->name;
1664*4882a593Smuzhiyun input_dev->phys = xpad->phys;
1665*4882a593Smuzhiyun usb_to_input_id(xpad->udev, &input_dev->id);
1666*4882a593Smuzhiyun
1667*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360W) {
1668*4882a593Smuzhiyun /* x360w controllers and the receiver have different ids */
1669*4882a593Smuzhiyun input_dev->id.product = 0x02a1;
1670*4882a593Smuzhiyun }
1671*4882a593Smuzhiyun
1672*4882a593Smuzhiyun input_dev->dev.parent = &xpad->intf->dev;
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun input_set_drvdata(input_dev, xpad);
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun if (xpad->xtype != XTYPE_XBOX360W) {
1677*4882a593Smuzhiyun input_dev->open = xpad_open;
1678*4882a593Smuzhiyun input_dev->close = xpad_close;
1679*4882a593Smuzhiyun }
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
1682*4882a593Smuzhiyun /* set up axes */
1683*4882a593Smuzhiyun for (i = 0; xpad_abs[i] >= 0; i++)
1684*4882a593Smuzhiyun xpad_set_up_abs(input_dev, xpad_abs[i]);
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun /* set up standard buttons */
1688*4882a593Smuzhiyun for (i = 0; xpad_common_btn[i] >= 0; i++)
1689*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY, xpad_common_btn[i]);
1690*4882a593Smuzhiyun
1691*4882a593Smuzhiyun /* set up model-specific ones */
1692*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
1693*4882a593Smuzhiyun xpad->xtype == XTYPE_XBOXONE) {
1694*4882a593Smuzhiyun for (i = 0; xpad360_btn[i] >= 0; i++)
1695*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY, xpad360_btn[i]);
1696*4882a593Smuzhiyun } else {
1697*4882a593Smuzhiyun for (i = 0; xpad_btn[i] >= 0; i++)
1698*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY, xpad_btn[i]);
1699*4882a593Smuzhiyun }
1700*4882a593Smuzhiyun
1701*4882a593Smuzhiyun if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
1702*4882a593Smuzhiyun for (i = 0; xpad_btn_pad[i] >= 0; i++)
1703*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY,
1704*4882a593Smuzhiyun xpad_btn_pad[i]);
1705*4882a593Smuzhiyun }
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun /*
1708*4882a593Smuzhiyun * This should be a simple else block. However historically
1709*4882a593Smuzhiyun * xbox360w has mapped DPAD to buttons while xbox360 did not. This
1710*4882a593Smuzhiyun * made no sense, but now we can not just switch back and have to
1711*4882a593Smuzhiyun * support both behaviors.
1712*4882a593Smuzhiyun */
1713*4882a593Smuzhiyun if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
1714*4882a593Smuzhiyun xpad->xtype == XTYPE_XBOX360W) {
1715*4882a593Smuzhiyun for (i = 0; xpad_abs_pad[i] >= 0; i++)
1716*4882a593Smuzhiyun xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun
1719*4882a593Smuzhiyun if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
1720*4882a593Smuzhiyun for (i = 0; xpad_btn_triggers[i] >= 0; i++)
1721*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY,
1722*4882a593Smuzhiyun xpad_btn_triggers[i]);
1723*4882a593Smuzhiyun } else {
1724*4882a593Smuzhiyun for (i = 0; xpad_abs_triggers[i] >= 0; i++)
1725*4882a593Smuzhiyun xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun error = xpad_init_ff(xpad);
1729*4882a593Smuzhiyun if (error)
1730*4882a593Smuzhiyun goto err_free_input;
1731*4882a593Smuzhiyun
1732*4882a593Smuzhiyun error = xpad_led_probe(xpad);
1733*4882a593Smuzhiyun if (error)
1734*4882a593Smuzhiyun goto err_destroy_ff;
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun error = input_register_device(xpad->dev);
1737*4882a593Smuzhiyun if (error)
1738*4882a593Smuzhiyun goto err_disconnect_led;
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun xpad->input_created = true;
1741*4882a593Smuzhiyun return 0;
1742*4882a593Smuzhiyun
1743*4882a593Smuzhiyun err_disconnect_led:
1744*4882a593Smuzhiyun xpad_led_disconnect(xpad);
1745*4882a593Smuzhiyun err_destroy_ff:
1746*4882a593Smuzhiyun input_ff_destroy(input_dev);
1747*4882a593Smuzhiyun err_free_input:
1748*4882a593Smuzhiyun input_free_device(input_dev);
1749*4882a593Smuzhiyun return error;
1750*4882a593Smuzhiyun }
1751*4882a593Smuzhiyun
xpad_probe(struct usb_interface * intf,const struct usb_device_id * id)1752*4882a593Smuzhiyun static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
1753*4882a593Smuzhiyun {
1754*4882a593Smuzhiyun struct usb_device *udev = interface_to_usbdev(intf);
1755*4882a593Smuzhiyun struct usb_xpad *xpad;
1756*4882a593Smuzhiyun struct usb_endpoint_descriptor *ep_irq_in, *ep_irq_out;
1757*4882a593Smuzhiyun int i, error;
1758*4882a593Smuzhiyun
1759*4882a593Smuzhiyun if (intf->cur_altsetting->desc.bNumEndpoints != 2)
1760*4882a593Smuzhiyun return -ENODEV;
1761*4882a593Smuzhiyun
1762*4882a593Smuzhiyun for (i = 0; xpad_device[i].idVendor; i++) {
1763*4882a593Smuzhiyun if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
1764*4882a593Smuzhiyun (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct))
1765*4882a593Smuzhiyun break;
1766*4882a593Smuzhiyun }
1767*4882a593Smuzhiyun
1768*4882a593Smuzhiyun xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
1769*4882a593Smuzhiyun if (!xpad)
1770*4882a593Smuzhiyun return -ENOMEM;
1771*4882a593Smuzhiyun
1772*4882a593Smuzhiyun usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
1773*4882a593Smuzhiyun strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
1774*4882a593Smuzhiyun
1775*4882a593Smuzhiyun xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
1776*4882a593Smuzhiyun GFP_KERNEL, &xpad->idata_dma);
1777*4882a593Smuzhiyun if (!xpad->idata) {
1778*4882a593Smuzhiyun error = -ENOMEM;
1779*4882a593Smuzhiyun goto err_free_mem;
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun
1782*4882a593Smuzhiyun xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
1783*4882a593Smuzhiyun if (!xpad->irq_in) {
1784*4882a593Smuzhiyun error = -ENOMEM;
1785*4882a593Smuzhiyun goto err_free_idata;
1786*4882a593Smuzhiyun }
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun xpad->udev = udev;
1789*4882a593Smuzhiyun xpad->intf = intf;
1790*4882a593Smuzhiyun xpad->mapping = xpad_device[i].mapping;
1791*4882a593Smuzhiyun xpad->xtype = xpad_device[i].xtype;
1792*4882a593Smuzhiyun xpad->name = xpad_device[i].name;
1793*4882a593Smuzhiyun INIT_WORK(&xpad->work, xpad_presence_work);
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun if (xpad->xtype == XTYPE_UNKNOWN) {
1796*4882a593Smuzhiyun if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
1797*4882a593Smuzhiyun if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
1798*4882a593Smuzhiyun xpad->xtype = XTYPE_XBOX360W;
1799*4882a593Smuzhiyun else if (intf->cur_altsetting->desc.bInterfaceProtocol == 208)
1800*4882a593Smuzhiyun xpad->xtype = XTYPE_XBOXONE;
1801*4882a593Smuzhiyun else
1802*4882a593Smuzhiyun xpad->xtype = XTYPE_XBOX360;
1803*4882a593Smuzhiyun } else {
1804*4882a593Smuzhiyun xpad->xtype = XTYPE_XBOX;
1805*4882a593Smuzhiyun }
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun if (dpad_to_buttons)
1808*4882a593Smuzhiyun xpad->mapping |= MAP_DPAD_TO_BUTTONS;
1809*4882a593Smuzhiyun if (triggers_to_buttons)
1810*4882a593Smuzhiyun xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;
1811*4882a593Smuzhiyun if (sticks_to_null)
1812*4882a593Smuzhiyun xpad->mapping |= MAP_STICKS_TO_NULL;
1813*4882a593Smuzhiyun }
1814*4882a593Smuzhiyun
1815*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOXONE &&
1816*4882a593Smuzhiyun intf->cur_altsetting->desc.bInterfaceNumber != 0) {
1817*4882a593Smuzhiyun /*
1818*4882a593Smuzhiyun * The Xbox One controller lists three interfaces all with the
1819*4882a593Smuzhiyun * same interface class, subclass and protocol. Differentiate by
1820*4882a593Smuzhiyun * interface number.
1821*4882a593Smuzhiyun */
1822*4882a593Smuzhiyun error = -ENODEV;
1823*4882a593Smuzhiyun goto err_free_in_urb;
1824*4882a593Smuzhiyun }
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun ep_irq_in = ep_irq_out = NULL;
1827*4882a593Smuzhiyun
1828*4882a593Smuzhiyun for (i = 0; i < 2; i++) {
1829*4882a593Smuzhiyun struct usb_endpoint_descriptor *ep =
1830*4882a593Smuzhiyun &intf->cur_altsetting->endpoint[i].desc;
1831*4882a593Smuzhiyun
1832*4882a593Smuzhiyun if (usb_endpoint_xfer_int(ep)) {
1833*4882a593Smuzhiyun if (usb_endpoint_dir_in(ep))
1834*4882a593Smuzhiyun ep_irq_in = ep;
1835*4882a593Smuzhiyun else
1836*4882a593Smuzhiyun ep_irq_out = ep;
1837*4882a593Smuzhiyun }
1838*4882a593Smuzhiyun }
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun if (!ep_irq_in || !ep_irq_out) {
1841*4882a593Smuzhiyun error = -ENODEV;
1842*4882a593Smuzhiyun goto err_free_in_urb;
1843*4882a593Smuzhiyun }
1844*4882a593Smuzhiyun
1845*4882a593Smuzhiyun error = xpad_init_output(intf, xpad, ep_irq_out);
1846*4882a593Smuzhiyun if (error)
1847*4882a593Smuzhiyun goto err_free_in_urb;
1848*4882a593Smuzhiyun
1849*4882a593Smuzhiyun usb_fill_int_urb(xpad->irq_in, udev,
1850*4882a593Smuzhiyun usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
1851*4882a593Smuzhiyun xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
1852*4882a593Smuzhiyun xpad, ep_irq_in->bInterval);
1853*4882a593Smuzhiyun xpad->irq_in->transfer_dma = xpad->idata_dma;
1854*4882a593Smuzhiyun xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun usb_set_intfdata(intf, xpad);
1857*4882a593Smuzhiyun
1858*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360W) {
1859*4882a593Smuzhiyun /*
1860*4882a593Smuzhiyun * Submit the int URB immediately rather than waiting for open
1861*4882a593Smuzhiyun * because we get status messages from the device whether
1862*4882a593Smuzhiyun * or not any controllers are attached. In fact, it's
1863*4882a593Smuzhiyun * exactly the message that a controller has arrived that
1864*4882a593Smuzhiyun * we're waiting for.
1865*4882a593Smuzhiyun */
1866*4882a593Smuzhiyun error = xpad360w_start_input(xpad);
1867*4882a593Smuzhiyun if (error)
1868*4882a593Smuzhiyun goto err_deinit_output;
1869*4882a593Smuzhiyun /*
1870*4882a593Smuzhiyun * Wireless controllers require RESET_RESUME to work properly
1871*4882a593Smuzhiyun * after suspend. Ideally this quirk should be in usb core
1872*4882a593Smuzhiyun * quirk list, but we have too many vendors producing these
1873*4882a593Smuzhiyun * controllers and we'd need to maintain 2 identical lists
1874*4882a593Smuzhiyun * here in this driver and in usb core.
1875*4882a593Smuzhiyun */
1876*4882a593Smuzhiyun udev->quirks |= USB_QUIRK_RESET_RESUME;
1877*4882a593Smuzhiyun } else {
1878*4882a593Smuzhiyun error = xpad_init_input(xpad);
1879*4882a593Smuzhiyun if (error)
1880*4882a593Smuzhiyun goto err_deinit_output;
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun return 0;
1883*4882a593Smuzhiyun
1884*4882a593Smuzhiyun err_deinit_output:
1885*4882a593Smuzhiyun xpad_deinit_output(xpad);
1886*4882a593Smuzhiyun err_free_in_urb:
1887*4882a593Smuzhiyun usb_free_urb(xpad->irq_in);
1888*4882a593Smuzhiyun err_free_idata:
1889*4882a593Smuzhiyun usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
1890*4882a593Smuzhiyun err_free_mem:
1891*4882a593Smuzhiyun kfree(xpad);
1892*4882a593Smuzhiyun return error;
1893*4882a593Smuzhiyun }
1894*4882a593Smuzhiyun
xpad_disconnect(struct usb_interface * intf)1895*4882a593Smuzhiyun static void xpad_disconnect(struct usb_interface *intf)
1896*4882a593Smuzhiyun {
1897*4882a593Smuzhiyun struct usb_xpad *xpad = usb_get_intfdata(intf);
1898*4882a593Smuzhiyun
1899*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360W)
1900*4882a593Smuzhiyun xpad360w_stop_input(xpad);
1901*4882a593Smuzhiyun
1902*4882a593Smuzhiyun xpad_deinit_input(xpad);
1903*4882a593Smuzhiyun
1904*4882a593Smuzhiyun /*
1905*4882a593Smuzhiyun * Now that both input device and LED device are gone we can
1906*4882a593Smuzhiyun * stop output URB.
1907*4882a593Smuzhiyun */
1908*4882a593Smuzhiyun xpad_stop_output(xpad);
1909*4882a593Smuzhiyun
1910*4882a593Smuzhiyun xpad_deinit_output(xpad);
1911*4882a593Smuzhiyun
1912*4882a593Smuzhiyun usb_free_urb(xpad->irq_in);
1913*4882a593Smuzhiyun usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
1914*4882a593Smuzhiyun xpad->idata, xpad->idata_dma);
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun kfree(xpad);
1917*4882a593Smuzhiyun
1918*4882a593Smuzhiyun usb_set_intfdata(intf, NULL);
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun
xpad_suspend(struct usb_interface * intf,pm_message_t message)1921*4882a593Smuzhiyun static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun struct usb_xpad *xpad = usb_get_intfdata(intf);
1924*4882a593Smuzhiyun struct input_dev *input = xpad->dev;
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360W) {
1927*4882a593Smuzhiyun /*
1928*4882a593Smuzhiyun * Wireless controllers always listen to input so
1929*4882a593Smuzhiyun * they are notified when controller shows up
1930*4882a593Smuzhiyun * or goes away.
1931*4882a593Smuzhiyun */
1932*4882a593Smuzhiyun xpad360w_stop_input(xpad);
1933*4882a593Smuzhiyun
1934*4882a593Smuzhiyun /*
1935*4882a593Smuzhiyun * The wireless adapter is going off now, so the
1936*4882a593Smuzhiyun * gamepads are going to become disconnected.
1937*4882a593Smuzhiyun * Unless explicitly disabled, power them down
1938*4882a593Smuzhiyun * so they don't just sit there flashing.
1939*4882a593Smuzhiyun */
1940*4882a593Smuzhiyun if (auto_poweroff && xpad->pad_present)
1941*4882a593Smuzhiyun xpad360w_poweroff_controller(xpad);
1942*4882a593Smuzhiyun } else {
1943*4882a593Smuzhiyun mutex_lock(&input->mutex);
1944*4882a593Smuzhiyun if (input->users)
1945*4882a593Smuzhiyun xpad_stop_input(xpad);
1946*4882a593Smuzhiyun mutex_unlock(&input->mutex);
1947*4882a593Smuzhiyun }
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun xpad_stop_output(xpad);
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun return 0;
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun
xpad_resume(struct usb_interface * intf)1954*4882a593Smuzhiyun static int xpad_resume(struct usb_interface *intf)
1955*4882a593Smuzhiyun {
1956*4882a593Smuzhiyun struct usb_xpad *xpad = usb_get_intfdata(intf);
1957*4882a593Smuzhiyun struct input_dev *input = xpad->dev;
1958*4882a593Smuzhiyun int retval = 0;
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun if (xpad->xtype == XTYPE_XBOX360W) {
1961*4882a593Smuzhiyun retval = xpad360w_start_input(xpad);
1962*4882a593Smuzhiyun } else {
1963*4882a593Smuzhiyun mutex_lock(&input->mutex);
1964*4882a593Smuzhiyun if (input->users) {
1965*4882a593Smuzhiyun retval = xpad_start_input(xpad);
1966*4882a593Smuzhiyun } else if (xpad->xtype == XTYPE_XBOXONE) {
1967*4882a593Smuzhiyun /*
1968*4882a593Smuzhiyun * Even if there are no users, we'll send Xbox One pads
1969*4882a593Smuzhiyun * the startup sequence so they don't sit there and
1970*4882a593Smuzhiyun * blink until somebody opens the input device again.
1971*4882a593Smuzhiyun */
1972*4882a593Smuzhiyun retval = xpad_start_xbox_one(xpad);
1973*4882a593Smuzhiyun }
1974*4882a593Smuzhiyun mutex_unlock(&input->mutex);
1975*4882a593Smuzhiyun }
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun return retval;
1978*4882a593Smuzhiyun }
1979*4882a593Smuzhiyun
1980*4882a593Smuzhiyun static struct usb_driver xpad_driver = {
1981*4882a593Smuzhiyun .name = "xpad",
1982*4882a593Smuzhiyun .probe = xpad_probe,
1983*4882a593Smuzhiyun .disconnect = xpad_disconnect,
1984*4882a593Smuzhiyun .suspend = xpad_suspend,
1985*4882a593Smuzhiyun .resume = xpad_resume,
1986*4882a593Smuzhiyun .id_table = xpad_table,
1987*4882a593Smuzhiyun };
1988*4882a593Smuzhiyun
1989*4882a593Smuzhiyun module_usb_driver(xpad_driver);
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun MODULE_AUTHOR("Marko Friedemann <mfr@bmx-chemnitz.de>");
1992*4882a593Smuzhiyun MODULE_DESCRIPTION("X-Box pad driver");
1993*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1994