[PATCH v3] HID: add driver for Gigabyte Aero vendor-specific brightness keys
From: Uddhav Swami <hidden>
Date: 2026-07-15 05:59:56
Also in:
lkml
Subsystem:
hid core layer, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Linus Torvalds
The Gigabyte Aero 15 XB keyboard (Chu Yuen Enterprise Co., Ltd,
USB ID 1044:7a3f) sends brightness up/down keypresses as vendor-defined
HID reports (Usage Page 0xFF02, Report ID 4) rather than standard HID
Consumer Control usages, causing KEY_BRIGHTNESSUP and KEY_BRIGHTNESSDOWN
to never reach the input subsystem.
Add a minimal HID driver that intercepts Report ID 4 and maps values
0x7D and 0x7E to KEY_BRIGHTNESSDOWN and KEY_BRIGHTNESSUP respectively.
Tested on: Gigabyte Aero 15 XB (USB ID 1044:7a3f)
Signed-off-by: Uddhav Swami <redacted>
---
v3:
- Restrict registration of brightness key capabilities to only the
hid_input containing GIGABYTE_AERO_REPORT_ID, avoiding the registration
of redundant/dummy input devices for other collections (reported by
Sashiko).
- Scan the hi->reports list to find the report, as hi->report is NULL
unless HID_QUIRK_MULTI_INPUT is set.
- Rename the error return variable in gigabyte_aero_probe() from 'ret' to
'error' to follow input subsystem conventions.
v2:
- Check HID_CLAIMED_INPUT after hid_hw_start() to avoid potential
use-after-free if input_register_device() fails during probe.
Reported by Sashiko.
drivers/hid/Kconfig | 10 +++
drivers/hid/Makefile | 1 +
drivers/hid/hid-gigabyte.c | 144 +++++++++++++++++++++++++++++++++++++
drivers/hid/hid-ids.h | 5 +-
4 files changed, 158 insertions(+), 2 deletions(-)
create mode 100644 drivers/hid/hid-gigabyte.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 03f36899e458..fa74e67e35c8 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig@@ -406,6 +406,16 @@ config HID_GFRM help Support for Google Fiber TV Box remote controls +config HID_GIGABYTE_AERO + tristate "Gigabyte Aero laptop vendor-specific keys" + depends on USB_HID + help + Support for vendor-specific keyboard keys on Gigabyte Aero + laptops + + Currently the following device is known to be supported: + - Gigabyte Aero 15 XB + config HID_GLORIOUS tristate "Glorious PC Gaming Race mice" help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 23e6e3dd0c56..ef3a14b04126 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile@@ -55,6 +55,7 @@ obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_FT260) += hid-ft260.o obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o obj-$(CONFIG_HID_GFRM) += hid-gfrm.o +obj-$(CONFIG_HID_GIGABYTE_AERO) += hid-gigabyte.o obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o obj-$(CONFIG_HID_VIVALDI_COMMON) += hid-vivaldi-common.o obj-$(CONFIG_HID_GOODIX_SPI) += hid-goodix-spi.o
diff --git a/drivers/hid/hid-gigabyte.c b/drivers/hid/hid-gigabyte.c
new file mode 100644
index 000000000000..5a66d270ea8e
--- /dev/null
+++ b/drivers/hid/hid-gigabyte.c@@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID driver for Gigabyte Aero laptop vendor-specific brightness keys. + * + * The keyboard sends brightness up/down presses as a vendor-defined usage page + * report instead of standard HID Consumer Control usages. + * + * This driver intercepts them and emits the correct KEY_BRIGHTNESSUP / + * KEY_BRIGHTNESSDOWN events. + * + * Currently supported devices are: + * Gigabyte Aero 15 XB + * + * Copyright (c) 2026 Uddhav Swami <uddhavswami@gmail.com> + * + * This module based on hid-asus by + * Copyright (c) 2016 Yusuke Fujimaki <usk.fujimaki@gmail.com> + * Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org> + * Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com> + * Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com> + */ + +#include <linux/hid.h> +#include <linux/module.h> +#include <linux/input.h> + +#include "hid-ids.h" + +MODULE_AUTHOR("Uddhav Swami <uddhavswami@gmail.com>"); +MODULE_DESCRIPTION("HID driver for Gigabyte Aero"); + +#define GIGABYTE_AERO_REPORT_ID 0x04 +#define GIGABYTE_AERO_BRIGHTNESS_DOWN 0x7D +#define GIGABYTE_AERO_BRIGHTNESS_UP 0x7E + +struct gigabyte_drvdata { + struct input_dev *input; +}; + +static int gigabyte_aero_raw_event(struct hid_device *hdev, + struct hid_report *report, u8 *data, + int size) +{ + struct gigabyte_drvdata *drvdata = hid_get_drvdata(hdev); + + if (!drvdata->input) + return 0; + + if (report->id != GIGABYTE_AERO_REPORT_ID || size < 4) + return 0; + + switch (data[3]) { + case GIGABYTE_AERO_BRIGHTNESS_DOWN: + input_report_key(drvdata->input, KEY_BRIGHTNESSDOWN, 1); + input_sync(drvdata->input); + input_report_key(drvdata->input, KEY_BRIGHTNESSDOWN, 0); + input_sync(drvdata->input); + return 1; + case GIGABYTE_AERO_BRIGHTNESS_UP: + input_report_key(drvdata->input, KEY_BRIGHTNESSUP, 1); + input_sync(drvdata->input); + input_report_key(drvdata->input, KEY_BRIGHTNESSUP, 0); + input_sync(drvdata->input); + return 1; + default: + return 0; + } +} + +static int gigabyte_aero_input_configured(struct hid_device *hdev, + struct hid_input *hi) +{ + struct gigabyte_drvdata *drvdata = hid_get_drvdata(hdev); + struct hid_report *report; + bool has_report = false; + + list_for_each_entry(report, &hi->reports, hidinput_list) { + if (report->id == GIGABYTE_AERO_REPORT_ID) { + has_report = true; + break; + } + } + + if (!has_report) + return 0; + + input_set_capability(hi->input, EV_KEY, KEY_BRIGHTNESSUP); + input_set_capability(hi->input, EV_KEY, KEY_BRIGHTNESSDOWN); + + drvdata->input = hi->input; + + return 0; +} + +static int gigabyte_aero_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + struct gigabyte_drvdata *drvdata; + int error; + + drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + hid_set_drvdata(hdev, drvdata); + + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "gigabyte_aero: parse failed: %d\n", error); + return error; + } + + error = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (error) { + hid_err(hdev, "gigabyte_aero: hw start failed: %d\n", error); + return error; + } + + if (!(hdev->claimed & HID_CLAIMED_INPUT)) { + hid_err(hdev, "gigabyte_aero: no input device claimed\n"); + hid_hw_stop(hdev); + return -ENODEV; + } + + return 0; +} + +static const struct hid_device_id gigabyte_aero_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_CHU_YUEN, + USB_DEVICE_ID_CHU_YUEN_AERO_KBD) }, + {} +}; +MODULE_DEVICE_TABLE(hid, gigabyte_aero_devices); + +static struct hid_driver gigabyte_aero_driver = { + .name = "hid_gigabyte_aero", + .id_table = gigabyte_aero_devices, + .probe = gigabyte_aero_probe, + .raw_event = gigabyte_aero_raw_event, + .input_configured = gigabyte_aero_input_configured, +}; +module_hid_driver(gigabyte_aero_driver); + +MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b70f719b3b07..e33cdf33929b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h@@ -330,6 +330,9 @@ #define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 +#define USB_VENDOR_ID_CHU_YUEN 0x1044 +#define USB_DEVICE_ID_CHU_YUEN_AERO_KBD 0x7a3f + #define USB_VENDOR_ID_CIDC 0x1677 #define I2C_VENDOR_ID_CIRQUE 0x0488
@@ -1319,7 +1322,6 @@ #define USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE 0x0368 #define USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE 0x0369 - #define USB_VENDOR_ID_SONY 0x054c #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374
@@ -1610,7 +1612,6 @@ #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65 0x4d65 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22 - #define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */ #define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */
--
2.55.0