diff options
author | Nadia Holmquist Pedersen | 2023-04-06 00:43:30 +0000 |
---|---|---|
committer | Nadia Holmquist Pedersen | 2023-04-06 00:43:30 +0000 |
commit | 79b7bc9fc928680fb14507932b5faea2ba034e4b (patch) | |
tree | 8286ab9ddde9154d58a3c18be3c3962fa8ff5729 | |
parent | ffce16e529f8c3cacf1e9084486664509fb32cc9 (diff) | |
download | aur-79b7bc9fc928680fb14507932b5faea2ba034e4b.tar.gz |
Add support for the Switch N64 controller.
Also fix build for new kernels
-rw-r--r-- | .SRCINFO | 11 | ||||
-rw-r--r-- | PKGBUILD | 10 | ||||
-rw-r--r-- | dkms.conf | 4 | ||||
-rw-r--r-- | hid-ids.h | 1 | ||||
-rw-r--r-- | hid-nintendo.c | 132 |
5 files changed, 112 insertions, 46 deletions
@@ -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 - @@ -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); |