summarylogtreecommitdiffstats
path: root/0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch
diff options
context:
space:
mode:
authorJeka2025-03-20 23:34:20 +0300
committerJeka2025-03-20 23:34:20 +0300
commite2603a165805a865040d5ffbe1db5dfcc1b15087 (patch)
tree3d387db5b9f5aecdb938052b953a942b95928833 /0007-hid-asus-ally-move-MCU-FW-validation-to-module.patch
parenta9fcf6eb146bb99793f85b26567c1d3b350e5542 (diff)
downloadaur-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.patch265
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
+