diff options
author | Jeka | 2025-03-20 23:34:20 +0300 |
---|---|---|
committer | Jeka | 2025-03-20 23:34:20 +0300 |
commit | e2603a165805a865040d5ffbe1db5dfcc1b15087 (patch) | |
tree | 3d387db5b9f5aecdb938052b953a942b95928833 /0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch | |
parent | a9fcf6eb146bb99793f85b26567c1d3b350e5542 (diff) | |
download | aur-linux-jcore.tar.gz |
kernel release 6.13.7
Diffstat (limited to '0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch')
-rw-r--r-- | 0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch b/0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch new file mode 100644 index 000000000000..eb23dbb9d6ae --- /dev/null +++ b/0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch @@ -0,0 +1,265 @@ +From 6ef4589173fb3ac905db41a19410d177c3c929df Mon Sep 17 00:00:00 2001 +From: Luke Jones <luke@ljones.dev> +Date: Mon, 24 Feb 2025 19:40:04 +1300 +Subject: [PATCH 07/28] hid-asus-ally: move MCU FW validation to module + +Signed-off-by: Luke Jones <luke@ljones.dev> +--- + drivers/hid/hid-asus-ally.c | 97 ++++++++++++++++++++++++++++++++++ + drivers/hid/hid-asus.c | 101 ------------------------------------ + 2 files changed, 97 insertions(+), 101 deletions(-) + +diff --git a/drivers/hid/hid-asus-ally.c b/drivers/hid/hid-asus-ally.c +index d4172a829ced..cf0bbaa88a69 100644 +--- a/drivers/hid/hid-asus-ally.c ++++ b/drivers/hid/hid-asus-ally.c +@@ -368,6 +368,97 @@ static void ally_rgb_remove(struct hid_device *hdev) + /* ROG Ally driver init */ + /**************************************************************************************************/ + ++/* ++ * We don't care about any other part of the string except the version section. ++ * Example strings: FGA80100.RC72LA.312_T01, FGA80100.RC71LS.318_T01 ++ * The bytes "5a 05 03 31 00 1a 13" and possibly more come before the version ++ * string, and there may be additional bytes after the version string such as ++ * "75 00 74 00 65 00" or a postfix such as "_T01" ++ */ ++static int mcu_parse_version_string(const u8 *response, size_t response_size) ++{ ++ const u8 *end = response + response_size; ++ const u8 *p = response; ++ int dots, err, version; ++ char buf[4]; ++ ++ dots = 0; ++ while (p < end && dots < 2) { ++ if (*p++ == '.') ++ dots++; ++ } ++ ++ if (dots != 2 || p >= end || (p + 3) >= end) ++ return -EINVAL; ++ ++ memcpy(buf, p, 3); ++ buf[3] = '\0'; ++ ++ err = kstrtoint(buf, 10, &version); ++ if (err || version < 0) ++ return -EINVAL; ++ ++ return version; ++} ++ ++static int mcu_request_version(struct hid_device *hdev) ++{ ++ u8 *response __free(kfree) = kzalloc(ROG_ALLY_REPORT_SIZE, GFP_KERNEL); ++ const u8 request[] = { 0x5a, 0x05, 0x03, 0x31, 0x00, 0x20 }; ++ int ret; ++ ++ if (!response) ++ return -ENOMEM; ++ ++ ret = asus_dev_set_report(hdev, request, sizeof(request)); ++ if (ret < 0) ++ return ret; ++ ++ ret = hid_hw_raw_request(hdev, FEATURE_REPORT_ID, response, ++ ROG_ALLY_REPORT_SIZE, HID_FEATURE_REPORT, ++ HID_REQ_GET_REPORT); ++ if (ret < 0) ++ return ret; ++ ++ ret = mcu_parse_version_string(response, ROG_ALLY_REPORT_SIZE); ++ if (ret < 0) { ++ pr_err("Failed to parse MCU version: %d\n", ret); ++ print_hex_dump(KERN_ERR, "MCU: ", DUMP_PREFIX_NONE, ++ 16, 1, response, ROG_ALLY_REPORT_SIZE, false); ++ } ++ ++ return ret; ++} ++ ++static void validate_mcu_fw_version(struct hid_device *hdev, int idProduct) ++{ ++ int min_version, version; ++ ++ version = mcu_request_version(hdev); ++ if (version < 0) ++ return; ++ ++ switch (idProduct) { ++ case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY: ++ min_version = ROG_ALLY_MIN_MCU; ++ break; ++ case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X: ++ min_version = ROG_ALLY_X_MIN_MCU; ++ break; ++ default: ++ min_version = 0; ++ } ++ ++ if (version < min_version) { ++ hid_warn(hdev, ++ "The MCU firmware version must be %d or greater to avoid issues with suspend.\n", ++ min_version); ++ } else { ++ set_ally_mcu_hack(false); ++ set_ally_mcu_powersave(true); ++ } ++} ++ + static int ally_hid_init(struct hid_device *hdev) + { + int ret; +@@ -387,6 +478,9 @@ static int ally_hid_init(struct hid_device *hdev) + + static int ally_hid_probe(struct hid_device *hdev, const struct hid_device_id *_id) + { ++ struct usb_interface *intf = to_usb_interface(hdev->dev.parent); ++ struct usb_device *udev = interface_to_usbdev(intf); ++ u16 idProduct = le16_to_cpu(udev->descriptor.idProduct); + int ret, ep; + + ep = get_endpoint_address(hdev); +@@ -424,6 +518,8 @@ static int ally_hid_probe(struct hid_device *hdev, const struct hid_device_id *_ + + /* This should almost always exist */ + if (ep == ROG_ALLY_CFG_INTF_IN) { ++ validate_mcu_fw_version(hdev, idProduct); ++ + drvdata.led_rgb_dev = ally_rgb_create(hdev); + if (IS_ERR(drvdata.led_rgb_dev)) + hid_err(hdev, "Failed to create Ally gamepad LEDs.\n"); +@@ -512,6 +608,7 @@ static void __exit rog_ally_exit(void) + module_init(rog_ally_init); + module_exit(rog_ally_exit); + ++MODULE_IMPORT_NS("ASUS_WMI"); + MODULE_AUTHOR("Luke D. Jones"); + MODULE_DESCRIPTION("HID Driver for ASUS ROG Ally gamepad configuration."); + MODULE_LICENSE("GPL"); +diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c +index 9ebee77638a0..83883f58202b 100644 +--- a/drivers/hid/hid-asus.c ++++ b/drivers/hid/hid-asus.c +@@ -540,102 +540,9 @@ static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev) + return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT); + } + +-/* +- * We don't care about any other part of the string except the version section. +- * Example strings: FGA80100.RC72LA.312_T01, FGA80100.RC71LS.318_T01 +- * The bytes "5a 05 03 31 00 1a 13" and possibly more come before the version +- * string, and there may be additional bytes after the version string such as +- * "75 00 74 00 65 00" or a postfix such as "_T01" +- */ +-static int mcu_parse_version_string(const u8 *response, size_t response_size) +-{ +- const u8 *end = response + response_size; +- const u8 *p = response; +- int dots, err, version; +- char buf[4]; +- +- dots = 0; +- while (p < end && dots < 2) { +- if (*p++ == '.') +- dots++; +- } +- +- if (dots != 2 || p >= end || (p + 3) >= end) +- return -EINVAL; +- +- memcpy(buf, p, 3); +- buf[3] = '\0'; +- +- err = kstrtoint(buf, 10, &version); +- if (err || version < 0) +- return -EINVAL; +- +- return version; +-} +- +-static int mcu_request_version(struct hid_device *hdev) +-{ +- u8 *response __free(kfree) = kzalloc(ROG_ALLY_REPORT_SIZE, GFP_KERNEL); +- const u8 request[] = { 0x5a, 0x05, 0x03, 0x31, 0x00, 0x20 }; +- int ret; +- +- if (!response) +- return -ENOMEM; +- +- ret = asus_kbd_set_report(hdev, request, sizeof(request)); +- if (ret < 0) +- return ret; +- +- ret = hid_hw_raw_request(hdev, FEATURE_REPORT_ID, response, +- ROG_ALLY_REPORT_SIZE, HID_FEATURE_REPORT, +- HID_REQ_GET_REPORT); +- if (ret < 0) +- return ret; +- +- ret = mcu_parse_version_string(response, ROG_ALLY_REPORT_SIZE); +- if (ret < 0) { +- pr_err("Failed to parse MCU version: %d\n", ret); +- print_hex_dump(KERN_ERR, "MCU: ", DUMP_PREFIX_NONE, +- 16, 1, response, ROG_ALLY_REPORT_SIZE, false); +- } +- +- return ret; +-} +- +-static void validate_mcu_fw_version(struct hid_device *hdev, int idProduct) +-{ +- int min_version, version; +- +- version = mcu_request_version(hdev); +- if (version < 0) +- return; +- +- switch (idProduct) { +- case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY: +- min_version = ROG_ALLY_MIN_MCU; +- break; +- case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X: +- min_version = ROG_ALLY_X_MIN_MCU; +- break; +- default: +- min_version = 0; +- } +- +- if (version < min_version) { +- hid_warn(hdev, +- "The MCU firmware version must be %d or greater to avoid issues with suspend.\n", +- min_version); +- } else { +- set_ally_mcu_hack(false); +- set_ally_mcu_powersave(true); +- } +-} +- + static int asus_kbd_register_leds(struct hid_device *hdev) + { + struct asus_drvdata *drvdata = hid_get_drvdata(hdev); +- struct usb_interface *intf; +- struct usb_device *udev; + unsigned char kbd_func; + int ret; + +@@ -659,14 +566,6 @@ static int asus_kbd_register_leds(struct hid_device *hdev) + if (ret < 0) + return ret; + } +- +- if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) { +- intf = to_usb_interface(hdev->dev.parent); +- udev = interface_to_usbdev(intf); +- validate_mcu_fw_version(hdev, +- le16_to_cpu(udev->descriptor.idProduct)); +- } +- + } else { + /* Initialize keyboard */ + ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID); +-- +2.48.1 + |