Merge branch 'for-7.2/nintendo' into for-linus

- support for HORI Wireless Switch Pad (Hector Zelaya)
This commit is contained in:
Jiri Kosina
2026-06-16 21:51:31 +02:00
2 changed files with 71 additions and 12 deletions

View File

@@ -683,6 +683,9 @@
#define USB_DEVICE_ID_HARMONIX_WII_RB3_KEYBOARD 0x3330
#define USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_KEYBOARD_MODE 0x3338
#define USB_VENDOR_ID_HORI 0x0f0d
#define USB_DEVICE_ID_HORI_WIRELESS_SWITCH_PAD 0x00f6
#define USB_VENDOR_ID_HP 0x03f0
#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a

View File

@@ -316,6 +316,7 @@ enum joycon_ctlr_type {
JOYCON_CTLR_TYPE_JCL = 0x01,
JOYCON_CTLR_TYPE_JCR = 0x02,
JOYCON_CTLR_TYPE_PRO = 0x03,
JOYCON_CTLR_TYPE_LIC_PRO = 0x06,
JOYCON_CTLR_TYPE_NESL = 0x09,
JOYCON_CTLR_TYPE_NESR = 0x0A,
JOYCON_CTLR_TYPE_SNES = 0x0B,
@@ -433,6 +434,25 @@ static const struct joycon_ctlr_button_mapping procon_button_mappings[] = {
{ /* sentinel */ },
};
/* Licensed Pro Controllers (e.g. HORI) swap X/Y bits in the report */
static const struct joycon_ctlr_button_mapping lic_procon_button_mappings[] = {
{ BTN_EAST, JC_BTN_A, },
{ BTN_SOUTH, JC_BTN_B, },
{ BTN_NORTH, JC_BTN_Y, },
{ BTN_WEST, JC_BTN_X, },
{ BTN_TL, JC_BTN_L, },
{ BTN_TR, JC_BTN_R, },
{ BTN_TL2, JC_BTN_ZL, },
{ BTN_TR2, JC_BTN_ZR, },
{ BTN_SELECT, JC_BTN_MINUS, },
{ BTN_START, JC_BTN_PLUS, },
{ BTN_THUMBL, JC_BTN_LSTICK, },
{ BTN_THUMBR, JC_BTN_RSTICK, },
{ BTN_MODE, JC_BTN_HOME, },
{ BTN_Z, JC_BTN_CAP, },
{ /* sentinel */ },
};
static const struct joycon_ctlr_button_mapping nescon_button_mappings[] = {
{ BTN_SOUTH, JC_BTN_A, },
{ BTN_EAST, JC_BTN_B, },
@@ -695,7 +715,8 @@ static inline bool joycon_type_is_right_joycon(struct joycon_ctlr *ctlr)
static inline bool joycon_type_is_procon(struct joycon_ctlr *ctlr)
{
return ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO;
return ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO ||
ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO;
}
static inline bool joycon_type_is_snescon(struct joycon_ctlr *ctlr)
@@ -1710,7 +1731,10 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
joycon_report_left_stick(ctlr, rep);
joycon_report_right_stick(ctlr, rep);
joycon_report_dpad(ctlr, rep);
joycon_report_buttons(ctlr, rep, procon_button_mappings);
if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO)
joycon_report_buttons(ctlr, rep, lic_procon_button_mappings);
else
joycon_report_buttons(ctlr, rep, procon_button_mappings);
} else if (joycon_type_is_any_nescon(ctlr)) {
joycon_report_dpad(ctlr, rep);
joycon_report_buttons(ctlr, rep, nescon_button_mappings);
@@ -2156,7 +2180,10 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
joycon_config_left_stick(ctlr->input);
joycon_config_right_stick(ctlr->input);
joycon_config_dpad(ctlr->input);
joycon_config_buttons(ctlr->input, procon_button_mappings);
if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO)
joycon_config_buttons(ctlr->input, lic_procon_button_mappings);
else
joycon_config_buttons(ctlr->input, procon_button_mappings);
} else if (joycon_type_is_any_nescon(ctlr)) {
joycon_config_dpad(ctlr->input);
joycon_config_buttons(ctlr->input, nescon_button_mappings);
@@ -2503,13 +2530,30 @@ static int joycon_init(struct hid_device *hdev)
if (joycon_has_joysticks(ctlr)) {
/* get controller calibration data, and parse it */
ret = joycon_request_calibration(ctlr);
if (ret) {
if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO) {
/*
* We can function with default calibration, but it may be
* inaccurate. Provide a warning, and continue on.
* Licensed controllers may have incompatible SPI flash
* layouts. Use default calibration values.
*/
hid_warn(hdev, "Analog stick positions may be inaccurate\n");
hid_info(hdev, "using default cal for licensed controller\n");
joycon_use_default_calibration(hdev,
&ctlr->left_stick_cal_x,
&ctlr->left_stick_cal_y,
"left", 0);
joycon_use_default_calibration(hdev,
&ctlr->right_stick_cal_x,
&ctlr->right_stick_cal_y,
"right", 0);
} else {
ret = joycon_request_calibration(ctlr);
if (ret) {
/*
* We can function with default calibration, but
* it may be inaccurate. Provide a warning, and
* continue on.
*/
hid_warn(hdev, "Analog stick positions may be inaccurate\n");
}
}
}
@@ -2527,8 +2571,13 @@ static int joycon_init(struct hid_device *hdev)
/* Enable the IMU */
ret = joycon_enable_imu(ctlr);
if (ret) {
hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret);
goto out_unlock;
if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO) {
hid_dbg(hdev, "IMU enable failed for licensed controller, continuing\n");
ret = 0;
} else {
hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret);
goto out_unlock;
}
}
}
@@ -2543,8 +2592,13 @@ static int joycon_init(struct hid_device *hdev)
/* Enable rumble */
ret = joycon_enable_rumble(ctlr);
if (ret) {
hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret);
goto out_unlock;
if (ctlr->ctlr_type == JOYCON_CTLR_TYPE_LIC_PRO) {
hid_dbg(hdev, "rumble enable failed for licensed controller, continuing\n");
ret = 0;
} else {
hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret);
goto out_unlock;
}
}
}
@@ -2813,6 +2867,8 @@ static const struct hid_device_id nintendo_hid_devices[] = {
USB_DEVICE_ID_NINTENDO_GENCON) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
USB_DEVICE_ID_NINTENDO_N64CON) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HORI,
USB_DEVICE_ID_HORI_WIRELESS_SWITCH_PAD) },
{ }
};
MODULE_DEVICE_TABLE(hid, nintendo_hid_devices);