diff mbox

[RFC,24/26] HID: wiimote: support Nintendo Wii U Pro Controller

Message ID 1367788390-29835-25-git-send-email-dh.herrmann@gmail.com (mailing list archive)
State New, archived
Delegated to: Jiri Kosina
Headers show

Commit Message

David Herrmann May 5, 2013, 9:13 p.m. UTC
The Wii U Pro Controller is a new Nintendo remote device that looks very
similar to the XBox controller. It has nearly the same features and uses
the same protocol as the Wii Remote.

We add a new wiimote extension device so the Pro Controller is properly
detected and supported.

The device reports MP support, which is odd and I couldn't get it working,
yet. Hence, we disable MP registers for now. Further investigation is
needed to see what extra capabilities are provided.

There are some other unknown bits in the extension reports that I couldn't
figure out what they do. You can use hidraw to access these if you're
interested.

We might want to hook up the "charging" and "USB" bits to the battery
device so user-space can query whether it is currently charged via USB.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/hid/hid-wiimote-core.c    |  23 +++
 drivers/hid/hid-wiimote-modules.c | 295 ++++++++++++++++++++++++++++++++++++++
 drivers/hid/hid-wiimote.h         |   2 +
 3 files changed, 320 insertions(+)

Comments

Todd Showalter May 6, 2013, 12:43 a.m. UTC | #1
On Sun, May 5, 2013 at 5:13 PM, David Herrmann <dh.herrmann@gmail.com> wrote:

> The Wii U Pro Controller is a new Nintendo remote device that looks very
> similar to the XBox controller. It has nearly the same features and uses
> the same protocol as the Wii Remote.

    As with the classic controller, could this please be mapped to the
standard gamepad where possible?

                                      Todd.

--
 Todd Showalter, President,
 Electron Jump Games, Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Herrmann May 6, 2013, 5:49 a.m. UTC | #2
Hi Todd

On Mon, May 6, 2013 at 2:43 AM, Todd Showalter <todd@electronjump.com> wrote:
> On Sun, May 5, 2013 at 5:13 PM, David Herrmann <dh.herrmann@gmail.com> wrote:
>
>> The Wii U Pro Controller is a new Nintendo remote device that looks very
>> similar to the XBox controller. It has nearly the same features and uses
>> the same protocol as the Wii Remote.
>
>     As with the classic controller, could this please be mapped to the
> standard gamepad where possible?

> - left stick to ABS_LX, ABS_LY
> - right stick to ABS_RX, ABS_RY

These make sense to me, indeed.

> - dpad to ABS_DX, ABS_DY

These are digital buttons on this gamepad. What's wrong with
KEY_{left, right, up, down}? Or I would prefer BTN_{left, right, up,
down} instead.

> - left trigger to ABS_LTRIG
> - right trigger to ABS_RTRIG

These are also digital buttons, so what's wrong with BTN_TL/TR?

> - x to BTN_NORTH
> - a to BTN_EAST
> - b to BTN_SOUTH
> - y to BTN_WEST

These make sense to me. At least keyboards also return the American
keycodes instead of trying to guess the label. However, if you want
"help texts" in your applications, like "press A to continue", you
need a user-space helper library, anyway. Otherwise, you cannot be
sure this key is labeled "A" on the current device.
That's also the reason why I don't think these mappings really help.

> - zl to BTN_LSHOULDER
> - zr to BTN_RSHOULDER

Again, why not reuse BTN_ZL/ZR?

> - plus to BTN_START
> - minus to BTN_SELECT
> - home to BTN_SYSTEM

The other Nintendo drivers return BTN_MODE for "home". Could you
explain what's wrong with that?

Thanks!
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Todd Showalter May 6, 2013, 2:14 p.m. UTC | #3
On Mon, May 6, 2013 at 1:49 AM, David Herrmann <dh.herrmann@gmail.com> wrote:

>>> The Wii U Pro Controller is a new Nintendo remote device that looks very
>>> similar to the XBox controller. It has nearly the same features and uses
>>> the same protocol as the Wii Remote.
>>
>>     As with the classic controller, could this please be mapped to the
>> standard gamepad where possible?
>
>> - left stick to ABS_LX, ABS_LY
>> - right stick to ABS_RX, ABS_RY
>
> These make sense to me, indeed.
>
>> - dpad to ABS_DX, ABS_DY
>
> These are digital buttons on this gamepad. What's wrong with
> KEY_{left, right, up, down}? Or I would prefer BTN_{left, right, up,
> down} instead.

    Some of the gamepads in evdev currently map their dpads to
ABS_HAT0X, ABS_HAT0Y.  For the most part I'd be good with switching
them to buttons; it's mostly just a matter of choosing a standard and
sticking to it.  The only argument for making them ABS_ values (other
than "some of them already do that") is the Sony controllers; the PS2
and PS3 dpads are actually pressure sensitive, and have an effective
resolution double that of the analog sticks even before you take the
deadzone into account.  The PS* analog sticks are very noisy and need
large deadzones, while the dpad pressure sensitivity is quite stable
around the center for obvious reasons.

>> - left trigger to ABS_LTRIG
>> - right trigger to ABS_RTRIG
>
> These are also digital buttons, so what's wrong with BTN_TL/TR?

    They're digital on the classic pro, but they're analog on the
classic, IIRC.  I believe they also have separate "button" values when
they bottom out, much like the gamecube controller, but that's beyond
the scope of the standard gamepad I'm proposing.

>> - x to BTN_NORTH
>> - a to BTN_EAST
>> - b to BTN_SOUTH
>> - y to BTN_WEST
>
> These make sense to me. At least keyboards also return the American
> keycodes instead of trying to guess the label. However, if you want
> "help texts" in your applications, like "press A to continue", you
> need a user-space helper library, anyway. Otherwise, you cannot be
> sure this key is labeled "A" on the current device.
> That's also the reason why I don't think these mappings really help.

    I'd far rather have position-defined buttons and then some sort of
mapping I could look up to tell me what the label was on the player's
controller.  I might want to put help text up, but I definitely want
to read the button.  Besides, with the standard gamepad I'm proposing
you could throw up a diagram of the controller with (for example) an
arrow pointing to a blank NORTH button just saying "Menu" or "Battloid
Mode" or "Use".

    Making a game is often about deciding where to spend your limited
resources.  Money, time, artwork and programming effort you spend
customizing the help screens for different controllers is effort not
being spent on making the part of the game that people play better.

>> - zl to BTN_LSHOULDER
>> - zr to BTN_RSHOULDER
>
> Again, why not reuse BTN_ZL/ZR?

    Because there are equivalent controls on lots of other gamepads.
L1/R1 on sony gamepads, LB/RB on xbox 360, and so forth.  Again, it's
the position and function that matters, not the arbitrary label on the
button.  The label on the button is only arguably useful for help
text, but there is *so much* variance in labeling between functionally
identical hardware that it makes no sense to waste the development
effort on custom per-controller help text.

>> - plus to BTN_START
>> - minus to BTN_SELECT
>> - home to BTN_SYSTEM
>
> The other Nintendo drivers return BTN_MODE for "home". Could you
> explain what's wrong with that?

    It's not essential; we could make the others do BTN_MODE.  The
idea is that we've got what's essentially a system request button on
many gamepads; a button whose job is to bypass the game and bring up
the underlying OS.  On recent Nintendo controllers (Wii, WiiU) it's
the "Home" button.  On PS3 it's the playstation logo button.  On XBox
360 controllers it's the big glowy X button.

    All of those are attempting to solve the same problem on their
respective consoles; how does one simply get through a full-screen
game to talk to the OS when the gamepad is the primary input method
and all of its functions have game mappings?  The answer in all three
cases was to put a system button on the controller that games aren't
allowed to map.

    We're not bound by that, obviously, but in the case of living room
gaming PCs where we may well have Linux boxes that are being treated
like game consoles much of the time, having a standardized system
request button on gamepads that have appropriate hardware is a useful
abstraction.  I'm suggesting calling it BTN_SYSTEM rather than
BTN_MODE because to me BTN_MODE implies different things, but it's
admittedly semantics at that point.

                                                Todd.

--
 Todd Showalter, President,
 Electron Jump Games, Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Herrmann May 8, 2013, 3:33 p.m. UTC | #4
Hi Todd

On Mon, May 6, 2013 at 4:14 PM, Todd Showalter <todd@electronjump.com> wrote:
> On Mon, May 6, 2013 at 1:49 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
>
>>>> The Wii U Pro Controller is a new Nintendo remote device that looks very
>>>> similar to the XBox controller. It has nearly the same features and uses
>>>> the same protocol as the Wii Remote.
>>>
>>>     As with the classic controller, could this please be mapped to the
>>> standard gamepad where possible?
>>
>>> - left stick to ABS_LX, ABS_LY
>>> - right stick to ABS_RX, ABS_RY
>>
>> These make sense to me, indeed.
>>
>>> - dpad to ABS_DX, ABS_DY
>>
>> These are digital buttons on this gamepad. What's wrong with
>> KEY_{left, right, up, down}? Or I would prefer BTN_{left, right, up,
>> down} instead.
>
>     Some of the gamepads in evdev currently map their dpads to
> ABS_HAT0X, ABS_HAT0Y.  For the most part I'd be good with switching
> them to buttons; it's mostly just a matter of choosing a standard and
> sticking to it.  The only argument for making them ABS_ values (other
> than "some of them already do that") is the Sony controllers; the PS2
> and PS3 dpads are actually pressure sensitive, and have an effective
> resolution double that of the analog sticks even before you take the
> deadzone into account.  The PS* analog sticks are very noisy and need
> large deadzones, while the dpad pressure sensitivity is quite stable
> around the center for obvious reasons.

See below, same reasons apply here.

>>> - left trigger to ABS_LTRIG
>>> - right trigger to ABS_RTRIG
>>
>> These are also digital buttons, so what's wrong with BTN_TL/TR?
>
>     They're digital on the classic pro, but they're analog on the
> classic, IIRC.  I believe they also have separate "button" values when
> they bottom out, much like the gamecube controller, but that's beyond
> the scope of the standard gamepad I'm proposing.

What's the problem with using both, ABS _and_ BTN? I don't think we
should do any interpretation in the kernel. Devices that have analog
triggers report ABS_XTRIG, devices with digital triggers report
BTN_TX. Userspace simply needs to listen for both. And if a device
exports both (like the Wii classic controller), they simply export
both and userspace chooses whatever it prefers.

As long as both ABS_XTRIG and BTN_TX are defined to correspond to the
same triggers, I think it's better to use both. Or am I missing
something?

>>> - x to BTN_NORTH
>>> - a to BTN_EAST
>>> - b to BTN_SOUTH
>>> - y to BTN_WEST
>>
>> These make sense to me. At least keyboards also return the American
>> keycodes instead of trying to guess the label. However, if you want
>> "help texts" in your applications, like "press A to continue", you
>> need a user-space helper library, anyway. Otherwise, you cannot be
>> sure this key is labeled "A" on the current device.
>> That's also the reason why I don't think these mappings really help.
>
>     I'd far rather have position-defined buttons and then some sort of
> mapping I could look up to tell me what the label was on the player's
> controller.  I might want to put help text up, but I definitely want
> to read the button.  Besides, with the standard gamepad I'm proposing
> you could throw up a diagram of the controller with (for example) an
> arrow pointing to a blank NORTH button just saying "Menu" or "Battloid
> Mode" or "Use".
>
>     Making a game is often about deciding where to spend your limited
> resources.  Money, time, artwork and programming effort you spend
> customizing the help screens for different controllers is effort not
> being spent on making the part of the game that people play better.

As I said before, I don't really care. I will send v2 with a patch
that introduces these buttons. Lets see what Dmitry thinks.

But we need a user-space library, anyway, to get button-names (as I
explained earlier).

>>> - zl to BTN_LSHOULDER
>>> - zr to BTN_RSHOULDER
>>
>> Again, why not reuse BTN_ZL/ZR?
>
>     Because there are equivalent controls on lots of other gamepads.
> L1/R1 on sony gamepads, LB/RB on xbox 360, and so forth.  Again, it's
> the position and function that matters, not the arbitrary label on the
> button.  The label on the button is only arguably useful for help
> text, but there is *so much* variance in labeling between functionally
> identical hardware that it makes no sense to waste the development
> effort on custom per-controller help text.

No, I meant what's wrong with re-using BTN_ZX for this purpose? Why
introduce new constants? Just say, all new drivers must not use BTN_ZX
if it's not a shoulder button. This avoids introducing BTN_XSHOULDER.

And btw., there is no BTN_ZL/ZR, I meant BTN_TL2/TR2.. sorry for the
confusion, my bad.

>>> - plus to BTN_START
>>> - minus to BTN_SELECT
>>> - home to BTN_SYSTEM
>>
>> The other Nintendo drivers return BTN_MODE for "home". Could you
>> explain what's wrong with that?
>
>     It's not essential; we could make the others do BTN_MODE.  The
> idea is that we've got what's essentially a system request button on
> many gamepads; a button whose job is to bypass the game and bring up
> the underlying OS.  On recent Nintendo controllers (Wii, WiiU) it's
> the "Home" button.  On PS3 it's the playstation logo button.  On XBox
> 360 controllers it's the big glowy X button.
>
>     All of those are attempting to solve the same problem on their
> respective consoles; how does one simply get through a full-screen
> game to talk to the OS when the gamepad is the primary input method
> and all of its functions have game mappings?  The answer in all three
> cases was to put a system button on the controller that games aren't
> allowed to map.
>
>     We're not bound by that, obviously, but in the case of living room
> gaming PCs where we may well have Linux boxes that are being treated
> like game consoles much of the time, having a standardized system
> request button on gamepads that have appropriate hardware is a useful
> abstraction.  I'm suggesting calling it BTN_SYSTEM rather than
> BTN_MODE because to me BTN_MODE implies different things, but it's
> admittedly semantics at that point.

So how about the following?

+static const __u16 wiimod_pro_map[] = {
+       BTN_EAST,          /* WIIMOD_PRO_KEY_A */
+       BTN_SOUTH,          /* WIIMOD_PRO_KEY_B */
+       BTN_NORTH,          /* WIIMOD_PRO_KEY_X */
+       BTN_WEST,          /* WIIMOD_PRO_KEY_Y */
+       BTN_START,      /* WIIMOD_PRO_KEY_PLUS */
+       BTN_SELECT,     /* WIIMOD_PRO_KEY_MINUS */
+       BTN_MODE,       /* WIIMOD_PRO_KEY_HOME */
+       BTN_DLEFT,       /* WIIMOD_PRO_KEY_LEFT */
+       BTN_DRIGHT,      /* WIIMOD_PRO_KEY_RIGHT */
+       BTN_DUP,         /* WIIMOD_PRO_KEY_UP */
+       BTN_DDOWN,       /* WIIMOD_PRO_KEY_DOWN */
+       BTN_TL,         /* WIIMOD_PRO_KEY_TL */
+       BTN_TR,         /* WIIMOD_PRO_KEY_TR */
+       BTN_TL2,        /* WIIMOD_PRO_KEY_ZL */
+       BTN_TR2,        /* WIIMOD_PRO_KEY_ZR */
+       BTN_THUMBL,     /* WIIMOD_PRO_KEY_THUMBL */
+       BTN_THUMBR,     /* WIIMOD_PRO_KEY_THUMBR */
+};

That would introduce BTN_DLEFT/DRIGHT/DUP/DDOWN for D-Pad buttons and
BTN_EAST/SOUTH/NORTH/WEST for action buttons.

If everyone is ok with this, I will resend the patches for
Pro-Controller after the other parts of this series got
applied/acked/nacked/whatever. I will also add some documentation to
src/Documentation/input/ and try to see what we can do about the other
gamepads.

Thanks
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Todd Showalter May 8, 2013, 4:40 p.m. UTC | #5
On Wed, May 8, 2013 at 11:33 AM, David Herrmann <dh.herrmann@gmail.com> wrote:

>>     They're digital on the classic pro, but they're analog on the
>> classic, IIRC.  I believe they also have separate "button" values when
>> they bottom out, much like the gamecube controller, but that's beyond
>> the scope of the standard gamepad I'm proposing.
>
> What's the problem with using both, ABS _and_ BTN? I don't think we
> should do any interpretation in the kernel. Devices that have analog
> triggers report ABS_XTRIG, devices with digital triggers report
> BTN_TX. Userspace simply needs to listen for both. And if a device
> exports both (like the Wii classic controller), they simply export
> both and userspace chooses whatever it prefers.

    My opinion is that the kernel is the right place to provide
hardware abstraction, and that a standard gamepad is useful the same
way a standard mouse, a standard ethernet device or a standard
filesystem interface are useful abstractions.  That is, I don't want
to have to care who made it if I want to make normal use of it.  My
opinion isn't universally shared, however, so I'm working on a library
to sit between the kernel and things that want a standard gamepad.

> As long as both ABS_XTRIG and BTN_TX are defined to correspond to the
> same triggers, I think it's better to use both. Or am I missing
> something?

    The problem is the specific thing I'm trying to solve with the
idea of the standard gamepad.  Right now, if I open() something in
/dev/input that seems like it ought to be a gamepad, I get a giant
unsorted bag of events that are only comprehensible via a priori
knowledge.  I keep coming back to the ps3 controller because it's the
worst offender that I've found; the right stick maps to ABS_Z, ABS_RZ,
while the XBox controller right stick maps to ABS_RX, ABS_RY.  This is
not documented anywhere I've found, and I've no idea what quirks other
controllers have in their mappings or whether they are documented or
not.

    What I'm trying to do is make it so that there are five categories
of control, in order of usefulness to games:

1) known controls that all sane gamepads will have (left stick, dpad,
NSEW buttons...)
2) known controls that most sane gamepads will have (right stick...)
3) known controls that many gamepads have (system/mode button, select button...)
4) common things (accelerometers...)
5) device-specific controls

    Right now, almost everything is in bucket 5, and from a game
development point of view that sucks.  The further up the buckets we
can move a control, the better.

    So, the problem that I have with "devices that have analog
triggers report XTRIG, devices with digital triggers report TX" is
that absent a common mapping I now potentially have to care about the
difference when I'm developing a game.  It moves these to bucket 3,
which means as a developer I likely just don't use them unless my game
really needs them.

> As I said before, I don't really care. I will send v2 with a patch
> that introduces these buttons. Lets see what Dmitry thinks.
>
> But we need a user-space library, anyway, to get button-names (as I
> explained earlier).

    I'm working on that. :)

> No, I meant what's wrong with re-using BTN_ZX for this purpose? Why
> introduce new constants? Just say, all new drivers must not use BTN_ZX
> if it's not a shoulder button. This avoids introducing BTN_XSHOULDER.

    I suppose we could just use that.  It probably makes more sense to
use BTN_TL and BTN_TR, though; the xbox 360 controller maps LB and RB
to BTN_TL and BTN_TR, and they're equivalent placement and function.

> And btw., there is no BTN_ZL/ZR, I meant BTN_TL2/TR2.. sorry for the
> confusion, my bad.

    Fair enough.

> So how about the following?
>
> +static const __u16 wiimod_pro_map[] = {
> +       BTN_EAST,          /* WIIMOD_PRO_KEY_A */
> +       BTN_SOUTH,          /* WIIMOD_PRO_KEY_B */
> +       BTN_NORTH,          /* WIIMOD_PRO_KEY_X */
> +       BTN_WEST,          /* WIIMOD_PRO_KEY_Y */
> +       BTN_START,      /* WIIMOD_PRO_KEY_PLUS */
> +       BTN_SELECT,     /* WIIMOD_PRO_KEY_MINUS */
> +       BTN_MODE,       /* WIIMOD_PRO_KEY_HOME */
> +       BTN_DLEFT,       /* WIIMOD_PRO_KEY_LEFT */
> +       BTN_DRIGHT,      /* WIIMOD_PRO_KEY_RIGHT */
> +       BTN_DUP,         /* WIIMOD_PRO_KEY_UP */
> +       BTN_DDOWN,       /* WIIMOD_PRO_KEY_DOWN */
> +       BTN_TL,         /* WIIMOD_PRO_KEY_TL */
> +       BTN_TR,         /* WIIMOD_PRO_KEY_TR */
> +       BTN_TL2,        /* WIIMOD_PRO_KEY_ZL */
> +       BTN_TR2,        /* WIIMOD_PRO_KEY_ZR */
> +       BTN_THUMBL,     /* WIIMOD_PRO_KEY_THUMBL */
> +       BTN_THUMBR,     /* WIIMOD_PRO_KEY_THUMBR */
> +};
>
> That would introduce BTN_DLEFT/DRIGHT/DUP/DDOWN for D-Pad buttons and
> BTN_EAST/SOUTH/NORTH/WEST for action buttons.

    That looks fine to me.

                                      Todd.

--
 Todd Showalter, President,
 Electron Jump Games, Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov May 8, 2013, 5:05 p.m. UTC | #6
On Wed, May 08, 2013 at 12:40:51PM -0400, Todd Showalter wrote:
> On Wed, May 8, 2013 at 11:33 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> 
> >>     They're digital on the classic pro, but they're analog on the
> >> classic, IIRC.  I believe they also have separate "button" values when
> >> they bottom out, much like the gamecube controller, but that's beyond
> >> the scope of the standard gamepad I'm proposing.
> >
> > What's the problem with using both, ABS _and_ BTN? I don't think we
> > should do any interpretation in the kernel. Devices that have analog
> > triggers report ABS_XTRIG, devices with digital triggers report
> > BTN_TX. Userspace simply needs to listen for both. And if a device
> > exports both (like the Wii classic controller), they simply export
> > both and userspace chooses whatever it prefers.
> 
>     My opinion is that the kernel is the right place to provide
> hardware abstraction, and that a standard gamepad is useful the same
> way a standard mouse, a standard ethernet device or a standard
> filesystem interface are useful abstractions.  That is, I don't want
> to have to care who made it if I want to make normal use of it.  My
> opinion isn't universally shared, however, so I'm working on a library
> to sit between the kernel and things that want a standard gamepad.
> 
> > As long as both ABS_XTRIG and BTN_TX are defined to correspond to the
> > same triggers, I think it's better to use both. Or am I missing
> > something?
> 
>     The problem is the specific thing I'm trying to solve with the
> idea of the standard gamepad.  Right now, if I open() something in
> /dev/input that seems like it ought to be a gamepad, I get a giant
> unsorted bag of events that are only comprehensible via a priori
> knowledge.  I keep coming back to the ps3 controller because it's the
> worst offender that I've found; the right stick maps to ABS_Z, ABS_RZ,
> while the XBox controller right stick maps to ABS_RX, ABS_RY.  This is
> not documented anywhere I've found, and I've no idea what quirks other
> controllers have in their mappings or whether they are documented or
> not.

So PS3 gamepad is such a mess because we simply do not have a driver
that maps the buttons properly. IIRC it gets bound to a generic HID
driver that enumerates absolute axis in a very naive fashion. I think
there were some effort in making PS3 work in userspace (in BT mode), but
I do not know if it was ever completed.

So for PS3 what we need is a HID driver providing proper mapping,
nothing more, nothing less.

> 
>     What I'm trying to do is make it so that there are five categories
> of control, in order of usefulness to games:
> 
> 1) known controls that all sane gamepads will have (left stick, dpad,
> NSEW buttons...)
> 2) known controls that most sane gamepads will have (right stick...)
> 3) known controls that many gamepads have (system/mode button, select button...)
> 4) common things (accelerometers...)
> 5) device-specific controls
> 
>     Right now, almost everything is in bucket 5, and from a game
> development point of view that sucks.  The further up the buckets we
> can move a control, the better.
> 
>     So, the problem that I have with "devices that have analog
> triggers report XTRIG, devices with digital triggers report TX" is
> that absent a common mapping I now potentially have to care about the
> difference when I'm developing a game.  It moves these to bucket 3,
> which means as a developer I likely just don't use them unless my game
> really needs them.

Or you have your library that provides ABS->BTN translation.

You can even have your API structured such that consumer provides list
of events it is interested in and the library tries to synthesize
missing events if it can.

> 
> > As I said before, I don't really care. I will send v2 with a patch
> > that introduces these buttons. Lets see what Dmitry thinks.

So we already have:

#define BTN_A                   0x130
#define BTN_B                   0x131
#define BTN_C                   0x132
#define BTN_X                   0x133
#define BTN_Y                   0x134
#define BTN_Z                   0x135
#define BTN_TL                  0x136
#define BTN_TR                  0x137
#define BTN_TL2                 0x138
#define BTN_TR2                 0x139
#define BTN_SELECT              0x13a
#define BTN_START               0x13b
#define BTN_MODE                0x13c
#define BTN_THUMBL              0x13d
#define BTN_THUMBR              0x13e

So if we really want to have BTN_NORTH, etc, we want to alias existing
ones.
Todd Showalter May 8, 2013, 5:20 p.m. UTC | #7
On Wed, May 8, 2013 at 1:05 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:

> Or you have your library that provides ABS->BTN translation.
>
> You can even have your API structured such that consumer provides list
> of events it is interested in and the library tries to synthesize
> missing events if it can.

    That's in the plans.

> So we already have:
>
> #define BTN_A                   0x130
> #define BTN_B                   0x131
> #define BTN_C                   0x132
> #define BTN_X                   0x133
> #define BTN_Y                   0x134
> #define BTN_Z                   0x135
> #define BTN_TL                  0x136
> #define BTN_TR                  0x137
> #define BTN_TL2                 0x138
> #define BTN_TR2                 0x139
> #define BTN_SELECT              0x13a
> #define BTN_START               0x13b
> #define BTN_MODE                0x13c
> #define BTN_THUMBL              0x13d
> #define BTN_THUMBR              0x13e
>
> So if we really want to have BTN_NORTH, etc, we want to alias existing
> ones.

    The problem is that the alias differs with hardware.  BTN_A would be:

- BTN_SOUTH on xbox gamepads
- BTN_EAST on nintendo gamepads and ouya

    Nintendo is:

A -> WEST
B -> SOUTH
X -> NORTH
Y -> EAST

   While Microsoft is:

A -> SOUTH
B -> EAST
X -> WEST
Y -> NORTH

    They're mirror images of each other. So just aliasing is going to
break something.

                                       Todd.

--
 Todd Showalter, President,
 Electron Jump Games, Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Herrmann May 8, 2013, 5:25 p.m. UTC | #8
Hi Todd

On Wed, May 8, 2013 at 7:20 PM, Todd Showalter <todd@electronjump.com> wrote:
> On Wed, May 8, 2013 at 1:05 PM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
>
>> Or you have your library that provides ABS->BTN translation.
>>
>> You can even have your API structured such that consumer provides list
>> of events it is interested in and the library tries to synthesize
>> missing events if it can.
>
>     That's in the plans.
>
>> So we already have:
>>
>> #define BTN_A                   0x130
>> #define BTN_B                   0x131
>> #define BTN_C                   0x132
>> #define BTN_X                   0x133
>> #define BTN_Y                   0x134
>> #define BTN_Z                   0x135
>> #define BTN_TL                  0x136
>> #define BTN_TR                  0x137
>> #define BTN_TL2                 0x138
>> #define BTN_TR2                 0x139
>> #define BTN_SELECT              0x13a
>> #define BTN_START               0x13b
>> #define BTN_MODE                0x13c
>> #define BTN_THUMBL              0x13d
>> #define BTN_THUMBR              0x13e
>>
>> So if we really want to have BTN_NORTH, etc, we want to alias existing
>> ones.
>
>     The problem is that the alias differs with hardware.  BTN_A would be:
>
> - BTN_SOUTH on xbox gamepads
> - BTN_EAST on nintendo gamepads and ouya
>
>     Nintendo is:
>
> A -> WEST
> B -> SOUTH
> X -> NORTH
> Y -> EAST
>
>    While Microsoft is:
>
> A -> SOUTH
> B -> EAST
> X -> WEST
> Y -> NORTH
>
>     They're mirror images of each other. So just aliasing is going to
> break something.

No. Just ignore BTN_A/B/X/Y, use BTN_EAST/WEST/NORTH/SOUTH instead.
Only for legacy gamepads with wrong mappings you might reuse these. So
we basically overwrite the old names.
So you no longer care for BTN_A/B/X/Y and they will no longer
represent the labels of the buttons, but instead the location.

Regards
David
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov May 8, 2013, 5:26 p.m. UTC | #9
On Wed, May 08, 2013 at 01:20:58PM -0400, Todd Showalter wrote:
> On Wed, May 8, 2013 at 1:05 PM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> 
> > Or you have your library that provides ABS->BTN translation.
> >
> > You can even have your API structured such that consumer provides list
> > of events it is interested in and the library tries to synthesize
> > missing events if it can.
> 
>     That's in the plans.
> 
> > So we already have:
> >
> > #define BTN_A                   0x130
> > #define BTN_B                   0x131
> > #define BTN_C                   0x132
> > #define BTN_X                   0x133
> > #define BTN_Y                   0x134
> > #define BTN_Z                   0x135
> > #define BTN_TL                  0x136
> > #define BTN_TR                  0x137
> > #define BTN_TL2                 0x138
> > #define BTN_TR2                 0x139
> > #define BTN_SELECT              0x13a
> > #define BTN_START               0x13b
> > #define BTN_MODE                0x13c
> > #define BTN_THUMBL              0x13d
> > #define BTN_THUMBR              0x13e
> >
> > So if we really want to have BTN_NORTH, etc, we want to alias existing
> > ones.
> 
>     The problem is that the alias differs with hardware.  BTN_A would be:
> 
> - BTN_SOUTH on xbox gamepads
> - BTN_EAST on nintendo gamepads and ouya
> 
>     Nintendo is:
> 
> A -> WEST
> B -> SOUTH
> X -> NORTH
> Y -> EAST
> 
>    While Microsoft is:
> 
> A -> SOUTH
> B -> EAST
> X -> WEST
> Y -> NORTH
> 
>     They're mirror images of each other. So just aliasing is going to
> break something.

We should take existing in-kernel mapping (that would be XBOX and other
less advanced gamepads in drivers/input/joystick), alias
NORTH/SOUTH/EAST/WEST accordingly, have new users use NSEW button
definitions.

Thanks.
diff mbox

Patch

diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 3e69656..279a07d 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -452,6 +452,8 @@  static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
 		return WIIMOTE_EXT_CLASSIC_CONTROLLER;
 	if (rmem[4] == 0x04 && rmem[5] == 0x02)
 		return WIIMOTE_EXT_BALANCE_BOARD;
+	if (rmem[4] == 0x01 && rmem[5] == 0x20)
+		return WIIMOTE_EXT_PRO_CONTROLLER;
 
 	return WIIMOTE_EXT_UNKNOWN;
 }
@@ -601,6 +603,15 @@  static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = {
 		WIIMOD_NO_MP,
 		WIIMOD_NULL,
 	},
+	[WIIMOTE_DEV_PRO_CONTROLLER] = (const __u8[]) {
+		WIIMOD_BATTERY,
+		WIIMOD_LED1,
+		WIIMOD_LED2,
+		WIIMOD_LED3,
+		WIIMOD_LED4,
+		WIIMOD_NO_MP,
+		WIIMOD_NULL,
+	},
 };
 
 static void wiimote_modules_load(struct wiimote_data *wdata,
@@ -785,6 +796,7 @@  static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = {
 	[WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)",
 	[WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)",
 	[WIIMOTE_DEV_BALANCE_BOARD] = "Nintendo Wii Balance Board",
+	[WIIMOTE_DEV_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
 };
 
 /* Try to guess the device type based on all collected information. We
@@ -805,6 +817,9 @@  static void wiimote_init_set_type(struct wiimote_data *wdata,
 	if (exttype == WIIMOTE_EXT_BALANCE_BOARD) {
 		devtype = WIIMOTE_DEV_BALANCE_BOARD;
 		goto done;
+	} else if (exttype == WIIMOTE_EXT_PRO_CONTROLLER) {
+		devtype = WIIMOTE_DEV_PRO_CONTROLLER;
+		goto done;
 	}
 
 	if (!strcmp(name, "Nintendo RVL-CNT-01")) {
@@ -816,6 +831,9 @@  static void wiimote_init_set_type(struct wiimote_data *wdata,
 	} else if (!strcmp(name, "Nintendo RVL-WBC-01")) {
 		devtype = WIIMOTE_DEV_BALANCE_BOARD;
 		goto done;
+	} else if (!strcmp(name, "Nintendo RVL-CNT-01-UC")) {
+		devtype = WIIMOTE_DEV_PRO_CONTROLLER;
+		goto done;
 	}
 
 	if (vendor == USB_VENDOR_ID_NINTENDO) {
@@ -1058,6 +1076,7 @@  static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
 	[WIIMOTE_EXT_NUNCHUK] = "Nintendo Wii Nunchuk",
 	[WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
 	[WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
+	[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
 };
 
 /*
@@ -1634,6 +1653,8 @@  static ssize_t wiimote_ext_show(struct device *dev,
 		return sprintf(buf, "classic\n");
 	case WIIMOTE_EXT_BALANCE_BOARD:
 		return sprintf(buf, "balanceboard\n");
+	case WIIMOTE_EXT_PRO_CONTROLLER:
+		return sprintf(buf, "procontroller\n");
 	case WIIMOTE_EXT_UNKNOWN:
 		/* fallthrough */
 	default:
@@ -1680,6 +1701,8 @@  static ssize_t wiimote_dev_show(struct device *dev,
 		return sprintf(buf, "gen20\n");
 	case WIIMOTE_DEV_BALANCE_BOARD:
 		return sprintf(buf, "balanceboard\n");
+	case WIIMOTE_DEV_PRO_CONTROLLER:
+		return sprintf(buf, "procontroller\n");
 	case WIIMOTE_DEV_PENDING:
 		return sprintf(buf, "pending\n");
 	case WIIMOTE_DEV_UNKNOWN:
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index e2afe06..ab25a64 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1540,6 +1540,300 @@  static const struct wiimod_ops wiimod_bboard = {
 };
 
 /*
+ * Pro Controller
+ * Released with the Wii U was the Nintendo Wii U Pro Controller. It does not
+ * work together with the classic Wii, but only with the new Wii U. However, it
+ * uses the same protocol and provides a builtin "classic controller pro"
+ * extension, few standard buttons, a rumble motor, 4 LEDs and a battery.
+ * We provide all these via a standard extension device as the device doesn't
+ * feature an extension port.
+ */
+
+enum wiimod_pro_keys {
+	WIIMOD_PRO_KEY_A,
+	WIIMOD_PRO_KEY_B,
+	WIIMOD_PRO_KEY_X,
+	WIIMOD_PRO_KEY_Y,
+	WIIMOD_PRO_KEY_PLUS,
+	WIIMOD_PRO_KEY_MINUS,
+	WIIMOD_PRO_KEY_HOME,
+	WIIMOD_PRO_KEY_LEFT,
+	WIIMOD_PRO_KEY_RIGHT,
+	WIIMOD_PRO_KEY_UP,
+	WIIMOD_PRO_KEY_DOWN,
+	WIIMOD_PRO_KEY_TL,
+	WIIMOD_PRO_KEY_TR,
+	WIIMOD_PRO_KEY_ZL,
+	WIIMOD_PRO_KEY_ZR,
+	WIIMOD_PRO_KEY_THUMBL,
+	WIIMOD_PRO_KEY_THUMBR,
+	WIIMOD_PRO_KEY_NUM,
+};
+
+static const __u16 wiimod_pro_map[] = {
+	BTN_A,		/* WIIMOD_PRO_KEY_A */
+	BTN_B,		/* WIIMOD_PRO_KEY_B */
+	BTN_X,		/* WIIMOD_PRO_KEY_X */
+	BTN_Y,		/* WIIMOD_PRO_KEY_Y */
+	BTN_START,	/* WIIMOD_PRO_KEY_PLUS */
+	BTN_SELECT,	/* WIIMOD_PRO_KEY_MINUS */
+	BTN_MODE,	/* WIIMOD_PRO_KEY_HOME */
+	KEY_LEFT,	/* WIIMOD_PRO_KEY_LEFT */
+	KEY_RIGHT,	/* WIIMOD_PRO_KEY_RIGHT */
+	KEY_UP,		/* WIIMOD_PRO_KEY_UP */
+	KEY_DOWN,	/* WIIMOD_PRO_KEY_DOWN */
+	BTN_TL,		/* WIIMOD_PRO_KEY_TL */
+	BTN_TR,		/* WIIMOD_PRO_KEY_TR */
+	BTN_TL2,	/* WIIMOD_PRO_KEY_ZL */
+	BTN_TR2,	/* WIIMOD_PRO_KEY_ZR */
+	BTN_THUMBL,	/* WIIMOD_PRO_KEY_THUMBL */
+	BTN_THUMBR,	/* WIIMOD_PRO_KEY_THUMBR */
+};
+
+static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+	__s16 rx, ry, lx, ly;
+
+	/*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+	 *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+	 *    1   |                   LX <7:0>                    |
+	 *   -----+-----------------------+-----------------------+
+	 *    2   |  0     0     0     0  |       LX <11:8>       |
+	 *   -----+-----------------------+-----------------------+
+	 *    3   |                   RX <7:0>                    |
+	 *   -----+-----------------------+-----------------------+
+	 *    4   |  0     0     0     0  |       RX <11:8>       |
+	 *   -----+-----------------------+-----------------------+
+	 *    5   |                   LY <7:0>                    |
+	 *   -----+-----------------------+-----------------------+
+	 *    6   |  0     0     0     0  |       LY <11:8>       |
+	 *   -----+-----------------------+-----------------------+
+	 *    7   |                   RY <7:0>                    |
+	 *   -----+-----------------------+-----------------------+
+	 *    8   |  0     0     0     0  |       RY <11:8>       |
+	 *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+	 *    9   | BDR | BDD | BLT | B-  | BH  | B+  | BRT |  1  |
+	 *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+	 *   10   | BZL | BB  | BY  | BA  | BX  | BZR | BDL | BDU |
+	 *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+	 *   11   |  1  |     BATTERY     | USB |CHARG|LTHUM|RTHUM|
+	 *   -----+-----+-----------------+-----------+-----+-----+
+	 * All buttons are low-active (0 if pressed)
+	 * RX and RY are right analog stick
+	 * LX and LY are left analog stick
+	 * BLT is left trigger, BRT is right trigger.
+	 * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons
+	 * BZL is left Z button and BZR is right Z button
+	 * B-, BH, B+ are +, HOME and - buttons
+	 * BB, BY, BA, BX are A, B, X, Y buttons
+	 *
+	 * Bits marked as 0/1 are unknown and never changed during tests.
+	 *
+	 * Not entirely verified:
+	 *   CHARG: 1 if uncharging, 0 if charging
+	 *   USB: 1 if not connected, 0 if connected via USB
+	 *   BATTERY: battery capacity from 000 (empty) to 100 (full)
+	 */
+
+	lx = (ext[0] & 0xff) | ((ext[1] & 0x0f) << 8);
+	rx = (ext[2] & 0xff) | ((ext[3] & 0x0f) << 8);
+	ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8);
+	ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8);
+
+	input_report_abs(wdata->extension.input, ABS_HAT0X, lx - 0x800);
+	input_report_abs(wdata->extension.input, ABS_HAT0Y, ly - 0x800);
+	input_report_abs(wdata->extension.input, ABS_HAT1X, rx - 0x800);
+	input_report_abs(wdata->extension.input, ABS_HAT1Y, ry - 0x800);
+
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT],
+			 !(ext[8] & 0x80));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_DOWN],
+			 !(ext[8] & 0x40));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_TL],
+			 !(ext[8] & 0x20));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_MINUS],
+			 !(ext[8] & 0x10));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_HOME],
+			 !(ext[8] & 0x08));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_PLUS],
+			 !(ext[8] & 0x04));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_TR],
+			 !(ext[8] & 0x02));
+
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_ZL],
+			 !(ext[9] & 0x80));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_B],
+			 !(ext[9] & 0x40));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_Y],
+			 !(ext[9] & 0x20));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_A],
+			 !(ext[9] & 0x10));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_X],
+			 !(ext[9] & 0x08));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_ZR],
+			 !(ext[9] & 0x04));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_LEFT],
+			 !(ext[9] & 0x02));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_UP],
+			 !(ext[9] & 0x01));
+
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_THUMBL],
+			 !(ext[10] & 0x02));
+	input_report_key(wdata->extension.input,
+			 wiimod_pro_map[WIIMOD_PRO_KEY_THUMBR],
+			 !(ext[10] & 0x01));
+
+	input_sync(wdata->extension.input);
+}
+
+static int wiimod_pro_open(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	return 0;
+}
+
+static void wiimod_pro_close(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_pro_play(struct input_dev *dev, void *data,
+			   struct ff_effect *eff)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	__u8 value;
+	unsigned long flags;
+
+	/*
+	 * The wiimote supports only a single rumble motor so if any magnitude
+	 * is set to non-zero then we start the rumble motor. If both are set to
+	 * zero, we stop the rumble motor.
+	 */
+
+	if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
+		value = 1;
+	else
+		value = 0;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_rumble(wdata, value);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	return 0;
+}
+
+static int wiimod_pro_probe(const struct wiimod_ops *ops,
+			    struct wiimote_data *wdata)
+{
+	int ret, i;
+
+	wdata->extension.input = input_allocate_device();
+	if (!wdata->extension.input)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, wdata->extension.input->ffbit);
+	input_set_drvdata(wdata->extension.input, wdata);
+
+	if (input_ff_create_memless(wdata->extension.input, NULL,
+				    wiimod_pro_play)) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	wdata->extension.input->open = wiimod_pro_open;
+	wdata->extension.input->close = wiimod_pro_close;
+	wdata->extension.input->dev.parent = &wdata->hdev->dev;
+	wdata->extension.input->id.bustype = wdata->hdev->bus;
+	wdata->extension.input->id.vendor = wdata->hdev->vendor;
+	wdata->extension.input->id.product = wdata->hdev->product;
+	wdata->extension.input->id.version = wdata->hdev->version;
+	wdata->extension.input->name = WIIMOTE_NAME " Pro Controller";
+
+	set_bit(EV_KEY, wdata->extension.input->evbit);
+	for (i = 0; i < WIIMOD_PRO_KEY_NUM; ++i)
+		set_bit(wiimod_pro_map[i],
+			wdata->extension.input->keybit);
+
+	set_bit(EV_ABS, wdata->extension.input->evbit);
+	set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+	set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
+	set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+	set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
+	input_set_abs_params(wdata->extension.input,
+			     ABS_HAT0X, -0x800, 0x800, 2, 4);
+	input_set_abs_params(wdata->extension.input,
+			     ABS_HAT0Y, -0x800, 0x800, 2, 4);
+	input_set_abs_params(wdata->extension.input,
+			     ABS_HAT1X, -0x800, 0x800, 2, 4);
+	input_set_abs_params(wdata->extension.input,
+			     ABS_HAT1Y, -0x800, 0x800, 2, 4);
+
+	ret = input_register_device(wdata->extension.input);
+	if (ret)
+		goto err_free;
+
+	return 0;
+
+err_free:
+	input_free_device(wdata->extension.input);
+	wdata->extension.input = NULL;
+	return ret;
+}
+
+static void wiimod_pro_remove(const struct wiimod_ops *ops,
+			      struct wiimote_data *wdata)
+{
+	unsigned long flags;
+
+	if (!wdata->extension.input)
+		return;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_rumble(wdata, 0);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	input_unregister_device(wdata->extension.input);
+	wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_pro = {
+	.flags = WIIMOD_FLAG_EXT16,
+	.arg = 0,
+	.probe = wiimod_pro_probe,
+	.remove = wiimod_pro_remove,
+	.in_ext = wiimod_pro_in_ext,
+};
+
+/*
  * Builtin Motion Plus
  * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
  * disables polling for Motion-Plus. This should be set only for devices which
@@ -1788,4 +2082,5 @@  const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
 	[WIIMOTE_EXT_NUNCHUK] = &wiimod_nunchuk,
 	[WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
 	[WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
+	[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
 };
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 5cf8bcb..f1474f3 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -77,6 +77,7 @@  enum wiimote_devtype {
 	WIIMOTE_DEV_GEN10,
 	WIIMOTE_DEV_GEN20,
 	WIIMOTE_DEV_BALANCE_BOARD,
+	WIIMOTE_DEV_PRO_CONTROLLER,
 	WIIMOTE_DEV_NUM,
 };
 
@@ -86,6 +87,7 @@  enum wiimote_exttype {
 	WIIMOTE_EXT_NUNCHUK,
 	WIIMOTE_EXT_CLASSIC_CONTROLLER,
 	WIIMOTE_EXT_BALANCE_BOARD,
+	WIIMOTE_EXT_PRO_CONTROLLER,
 	WIIMOTE_EXT_NUM,
 };