summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadia Holmquist Pedersen2023-04-06 00:43:30 +0000
committerNadia Holmquist Pedersen2023-04-06 00:43:30 +0000
commit79b7bc9fc928680fb14507932b5faea2ba034e4b (patch)
tree8286ab9ddde9154d58a3c18be3c3962fa8ff5729
parentffce16e529f8c3cacf1e9084486664509fb32cc9 (diff)
downloadaur-79b7bc9fc928680fb14507932b5faea2ba034e4b.tar.gz
Add support for the Switch N64 controller.
Also fix build for new kernels
-rw-r--r--.SRCINFO11
-rw-r--r--PKGBUILD10
-rw-r--r--dkms.conf4
-rw-r--r--hid-ids.h1
-rw-r--r--hid-nintendo.c132
5 files changed, 112 insertions, 46 deletions
diff --git a/.SRCINFO b/.SRCINFO
index e5377ebea451..67eb09374e34 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = hid-nintendo-nso-dkms
- pkgdesc = HID driver for Nintendo Switch controllers patched with Switch Online NES and SNES controller support.
- pkgver = 1.2
+ pkgdesc = HID driver for Nintendo Switch controllers patched with Switch Online NES, SNES and N64 controller support.
+ pkgver = 20230406
pkgrel = 1
url = https://github.com/nadiaholmquist/linux/tree/hid-nintendo
arch = x86_64
@@ -12,10 +12,9 @@ pkgbase = hid-nintendo-nso-dkms
source = dkms.conf
source = hid-ids.h
source = Makefile
- md5sums = f6592f96d94c215e3de807bd8a80c612
- md5sums = 6d97239c33773b3f2fc5d497e98a1017
- md5sums = 6d1c428af9d73b4fd493ee1d4465700b
+ md5sums = 95aaf1a8aeaee02a8e7ba2c23e74f020
+ md5sums = 54ffcf23a7c3c8e002b58c580d920f87
+ md5sums = 86ce3f841c60b66bf3e0278f8e93659c
md5sums = 3a628988ca479023b45d2bd6b9b1cfb8
pkgname = hid-nintendo-nso-dkms
-
diff --git a/PKGBUILD b/PKGBUILD
index e48f3394d6fe..77ac903bca4f 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,9 +1,9 @@
_pkgbase=hid-nintendo
pkgname=hid-nintendo-nso-dkms
-pkgver=1.2
+pkgver=20230406
pkgrel=1
-pkgdesc="HID driver for Nintendo Switch controllers patched with Switch Online NES and SNES controller support."
+pkgdesc="HID driver for Nintendo Switch controllers patched with Switch Online NES, SNES and N64 controller support."
arch=('x86_64' 'aarch64')
url="https://github.com/nadiaholmquist/linux/tree/hid-nintendo"
license=("GPL2")
@@ -11,9 +11,9 @@ depends=('dkms')
source=('hid-nintendo.c' 'dkms.conf' 'hid-ids.h' 'Makefile')
conflicts=(hid-nintendo-dkms)
-md5sums=('f6592f96d94c215e3de807bd8a80c612'
- '6d97239c33773b3f2fc5d497e98a1017'
- '6d1c428af9d73b4fd493ee1d4465700b'
+md5sums=('95aaf1a8aeaee02a8e7ba2c23e74f020'
+ '54ffcf23a7c3c8e002b58c580d920f87'
+ '86ce3f841c60b66bf3e0278f8e93659c'
'3a628988ca479023b45d2bd6b9b1cfb8')
package() {
diff --git a/dkms.conf b/dkms.conf
index 58dec07cc80a..28d896a3ebe4 100644
--- a/dkms.conf
+++ b/dkms.conf
@@ -1,8 +1,8 @@
PACKAGE_NAME="@_PKGBASE@"
PACKAGE_VERSION="@PKGVER@"
MAKE="make -C $kernel_source_dir M=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/ modules"
-CLEAN="make -C $kernel_source_dir M+$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/ clean"
+CLEAN="make -C $kernel_source_dir M=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/ clean"
BUILT_MODULE_NAME[0]="@_PKGBASE@"
BUILT_MODULE_LOCATION[0]=""
-DEST_MODULE_LOCATION[0]="/kernel/drivers/hid/"
+DEST_MODULE_LOCATION[0]="/updates/dkms/"
AUTOINSTALL="yes"
diff --git a/hid-ids.h b/hid-ids.h
index 484a2f1ff47c..7eb71b5c36e8 100644
--- a/hid-ids.h
+++ b/hid-ids.h
@@ -873,6 +873,7 @@
#define USB_DEVICE_ID_NINTENDO_PROCON 0x2009
#define USB_DEVICE_ID_NINTENDO_CHRGGRIP 0x200E
#define USB_DEVICE_ID_NINTENDO_SNESCON 0x2017
+#define USB_DEVICE_ID_NINTENDO_N64CON 0x2019
#define USB_VENDOR_ID_NOVATEK 0x0603
#define USB_DEVICE_ID_NOVATEK_PCT 0x0600
diff --git a/hid-nintendo.c b/hid-nintendo.c
index 56e9b8fbd9d4..b0487b9d3cb0 100644
--- a/hid-nintendo.c
+++ b/hid-nintendo.c
@@ -304,7 +304,8 @@ enum joycon_ctlr_type {
JOYCON_CTLR_TYPE_PRO = 0x03,
JOYCON_CTLR_TYPE_NESL = 0x09,
JOYCON_CTLR_TYPE_NESR = 0x0A,
- JOYCON_CTLR_TYPE_SNES = 0x0B
+ JOYCON_CTLR_TYPE_SNES = 0x0B,
+ JOYCON_CTLR_TYPE_N64 = 0x0D,
};
struct joycon_stick_cal {
@@ -482,6 +483,8 @@ struct joycon_ctlr {
(ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_CHRGGRIP)
#define jc_type_is_snescon(ctlr) \
(ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_SNESCON)
+#define jc_type_is_n64con(ctlr) \
+ (ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_N64CON)
/* Does this controller have inputs associated with left joycon? */
#define jc_type_has_left(ctlr) \
@@ -493,15 +496,22 @@ struct joycon_ctlr {
(ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCR || \
ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO)
+/* Is this one of the Nintendo Switch Online controllers? */
+#define jc_type_is_nso(ctlr) \
+ (jc_type_is_nescon(ctlr) || \
+ jc_type_is_snescon(ctlr) || \
+ jc_type_is_n64con(ctlr))
+
/* Can this controller be connected via USB */
#define jc_has_usb(ctlr) \
(jc_type_is_procon(ctlr) || \
jc_type_is_chrggrip(ctlr) || \
- jc_type_is_snescon(ctlr))
+ jc_type_is_snescon(ctlr) || \
+ jc_type_is_n64con(ctlr))
/* Does this controller have motion sensors */
#define jc_has_imu(ctlr) \
- (!jc_type_is_nescon(ctlr) && !jc_type_is_snescon(ctlr))
+ (!jc_type_is_nso(ctlr))
/* Does this controller have rumble */
#define jc_has_rumble(ctlr) \
@@ -1202,7 +1212,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
unsigned long msecs = jiffies_to_msecs(jiffies);
spin_lock_irqsave(&ctlr->lock, flags);
- if (/*IS_ENABLED(CONFIG_NINTENDO_FF) && */ jc_has_rumble(ctlr) && \
+ if (IS_ENABLED(CONFIG_NINTENDO_FF) && jc_has_rumble(ctlr) && \
rep->vibrator_report &&
(msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
(ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
@@ -1240,7 +1250,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
/* Parse the buttons and sticks */
btns = hid_field_extract(ctlr->hdev, rep->button_status, 0, 24);
- if (jc_type_has_left(ctlr)) {
+ if (jc_type_has_left(ctlr) || jc_type_is_n64con(ctlr)) {
u16 raw_x;
u16 raw_y;
s32 x;
@@ -1256,7 +1266,8 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
/* report sticks */
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
-
+ }
+ if (jc_type_has_left(ctlr)) {
/* report buttons */
input_report_key(dev, BTN_TL, btns & JC_BTN_L);
input_report_key(dev, BTN_TL2, btns & JC_BTN_ZL);
@@ -1330,7 +1341,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
input_report_key(dev, BTN_SOUTH, btns & JC_BTN_B);
}
- if (jc_type_is_nescon(ctlr) || jc_type_is_snescon(ctlr)) {
+ if (jc_type_is_nso(ctlr)) {
s8 x = 0;
s8 y = 0;
@@ -1352,15 +1363,34 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
input_report_key(dev, BTN_SOUTH, btns & JC_BTN_B);
input_report_key(dev, BTN_TL, btns & JC_BTN_L);
input_report_key(dev, BTN_TR, btns & JC_BTN_R);
- input_report_key(dev, BTN_SELECT, btns & JC_BTN_MINUS);
input_report_key(dev, BTN_START, btns & JC_BTN_PLUS);
+ if (!jc_type_is_n64con(ctlr)) {
+ input_report_key(dev, BTN_SELECT, btns & JC_BTN_MINUS);
+ }
+
if (jc_type_is_snescon(ctlr)) {
input_report_key(dev, BTN_TL2, btns & JC_BTN_ZL);
input_report_key(dev, BTN_TR2, btns & JC_BTN_ZR);
input_report_key(dev, BTN_NORTH, btns & JC_BTN_X);
input_report_key(dev, BTN_WEST, btns & JC_BTN_Y);
}
+
+ if (jc_type_is_n64con(ctlr)) {
+ input_report_key(dev, BTN_TL2, btns & JC_BTN_ZL);
+ input_report_key(dev, BTN_MODE, btns & JC_BTN_HOME);
+ input_report_key(dev, BTN_Z, btns & JC_BTN_CAP);
+
+ /* Back ZR button */
+ input_report_key(dev, BTN_TR2, btns & JC_BTN_LSTICK);
+
+ /* C-buttons: up, right, down, left */
+ input_report_key(dev, BTN_NORTH, btns & JC_BTN_Y);
+ input_report_key(dev, BTN_THUMBR,
+ btns & JC_BTN_MINUS);
+ input_report_key(dev, BTN_THUMBL, btns & JC_BTN_ZR);
+ input_report_key(dev, BTN_WEST, btns & JC_BTN_X);
+ }
}
input_sync(dev);
@@ -1416,7 +1446,7 @@ static void joycon_rumble_worker(struct work_struct *work)
}
}
-//#if IS_ENABLED(CONFIG_NINTENDO_FF)
+#if IS_ENABLED(CONFIG_NINTENDO_FF)
static struct joycon_rumble_freq_data joycon_find_rumble_freq(u16 freq)
{
const size_t length = ARRAY_SIZE(joycon_rumble_frequencies);
@@ -1545,7 +1575,7 @@ static int joycon_play_effect(struct input_dev *dev, void *data,
effect->u.rumble.strong_magnitude,
true);
}
-//#endif /* IS_ENABLED(CONFIG_NINTENDO_FF) */
+#endif /* IS_ENABLED(CONFIG_NINTENDO_FF) */
static const unsigned int joycon_button_inputs_l[] = {
BTN_SELECT, BTN_Z, BTN_THUMBL,
@@ -1576,6 +1606,15 @@ static const unsigned int snescon_button_inputs[] = {
0 /* 0 signals end of array */
};
+static const unsigned int n64con_button_inputs[] = {
+ /* Original N64 controller buttons */
+ BTN_START, BTN_B, BTN_A, BTN_TL, BTN_TL2, BTN_TR,
+ BTN_WEST, BTN_NORTH, BTN_THUMBL, BTN_THUMBR,
+ /* NSO controller additions */
+ BTN_TR2, BTN_MODE, BTN_Z,
+ 0 /* 0 signals end of array */
+};
+
static int joycon_input_create(struct joycon_ctlr *ctlr)
{
struct hid_device *hdev;
@@ -1620,6 +1659,10 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
name = "Nintendo Switch SNES Controller";
imu_name = NULL;
break;
+ case USB_DEVICE_ID_NINTENDO_N64CON:
+ name = "Nintendo Switch N64 Controller";
+ imu_name = NULL;
+ break;
default: /* Should be impossible */
hid_err(hdev, "Invalid hid product\n");
return -EINVAL;
@@ -1675,9 +1718,28 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
input_set_capability(ctlr->input, EV_KEY,
joycon_button_inputs_r[i]);
}
- if (jc_type_is_nescon(ctlr) || jc_type_is_snescon(ctlr)) {
- const unsigned int* inputs = jc_type_is_nescon(ctlr) ?
- nescon_button_inputs : snescon_button_inputs;
+
+ if (jc_type_is_nso(ctlr)) {
+ const unsigned int* inputs;
+
+ if (jc_type_is_nescon(ctlr)) {
+ inputs = nescon_button_inputs;
+ } else if (jc_type_is_snescon(ctlr)) {
+ inputs = snescon_button_inputs;
+ } else if (jc_type_is_n64con(ctlr)) {
+ inputs = n64con_button_inputs;
+
+ input_set_abs_params(ctlr->input, ABS_X,
+ -JC_MAX_STICK_MAG,
+ JC_MAX_STICK_MAG,
+ JC_STICK_FUZZ,
+ JC_STICK_FLAT);
+ input_set_abs_params(ctlr->input, ABS_Y,
+ -JC_MAX_STICK_MAG,
+ JC_MAX_STICK_MAG,
+ JC_STICK_FUZZ,
+ JC_STICK_FLAT);
+ }
/* set up d-pad hat */
input_set_abs_params(ctlr->input, ABS_HAT0X,
@@ -1690,41 +1752,41 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
/* set up buttons */
for (i = 0; inputs[i] > 0; i++)
input_set_capability(ctlr->input, EV_KEY, inputs[i]);
-
- /* register the device here, we don't need any more setup */
- ret = input_register_device(ctlr->input);
- if (ret)
- return ret;
-
- return 0;
}
/* Let's report joy-con S triggers separately */
- if (hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONL) {
+ if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCL) {
input_set_capability(ctlr->input, EV_KEY, BTN_TR);
input_set_capability(ctlr->input, EV_KEY, BTN_TR2);
- } else if (hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONR) {
+ } else if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCR) {
input_set_capability(ctlr->input, EV_KEY, BTN_TL);
input_set_capability(ctlr->input, EV_KEY, BTN_TL2);
}
-//#if IS_ENABLED(CONFIG_NINTENDO_FF)
+#if IS_ENABLED(CONFIG_NINTENDO_FF)
/* set up rumble */
- input_set_capability(ctlr->input, EV_FF, FF_RUMBLE);
- input_ff_create_memless(ctlr->input, NULL, joycon_play_effect);
- ctlr->rumble_ll_freq = JC_RUMBLE_DFLT_LOW_FREQ;
- ctlr->rumble_lh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
- ctlr->rumble_rl_freq = JC_RUMBLE_DFLT_LOW_FREQ;
- ctlr->rumble_rh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
- joycon_clamp_rumble_freqs(ctlr);
- joycon_set_rumble(ctlr, 0, 0, false);
- ctlr->rumble_msecs = jiffies_to_msecs(jiffies);
-//#endif
+ if (jc_has_rumble(ctlr)) {
+ input_set_capability(ctlr->input, EV_FF, FF_RUMBLE);
+ input_ff_create_memless(ctlr->input, NULL,
+ joycon_play_effect);
+ ctlr->rumble_ll_freq = JC_RUMBLE_DFLT_LOW_FREQ;
+ ctlr->rumble_lh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
+ ctlr->rumble_rl_freq = JC_RUMBLE_DFLT_LOW_FREQ;
+ ctlr->rumble_rh_freq = JC_RUMBLE_DFLT_HIGH_FREQ;
+ joycon_clamp_rumble_freqs(ctlr);
+ joycon_set_rumble(ctlr, 0, 0, false);
+ ctlr->rumble_msecs = jiffies_to_msecs(jiffies);
+ }
+#endif
ret = input_register_device(ctlr->input);
if (ret)
return ret;
+ /* setup is done if the controller has no IMU */
+ if (!jc_has_imu(ctlr))
+ return 0;
+
/* configure the imu input device */
ctlr->imu_input = devm_input_allocate_device(&hdev->dev);
if (!ctlr->imu_input)
@@ -2335,6 +2397,10 @@ static const struct hid_device_id nintendo_hid_devices[] = {
USB_DEVICE_ID_NINTENDO_SNESCON) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
USB_DEVICE_ID_NINTENDO_SNESCON) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO,
+ USB_DEVICE_ID_NINTENDO_N64CON) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
+ USB_DEVICE_ID_NINTENDO_N64CON) },
{ }
};
MODULE_DEVICE_TABLE(hid, nintendo_hid_devices);