[v3] HID: Wiimote: Treat the d-pad as an analogue stick
diff mbox series

Message ID CANFaMLHQwNf3GnPYAxR-ryrYmO-wVmsEHijzVHEYozUt0EzDJw@mail.gmail.com
State New
Delegated to: Jiri Kosina
Headers show
Series
  • [v3] HID: Wiimote: Treat the d-pad as an analogue stick
Related show

Commit Message

Daniel Morse May 30, 2020, 3:04 p.m. UTC
The controllers from the Super Nintendo Classic Edition (AKA the SNES
Mini) appear as a Classic Controller Pro when connected to a Wii
Remote. All the buttons work as the same, with the d-pad being mapped
the same as the d-pad on the Classic Controller Pro. This differs from
the behaviour of most controllers with d-pads and no analogue sticks,
where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
for up and down. This patch adds an option to the hid-wiimote module
to make the Super Nintendo Classic Controller behave this way.

The patch has been tested with a Super Nintendo Classic Controller
plugged into a Wii Remote in both with the option both enabled and
disabled. When enabled the d-pad acts as the analogue control, and
when disabled it acts as it did before the patch was applied. This
patch has not been tested with e Wii Classic Controller (either the
original or the pro version) as I do not have one of these
controllers.

Although I have not tested it with these controllers, I think it is
likely this patch will also work with the NES Classic Edition
Controllers.

Changes from V1 to V2
* 3 if statements to control the behaviour, one to make the d-pad
register as button presses when the behaviour is disabled, and 2 to
make it act as an analog stick when enabled (once for each of the
motion plus states)
* the values for lx and ly are calculated and then passed to
input_report_abs() in one place, rather then calling
input_report_abs() from different places depending on how the values
are determined.
* using an array to map from button presses to analog value.
* reduced the values used to indicate the position of the analog stick

Changes from V3 to V3
* Moved the definition of dpad_as_analog in hid-wiimote.h
* Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
* changed digital_to_analog from an __s8 to static const s8
* Removed the unnecessary braces when getting values from digital_to_analog

Note: I have also attached a patch file to this final version in
addition to the code in the body because gmail web client keeps
turning the tabs into spaces.

Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>

From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
From: Speedfox <speedfox@speedfox.co.uk>
Date: Tue, 26 May 2020 02:55:50 +0100
Subject: [PATCH] Added option to make d-pad analog

Updates from code review
---
 drivers/hid/hid-wiimote-core.c    |  5 +++
 drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++-----------
 drivers/hid/hid-wiimote.h         |  2 +
 3 files changed, 50 insertions(+), 24 deletions(-)

Comments

David Rheinsberg June 1, 2020, 7:27 a.m. UTC | #1
Hi

On Sat, 30 May 2020 at 17:04, Daniel Morse <dmorse@speedfox.co.uk> wrote:
>
> The controllers from the Super Nintendo Classic Edition (AKA the SNES
> Mini) appear as a Classic Controller Pro when connected to a Wii
> Remote. All the buttons work as the same, with the d-pad being mapped
> the same as the d-pad on the Classic Controller Pro. This differs from
> the behaviour of most controllers with d-pads and no analogue sticks,
> where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
> for up and down. This patch adds an option to the hid-wiimote module
> to make the Super Nintendo Classic Controller behave this way.
>
> The patch has been tested with a Super Nintendo Classic Controller
> plugged into a Wii Remote in both with the option both enabled and
> disabled. When enabled the d-pad acts as the analogue control, and
> when disabled it acts as it did before the patch was applied. This
> patch has not been tested with e Wii Classic Controller (either the
> original or the pro version) as I do not have one of these
> controllers.
>
> Although I have not tested it with these controllers, I think it is
> likely this patch will also work with the NES Classic Edition
> Controllers.
>
> Changes from V1 to V2
> * 3 if statements to control the behaviour, one to make the d-pad
> register as button presses when the behaviour is disabled, and 2 to
> make it act as an analog stick when enabled (once for each of the
> motion plus states)
> * the values for lx and ly are calculated and then passed to
> input_report_abs() in one place, rather then calling
> input_report_abs() from different places depending on how the values
> are determined.
> * using an array to map from button presses to analog value.
> * reduced the values used to indicate the position of the analog stick
>
> Changes from V3 to V3
> * Moved the definition of dpad_as_analog in hid-wiimote.h
> * Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
> * changed digital_to_analog from an __s8 to static const s8
> * Removed the unnecessary braces when getting values from digital_to_analog
>
> Note: I have also attached a patch file to this final version in
> addition to the code in the body because gmail web client keeps
> turning the tabs into spaces.
>
> Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
> Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>
>
> From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
> From: Speedfox <speedfox@speedfox.co.uk>
> Date: Tue, 26 May 2020 02:55:50 +0100
> Subject: [PATCH] Added option to make d-pad analog
>
> Updates from code review
> ---

You can put comments below these 3 dashes^^. There seems to be some
email-header in the commit message above, and the changes between
versions can also be put outside of the commit message. Some
subsystems keep it in the commit-message, though. Maybe Jiri can strip
that when applying? The `Signed-off-by`-etc lines are usually last in
the commit-message. I don't mind either way.

Anyway, thanks for the patch, looks all good!
David
Daniel Morse June 1, 2020, 9:46 a.m. UTC | #2
On Mon, 1 Jun 2020 at 08:27, David Rheinsberg
<david.rheinsberg@gmail.com> wrote:
>
> Hi
>
> On Sat, 30 May 2020 at 17:04, Daniel Morse <dmorse@speedfox.co.uk> wrote:
> >
> > The controllers from the Super Nintendo Classic Edition (AKA the SNES
> > Mini) appear as a Classic Controller Pro when connected to a Wii
> > Remote. All the buttons work as the same, with the d-pad being mapped
> > the same as the d-pad on the Classic Controller Pro. This differs from
> > the behaviour of most controllers with d-pads and no analogue sticks,
> > where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
> > for up and down. This patch adds an option to the hid-wiimote module
> > to make the Super Nintendo Classic Controller behave this way.
> >
> > The patch has been tested with a Super Nintendo Classic Controller
> > plugged into a Wii Remote in both with the option both enabled and
> > disabled. When enabled the d-pad acts as the analogue control, and
> > when disabled it acts as it did before the patch was applied. This
> > patch has not been tested with e Wii Classic Controller (either the
> > original or the pro version) as I do not have one of these
> > controllers.
> >
> > Although I have not tested it with these controllers, I think it is
> > likely this patch will also work with the NES Classic Edition
> > Controllers.
> >
> > Changes from V1 to V2
> > * 3 if statements to control the behaviour, one to make the d-pad
> > register as button presses when the behaviour is disabled, and 2 to
> > make it act as an analog stick when enabled (once for each of the
> > motion plus states)
> > * the values for lx and ly are calculated and then passed to
> > input_report_abs() in one place, rather then calling
> > input_report_abs() from different places depending on how the values
> > are determined.
> > * using an array to map from button presses to analog value.
> > * reduced the values used to indicate the position of the analog stick
> >
> > Changes from V3 to V3
> > * Moved the definition of dpad_as_analog in hid-wiimote.h
> > * Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
> > * changed digital_to_analog from an __s8 to static const s8
> > * Removed the unnecessary braces when getting values from digital_to_analog
> >
> > Note: I have also attached a patch file to this final version in
> > addition to the code in the body because gmail web client keeps
> > turning the tabs into spaces.
> >
> > Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
> > Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>
> >
> > From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
> > From: Speedfox <speedfox@speedfox.co.uk>
> > Date: Tue, 26 May 2020 02:55:50 +0100
> > Subject: [PATCH] Added option to make d-pad analog
> >
> > Updates from code review
> > ---
>
> You can put comments below these 3 dashes^^. There seems to be some
> email-header in the commit message above, and the changes between
> versions can also be put outside of the commit message. Some
> subsystems keep it in the commit-message, though. Maybe Jiri can strip
> that when applying? The `Signed-off-by`-etc lines are usually last in
> the commit-message. I don't mind either way.

Since it's probably best that Jiri applies the patch from the
attachment which I included to get around gmail's inability to use
tabs, I think it'll be easiest to let him strip out that superfluous
email header when he does that rather than me sending another version
of the patch.

>
> Anyway, thanks for the patch, looks all good!
> David


Thanks again for reviewing my patch.

--Daniel
Daniel Morse June 9, 2020, 9:16 a.m. UTC | #3
Just wanted to check in and see if there was anything else I needed to
do to this patch before it gets merged?

--Daniel

On Mon, 1 Jun 2020 at 10:46, Daniel Morse <dmorse@speedfox.co.uk> wrote:
>
> On Mon, 1 Jun 2020 at 08:27, David Rheinsberg
> <david.rheinsberg@gmail.com> wrote:
> >
> > Hi
> >
> > On Sat, 30 May 2020 at 17:04, Daniel Morse <dmorse@speedfox.co.uk> wrote:
> > >
> > > The controllers from the Super Nintendo Classic Edition (AKA the SNES
> > > Mini) appear as a Classic Controller Pro when connected to a Wii
> > > Remote. All the buttons work as the same, with the d-pad being mapped
> > > the same as the d-pad on the Classic Controller Pro. This differs from
> > > the behaviour of most controllers with d-pads and no analogue sticks,
> > > where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
> > > for up and down. This patch adds an option to the hid-wiimote module
> > > to make the Super Nintendo Classic Controller behave this way.
> > >
> > > The patch has been tested with a Super Nintendo Classic Controller
> > > plugged into a Wii Remote in both with the option both enabled and
> > > disabled. When enabled the d-pad acts as the analogue control, and
> > > when disabled it acts as it did before the patch was applied. This
> > > patch has not been tested with e Wii Classic Controller (either the
> > > original or the pro version) as I do not have one of these
> > > controllers.
> > >
> > > Although I have not tested it with these controllers, I think it is
> > > likely this patch will also work with the NES Classic Edition
> > > Controllers.
> > >
> > > Changes from V1 to V2
> > > * 3 if statements to control the behaviour, one to make the d-pad
> > > register as button presses when the behaviour is disabled, and 2 to
> > > make it act as an analog stick when enabled (once for each of the
> > > motion plus states)
> > > * the values for lx and ly are calculated and then passed to
> > > input_report_abs() in one place, rather then calling
> > > input_report_abs() from different places depending on how the values
> > > are determined.
> > > * using an array to map from button presses to analog value.
> > > * reduced the values used to indicate the position of the analog stick
> > >
> > > Changes from V3 to V3
> > > * Moved the definition of dpad_as_analog in hid-wiimote.h
> > > * Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
> > > * changed digital_to_analog from an __s8 to static const s8
> > > * Removed the unnecessary braces when getting values from digital_to_analog
> > >
> > > Note: I have also attached a patch file to this final version in
> > > addition to the code in the body because gmail web client keeps
> > > turning the tabs into spaces.
> > >
> > > Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
> > > Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>
> > >
> > > From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
> > > From: Speedfox <speedfox@speedfox.co.uk>
> > > Date: Tue, 26 May 2020 02:55:50 +0100
> > > Subject: [PATCH] Added option to make d-pad analog
> > >
> > > Updates from code review
> > > ---
> >
> > You can put comments below these 3 dashes^^. There seems to be some
> > email-header in the commit message above, and the changes between
> > versions can also be put outside of the commit message. Some
> > subsystems keep it in the commit-message, though. Maybe Jiri can strip
> > that when applying? The `Signed-off-by`-etc lines are usually last in
> > the commit-message. I don't mind either way.
>
> Since it's probably best that Jiri applies the patch from the
> attachment which I included to get around gmail's inability to use
> tabs, I think it'll be easiest to let him strip out that superfluous
> email header when he does that rather than me sending another version
> of the patch.
>
> >
> > Anyway, thanks for the patch, looks all good!
> > David
>
>
> Thanks again for reviewing my patch.
>
> --Daniel
David Rheinsberg June 9, 2020, 1:09 p.m. UTC | #4
On Tue, 9 Jun 2020 at 11:16, Daniel Morse <daniel.morse@gmail.com> wrote:
>
> Just wanted to check in and see if there was anything else I needed to
> do to this patch before it gets merged?

There shouldn't be. But sometimes it takes a while for non-critical
patches to be picked up. I will add Benjamin as well, maybe he is
around and can apply patches.

Thanks
David
Jiri Kosina June 19, 2020, 7:25 a.m. UTC | #5
CCing David Hermann in case he has any review comments to this.

Thanks.

On Sat, 30 May 2020, Daniel Morse wrote:

> The controllers from the Super Nintendo Classic Edition (AKA the SNES
> Mini) appear as a Classic Controller Pro when connected to a Wii
> Remote. All the buttons work as the same, with the d-pad being mapped
> the same as the d-pad on the Classic Controller Pro. This differs from
> the behaviour of most controllers with d-pads and no analogue sticks,
> where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
> for up and down. This patch adds an option to the hid-wiimote module
> to make the Super Nintendo Classic Controller behave this way.
> 
> The patch has been tested with a Super Nintendo Classic Controller
> plugged into a Wii Remote in both with the option both enabled and
> disabled. When enabled the d-pad acts as the analogue control, and
> when disabled it acts as it did before the patch was applied. This
> patch has not been tested with e Wii Classic Controller (either the
> original or the pro version) as I do not have one of these
> controllers.
> 
> Although I have not tested it with these controllers, I think it is
> likely this patch will also work with the NES Classic Edition
> Controllers.
> 
> Changes from V1 to V2
> * 3 if statements to control the behaviour, one to make the d-pad
> register as button presses when the behaviour is disabled, and 2 to
> make it act as an analog stick when enabled (once for each of the
> motion plus states)
> * the values for lx and ly are calculated and then passed to
> input_report_abs() in one place, rather then calling
> input_report_abs() from different places depending on how the values
> are determined.
> * using an array to map from button presses to analog value.
> * reduced the values used to indicate the position of the analog stick
> 
> Changes from V3 to V3
> * Moved the definition of dpad_as_analog in hid-wiimote.h
> * Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
> * changed digital_to_analog from an __s8 to static const s8
> * Removed the unnecessary braces when getting values from digital_to_analog
> 
> Note: I have also attached a patch file to this final version in
> addition to the code in the body because gmail web client keeps
> turning the tabs into spaces.
> 
> Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
> Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>
> 
> >From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
> From: Speedfox <speedfox@speedfox.co.uk>
> Date: Tue, 26 May 2020 02:55:50 +0100
> Subject: [PATCH] Added option to make d-pad analog
> 
> Updates from code review
> ---
>  drivers/hid/hid-wiimote-core.c    |  5 +++
>  drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++-----------
>  drivers/hid/hid-wiimote.h         |  2 +
>  3 files changed, 50 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
> index 92874dbe4d4a..679e142fc850 100644
> --- a/drivers/hid/hid-wiimote-core.c
> +++ b/drivers/hid/hid-wiimote-core.c
> @@ -1870,6 +1870,11 @@ static const struct hid_device_id
> wiimote_hid_devices[] = {
>                  USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
>      { }
>  };
> +
> +bool wiimote_dpad_as_analog = false;
> +module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644);
> +MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input");
> +
>  MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
> 
>  static struct hid_driver wiimote_hid_driver = {
> diff --git a/drivers/hid/hid-wiimote-modules.c
> b/drivers/hid/hid-wiimote-modules.c
> index 2c3925357857..213c58bf2495 100644
> --- a/drivers/hid/hid-wiimote-modules.c
> +++ b/drivers/hid/hid-wiimote-modules.c
> @@ -1088,12 +1088,28 @@ static void wiimod_classic_in_ext(struct
> wiimote_data *wdata, const __u8 *ext)
>       * is the same as before.
>       */
> 
> +    static const s8 digital_to_analog[3] = {0x20, 0, -0x20};
> +
>      if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> -        lx = ext[0] & 0x3e;
> -        ly = ext[1] & 0x3e;
> +        if (wiimote_dpad_as_analog) {
> +            lx = digital_to_analog[1 - !(ext[4] & 0x80)
> +                + !(ext[1] & 0x01)];
> +            ly = digital_to_analog[1 - !(ext[4] & 0x40)
> +                + !(ext[0] & 0x01)];
> +        } else {
> +            lx = (ext[0] & 0x3e) - 0x20;
> +            ly = (ext[1] & 0x3e) - 0x20;
> +        }
>      } else {
> -        lx = ext[0] & 0x3f;
> -        ly = ext[1] & 0x3f;
> +        if (wiimote_dpad_as_analog) {
> +            lx = digital_to_analog[1 - !(ext[4] & 0x80)
> +                + !(ext[5] & 0x02)];
> +            ly = digital_to_analog[1 - !(ext[4] & 0x40)
> +                + !(ext[5] & 0x01)];
> +        } else {
> +            lx = (ext[0] & 0x3f) - 0x20;
> +            ly = (ext[1] & 0x3f) - 0x20;
> +        }
>      }
> 
>      rx = (ext[0] >> 3) & 0x18;
> @@ -1110,19 +1126,13 @@ static void wiimod_classic_in_ext(struct
> wiimote_data *wdata, const __u8 *ext)
>      rt <<= 1;
>      lt <<= 1;
> 
> -    input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
> -    input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
> +    input_report_abs(wdata->extension.input, ABS_HAT1X, lx);
> +    input_report_abs(wdata->extension.input, ABS_HAT1Y, ly);
>      input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
>      input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
>      input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
>      input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
> 
> -    input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
> -             !(ext[4] & 0x80));
> -    input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
> -             !(ext[4] & 0x40));
>      input_report_key(wdata->extension.input,
>               wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
>               !(ext[4] & 0x20));
> @@ -1157,20 +1167,29 @@ static void wiimod_classic_in_ext(struct
> wiimote_data *wdata, const __u8 *ext)
>               wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
>               !(ext[5] & 0x04));
> 
> -    if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> -        input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> -             !(ext[1] & 0x01));
> -        input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> -             !(ext[0] & 0x01));
> -    } else {
> +    if (!wiimote_dpad_as_analog) {
>          input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> -             !(ext[5] & 0x02));
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
> +                 !(ext[4] & 0x80));
>          input_report_key(wdata->extension.input,
> -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> -             !(ext[5] & 0x01));
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
> +                 !(ext[4] & 0x40));
> +
> +        if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> +            input_report_key(wdata->extension.input,
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> +                 !(ext[1] & 0x01));
> +            input_report_key(wdata->extension.input,
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> +                 !(ext[0] & 0x01));
> +        } else {
> +            input_report_key(wdata->extension.input,
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> +                 !(ext[5] & 0x02));
> +            input_report_key(wdata->extension.input,
> +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> +                 !(ext[5] & 0x01));
> +        }
>      }
> 
>      input_sync(wdata->extension.input);
> diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
> index b2a26a0a8f12..ad4ff837f43e 100644
> --- a/drivers/hid/hid-wiimote.h
> +++ b/drivers/hid/hid-wiimote.h
> @@ -162,6 +162,8 @@ struct wiimote_data {
>      struct work_struct init_worker;
>  };
> 
> +extern bool wiimote_dpad_as_analog;
> +
>  /* wiimote modules */
> 
>  enum wiimod_module {
> -- 
> 2.25.1
>
David Herrmann June 19, 2020, 11:35 a.m. UTC | #6
Hi

On Fri, Jun 19, 2020 at 9:25 AM Jiri Kosina <jikos@kernel.org> wrote:
>
>
> CCing David Hermann in case he has any review comments to this.
>
> Thanks.

Yes, all good!

Reviewed-by: David Herrmann <dh.herrmann@gmail.com>

(You want me to send an adjustment for `MAINTAINERS` to link to my new
email-address/name? Got married some time ago already, but forgot to
adjust the `MAINTAINERS` file.)

Thanks
David

> On Sat, 30 May 2020, Daniel Morse wrote:
>
> > The controllers from the Super Nintendo Classic Edition (AKA the SNES
> > Mini) appear as a Classic Controller Pro when connected to a Wii
> > Remote. All the buttons work as the same, with the d-pad being mapped
> > the same as the d-pad on the Classic Controller Pro. This differs from
> > the behaviour of most controllers with d-pads and no analogue sticks,
> > where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y
> > for up and down. This patch adds an option to the hid-wiimote module
> > to make the Super Nintendo Classic Controller behave this way.
> >
> > The patch has been tested with a Super Nintendo Classic Controller
> > plugged into a Wii Remote in both with the option both enabled and
> > disabled. When enabled the d-pad acts as the analogue control, and
> > when disabled it acts as it did before the patch was applied. This
> > patch has not been tested with e Wii Classic Controller (either the
> > original or the pro version) as I do not have one of these
> > controllers.
> >
> > Although I have not tested it with these controllers, I think it is
> > likely this patch will also work with the NES Classic Edition
> > Controllers.
> >
> > Changes from V1 to V2
> > * 3 if statements to control the behaviour, one to make the d-pad
> > register as button presses when the behaviour is disabled, and 2 to
> > make it act as an analog stick when enabled (once for each of the
> > motion plus states)
> > * the values for lx and ly are calculated and then passed to
> > input_report_abs() in one place, rather then calling
> > input_report_abs() from different places depending on how the values
> > are determined.
> > * using an array to map from button presses to analog value.
> > * reduced the values used to indicate the position of the analog stick
> >
> > Changes from V3 to V3
> > * Moved the definition of dpad_as_analog in hid-wiimote.h
> > * Renamed the dpad_as_analog vaiable to wiimote_dpad_as_analog
> > * changed digital_to_analog from an __s8 to static const s8
> > * Removed the unnecessary braces when getting values from digital_to_analog
> >
> > Note: I have also attached a patch file to this final version in
> > addition to the code in the body because gmail web client keeps
> > turning the tabs into spaces.
> >
> > Signed-off-by: Daniel G. Morse <dmorse@speedfox.co.uk>
> > Reviewed-by: David Rheinsberg <david.rheinsberg@gmail.com>
> >
> > >From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
> > From: Speedfox <speedfox@speedfox.co.uk>
> > Date: Tue, 26 May 2020 02:55:50 +0100
> > Subject: [PATCH] Added option to make d-pad analog
> >
> > Updates from code review
> > ---
> >  drivers/hid/hid-wiimote-core.c    |  5 +++
> >  drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++-----------
> >  drivers/hid/hid-wiimote.h         |  2 +
> >  3 files changed, 50 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
> > index 92874dbe4d4a..679e142fc850 100644
> > --- a/drivers/hid/hid-wiimote-core.c
> > +++ b/drivers/hid/hid-wiimote-core.c
> > @@ -1870,6 +1870,11 @@ static const struct hid_device_id
> > wiimote_hid_devices[] = {
> >                  USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
> >      { }
> >  };
> > +
> > +bool wiimote_dpad_as_analog = false;
> > +module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644);
> > +MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input");
> > +
> >  MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
> >
> >  static struct hid_driver wiimote_hid_driver = {
> > diff --git a/drivers/hid/hid-wiimote-modules.c
> > b/drivers/hid/hid-wiimote-modules.c
> > index 2c3925357857..213c58bf2495 100644
> > --- a/drivers/hid/hid-wiimote-modules.c
> > +++ b/drivers/hid/hid-wiimote-modules.c
> > @@ -1088,12 +1088,28 @@ static void wiimod_classic_in_ext(struct
> > wiimote_data *wdata, const __u8 *ext)
> >       * is the same as before.
> >       */
> >
> > +    static const s8 digital_to_analog[3] = {0x20, 0, -0x20};
> > +
> >      if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> > -        lx = ext[0] & 0x3e;
> > -        ly = ext[1] & 0x3e;
> > +        if (wiimote_dpad_as_analog) {
> > +            lx = digital_to_analog[1 - !(ext[4] & 0x80)
> > +                + !(ext[1] & 0x01)];
> > +            ly = digital_to_analog[1 - !(ext[4] & 0x40)
> > +                + !(ext[0] & 0x01)];
> > +        } else {
> > +            lx = (ext[0] & 0x3e) - 0x20;
> > +            ly = (ext[1] & 0x3e) - 0x20;
> > +        }
> >      } else {
> > -        lx = ext[0] & 0x3f;
> > -        ly = ext[1] & 0x3f;
> > +        if (wiimote_dpad_as_analog) {
> > +            lx = digital_to_analog[1 - !(ext[4] & 0x80)
> > +                + !(ext[5] & 0x02)];
> > +            ly = digital_to_analog[1 - !(ext[4] & 0x40)
> > +                + !(ext[5] & 0x01)];
> > +        } else {
> > +            lx = (ext[0] & 0x3f) - 0x20;
> > +            ly = (ext[1] & 0x3f) - 0x20;
> > +        }
> >      }
> >
> >      rx = (ext[0] >> 3) & 0x18;
> > @@ -1110,19 +1126,13 @@ static void wiimod_classic_in_ext(struct
> > wiimote_data *wdata, const __u8 *ext)
> >      rt <<= 1;
> >      lt <<= 1;
> >
> > -    input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
> > -    input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
> > +    input_report_abs(wdata->extension.input, ABS_HAT1X, lx);
> > +    input_report_abs(wdata->extension.input, ABS_HAT1Y, ly);
> >      input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
> >      input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
> >      input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
> >      input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
> >
> > -    input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
> > -             !(ext[4] & 0x80));
> > -    input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
> > -             !(ext[4] & 0x40));
> >      input_report_key(wdata->extension.input,
> >               wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
> >               !(ext[4] & 0x20));
> > @@ -1157,20 +1167,29 @@ static void wiimod_classic_in_ext(struct
> > wiimote_data *wdata, const __u8 *ext)
> >               wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
> >               !(ext[5] & 0x04));
> >
> > -    if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> > -        input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> > -             !(ext[1] & 0x01));
> > -        input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> > -             !(ext[0] & 0x01));
> > -    } else {
> > +    if (!wiimote_dpad_as_analog) {
> >          input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> > -             !(ext[5] & 0x02));
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
> > +                 !(ext[4] & 0x80));
> >          input_report_key(wdata->extension.input,
> > -             wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> > -             !(ext[5] & 0x01));
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
> > +                 !(ext[4] & 0x40));
> > +
> > +        if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
> > +            input_report_key(wdata->extension.input,
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> > +                 !(ext[1] & 0x01));
> > +            input_report_key(wdata->extension.input,
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> > +                 !(ext[0] & 0x01));
> > +        } else {
> > +            input_report_key(wdata->extension.input,
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
> > +                 !(ext[5] & 0x02));
> > +            input_report_key(wdata->extension.input,
> > +                 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
> > +                 !(ext[5] & 0x01));
> > +        }
> >      }
> >
> >      input_sync(wdata->extension.input);
> > diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
> > index b2a26a0a8f12..ad4ff837f43e 100644
> > --- a/drivers/hid/hid-wiimote.h
> > +++ b/drivers/hid/hid-wiimote.h
> > @@ -162,6 +162,8 @@ struct wiimote_data {
> >      struct work_struct init_worker;
> >  };
> >
> > +extern bool wiimote_dpad_as_analog;
> > +
> >  /* wiimote modules */
> >
> >  enum wiimod_module {
> > --
> > 2.25.1
> >
>
> --
> Jiri Kosina
> SUSE Labs
>
Jiri Kosina June 19, 2020, 11:41 a.m. UTC | #7
On Fri, 19 Jun 2020, David Herrmann wrote:

> > CCing David Hermann in case he has any review comments to this.
> >
> > Thanks.
> 
> Yes, all good!
> 
> Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
> 
> (You want me to send an adjustment for `MAINTAINERS` to link to my new
> email-address/name? Got married some time ago already, but forgot to
> adjust the `MAINTAINERS` file.)

Ah, I wasn't aware that the two of you are the same person :-) Yes, if you 
could do that, it'd be helpful.

Also, Daniel, the patch is unfortunately still whitespace-corrupted and 
line-wrapper, so I can't apply it. Could you please fix that up and 
resend?

Thanks,
Daniel Morse June 19, 2020, 11:44 a.m. UTC | #8
Does that apply to the version I attached as well as the version in
the body of the email? There isn't much I can do about the version in
the body of the email as I'm on gmail.


On Fri, 19 Jun 2020 at 12:41, Jiri Kosina <jikos@kernel.org> wrote:
>
> On Fri, 19 Jun 2020, David Herrmann wrote:
>
> > > CCing David Hermann in case he has any review comments to this.
> > >
> > > Thanks.
> >
> > Yes, all good!
> >
> > Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
> >
> > (You want me to send an adjustment for `MAINTAINERS` to link to my new
> > email-address/name? Got married some time ago already, but forgot to
> > adjust the `MAINTAINERS` file.)
>
> Ah, I wasn't aware that the two of you are the same person :-) Yes, if you
> could do that, it'd be helpful.
>
> Also, Daniel, the patch is unfortunately still whitespace-corrupted and
> line-wrapper, so I can't apply it. Could you please fix that up and
> resend?
>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs
>
Jiri Kosina June 19, 2020, 12:18 p.m. UTC | #9
On Fri, 19 Jun 2020, Daniel Morse wrote:

> Does that apply to the version I attached as well as the version in
> the body of the email? There isn't much I can do about the version in
> the body of the email as I'm on gmail.

That one is ok when it comes to patch damage, but doesn't have proper 
metadata (changelog, author, etc).

I've fixed that up manually (and applied the patch), but if you could fix 
this for any further submissions, I'd appreciate it :)

Thanks,
Daniel Morse June 19, 2020, 12:53 p.m. UTC | #10
Jiri,

Thanks for fixing that for me. I thought that the patch in the
attachment was OK except for the metadata, but I just wanted to check
before I sent an updated version through.

If I send through any more submissions I'll move to another mail
client so as to avoid gmail mangling the whitespace. I only realised
it was doing that after I had sent the first version through.

--Daniel

On Fri, 19 Jun 2020 at 13:18, Jiri Kosina <jikos@kernel.org> wrote:
>
> On Fri, 19 Jun 2020, Daniel Morse wrote:
>
> > Does that apply to the version I attached as well as the version in
> > the body of the email? There isn't much I can do about the version in
> > the body of the email as I'm on gmail.
>
> That one is ok when it comes to patch damage, but doesn't have proper
> metadata (changelog, author, etc).
>
> I've fixed that up manually (and applied the patch), but if you could fix
> this for any further submissions, I'd appreciate it :)
>
> Thanks,
>
> --
> Jiri Kosina
> SUSE Labs
>

Patch
diff mbox series

From 8909feec10fda919d1ec46c95418d63ac52ee41f Mon Sep 17 00:00:00 2001
From: Speedfox <speedfox@speedfox.co.uk>
Date: Tue, 26 May 2020 02:55:50 +0100
Subject: [PATCH] Added option to make d-pad analog

Updates from code review
---
 drivers/hid/hid-wiimote-core.c    |  5 +++
 drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++-----------
 drivers/hid/hid-wiimote.h         |  2 +
 3 files changed, 50 insertions(+), 24 deletions(-)

diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 92874dbe4d4a..679e142fc850 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -1870,6 +1870,11 @@  static const struct hid_device_id wiimote_hid_devices[] = {
 				USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ }
 };
+
+bool wiimote_dpad_as_analog = false;
+module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644);
+MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input");
+
 MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
 
 static struct hid_driver wiimote_hid_driver = {
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 2c3925357857..213c58bf2495 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1088,12 +1088,28 @@  static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
 	 * is the same as before.
 	 */
 
+	static const s8 digital_to_analog[3] = {0x20, 0, -0x20};
+
 	if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
-		lx = ext[0] & 0x3e;
-		ly = ext[1] & 0x3e;
+		if (wiimote_dpad_as_analog) {
+			lx = digital_to_analog[1 - !(ext[4] & 0x80)
+				+ !(ext[1] & 0x01)];
+			ly = digital_to_analog[1 - !(ext[4] & 0x40)
+				+ !(ext[0] & 0x01)];
+		} else {
+			lx = (ext[0] & 0x3e) - 0x20;
+			ly = (ext[1] & 0x3e) - 0x20;
+		}
 	} else {
-		lx = ext[0] & 0x3f;
-		ly = ext[1] & 0x3f;
+		if (wiimote_dpad_as_analog) {
+			lx = digital_to_analog[1 - !(ext[4] & 0x80)
+				+ !(ext[5] & 0x02)];
+			ly = digital_to_analog[1 - !(ext[4] & 0x40)
+				+ !(ext[5] & 0x01)];
+		} else {
+			lx = (ext[0] & 0x3f) - 0x20;
+			ly = (ext[1] & 0x3f) - 0x20;
+		}
 	}
 
 	rx = (ext[0] >> 3) & 0x18;
@@ -1110,19 +1126,13 @@  static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
 	rt <<= 1;
 	lt <<= 1;
 
-	input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
-	input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
+	input_report_abs(wdata->extension.input, ABS_HAT1X, lx);
+	input_report_abs(wdata->extension.input, ABS_HAT1Y, ly);
 	input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
 	input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
 	input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
 	input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
 
-	input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
-			 !(ext[4] & 0x80));
-	input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
-			 !(ext[4] & 0x40));
 	input_report_key(wdata->extension.input,
 			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
 			 !(ext[4] & 0x20));
@@ -1157,20 +1167,29 @@  static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
 			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
 			 !(ext[5] & 0x04));
 
-	if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
-		input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
-			 !(ext[1] & 0x01));
-		input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
-			 !(ext[0] & 0x01));
-	} else {
+	if (!wiimote_dpad_as_analog) {
 		input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
-			 !(ext[5] & 0x02));
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
+				 !(ext[4] & 0x80));
 		input_report_key(wdata->extension.input,
-			 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
-			 !(ext[5] & 0x01));
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
+				 !(ext[4] & 0x40));
+
+		if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+			input_report_key(wdata->extension.input,
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
+				 !(ext[1] & 0x01));
+			input_report_key(wdata->extension.input,
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
+				 !(ext[0] & 0x01));
+		} else {
+			input_report_key(wdata->extension.input,
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
+				 !(ext[5] & 0x02));
+			input_report_key(wdata->extension.input,
+				 wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
+				 !(ext[5] & 0x01));
+		}
 	}
 
 	input_sync(wdata->extension.input);
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index b2a26a0a8f12..ad4ff837f43e 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -162,6 +162,8 @@  struct wiimote_data {
 	struct work_struct init_worker;
 };
 
+extern bool wiimote_dpad_as_analog;
+
 /* wiimote modules */
 
 enum wiimod_module {
-- 
2.25.1