Skip to content

Commit a8cbf80

Browse files
Daniel G. MorseJiri Kosina
authored andcommitted
HID: Wiimote: Treat the d-pad as an analogue stick
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. Signed-off-by: Daniel G. Morse <[email protected]> Reviewed-by: David Rheinsberg <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent a789d5f commit a8cbf80

File tree

3 files changed

+50
-24
lines changed

3 files changed

+50
-24
lines changed

drivers/hid/hid-wiimote-core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,11 @@ static const struct hid_device_id wiimote_hid_devices[] = {
18701870
USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
18711871
{ }
18721872
};
1873+
1874+
bool wiimote_dpad_as_analog = false;
1875+
module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644);
1876+
MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input");
1877+
18731878
MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
18741879

18751880
static struct hid_driver wiimote_hid_driver = {

drivers/hid/hid-wiimote-modules.c

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,12 +1088,28 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
10881088
* is the same as before.
10891089
*/
10901090

1091+
static const s8 digital_to_analog[3] = {0x20, 0, -0x20};
1092+
10911093
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
1092-
lx = ext[0] & 0x3e;
1093-
ly = ext[1] & 0x3e;
1094+
if (wiimote_dpad_as_analog) {
1095+
lx = digital_to_analog[1 - !(ext[4] & 0x80)
1096+
+ !(ext[1] & 0x01)];
1097+
ly = digital_to_analog[1 - !(ext[4] & 0x40)
1098+
+ !(ext[0] & 0x01)];
1099+
} else {
1100+
lx = (ext[0] & 0x3e) - 0x20;
1101+
ly = (ext[1] & 0x3e) - 0x20;
1102+
}
10941103
} else {
1095-
lx = ext[0] & 0x3f;
1096-
ly = ext[1] & 0x3f;
1104+
if (wiimote_dpad_as_analog) {
1105+
lx = digital_to_analog[1 - !(ext[4] & 0x80)
1106+
+ !(ext[5] & 0x02)];
1107+
ly = digital_to_analog[1 - !(ext[4] & 0x40)
1108+
+ !(ext[5] & 0x01)];
1109+
} else {
1110+
lx = (ext[0] & 0x3f) - 0x20;
1111+
ly = (ext[1] & 0x3f) - 0x20;
1112+
}
10971113
}
10981114

10991115
rx = (ext[0] >> 3) & 0x18;
@@ -1110,19 +1126,13 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
11101126
rt <<= 1;
11111127
lt <<= 1;
11121128

1113-
input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20);
1114-
input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20);
1129+
input_report_abs(wdata->extension.input, ABS_HAT1X, lx);
1130+
input_report_abs(wdata->extension.input, ABS_HAT1Y, ly);
11151131
input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
11161132
input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
11171133
input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
11181134
input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
11191135

1120-
input_report_key(wdata->extension.input,
1121-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
1122-
!(ext[4] & 0x80));
1123-
input_report_key(wdata->extension.input,
1124-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
1125-
!(ext[4] & 0x40));
11261136
input_report_key(wdata->extension.input,
11271137
wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
11281138
!(ext[4] & 0x20));
@@ -1157,20 +1167,29 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
11571167
wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
11581168
!(ext[5] & 0x04));
11591169

1160-
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
1161-
input_report_key(wdata->extension.input,
1162-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1163-
!(ext[1] & 0x01));
1164-
input_report_key(wdata->extension.input,
1165-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1166-
!(ext[0] & 0x01));
1167-
} else {
1170+
if (!wiimote_dpad_as_analog) {
11681171
input_report_key(wdata->extension.input,
1169-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1170-
!(ext[5] & 0x02));
1172+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
1173+
!(ext[4] & 0x80));
11711174
input_report_key(wdata->extension.input,
1172-
wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1173-
!(ext[5] & 0x01));
1175+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
1176+
!(ext[4] & 0x40));
1177+
1178+
if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
1179+
input_report_key(wdata->extension.input,
1180+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1181+
!(ext[1] & 0x01));
1182+
input_report_key(wdata->extension.input,
1183+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1184+
!(ext[0] & 0x01));
1185+
} else {
1186+
input_report_key(wdata->extension.input,
1187+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1188+
!(ext[5] & 0x02));
1189+
input_report_key(wdata->extension.input,
1190+
wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1191+
!(ext[5] & 0x01));
1192+
}
11741193
}
11751194

11761195
input_sync(wdata->extension.input);

drivers/hid/hid-wiimote.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ struct wiimote_data {
162162
struct work_struct init_worker;
163163
};
164164

165+
extern bool wiimote_dpad_as_analog;
166+
165167
/* wiimote modules */
166168

167169
enum wiimod_module {

0 commit comments

Comments
 (0)