From: Cristian Mazzotta <cmmazzo@icloud.com>
To: aer@tuxedocomputers.com
Cc: W_Armin@gmx.de, bentiss@kernel.org, jikos@kernel.org,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
wse@tuxedocomputers.com, Cristian Mazzotta <cmmazzo@icloud.com>
Subject: [PATCH 1/4] HID: lamparray: read attribute reports synchronously
Date: Wed, 9 Sep 2026 11:52:54 -0500 [thread overview]
Message-ID: <20260909165257.352597-2-cmmazzo@icloud.com> (raw)
In-Reply-To: <20260909165257.352597-1-cmmazzo@icloud.com>
lamparray_read_attributes_report() and lamparray_get_lamp_attributes()
use hid_hw_request(HID_REQ_GET_REPORT) followed by hid_hw_wait(), then
read the results out of field->value[]. hid_hw_request() is asynchronous
and hid_hw_wait() only clears the output queue, so the values are still
read before the transfer has completed.
On an Acer Predator PT14-52T (USB keyboard 05AF:767A), this returns zero
for LampCount, and then zero for red, green, blue, and intensity counts.
The last one is evil: max_brightness is passed to
led_mc_calc_color_components() as a divisor during
lamparray_register_led(), resulting in a divide by zero during probe:
Oops: divide error: 0000 [#1] SMP NOPTI
RIP: 0010:led_mc_calc_color_components+0x58/0x70
Call Trace:
lamparray_register_led+0x119/0x1e0
lamparray_register+0x502/0x820
hid_generic_probe+0x5e/0xc0
The fault kills the kworker running hub_event() while it holds the USB
and HID device locks, which stalls further probing on that bus.
Use hid_hw_raw_request() with a hid_report_len()-sized buffer and hand
the result to hid_report_raw_event() so the HID core parses it into
field->value[] before the values are read.
Validate the level counts after reading them and fail with -EINVAL if
any is zero, so a device reporting no levels cannot reach
led_mc_calc_color_components() at all. The four level fields are also
required to share one report, since a single GET_REPORT is used to
fetch them.
Signed-off-by: Cristian Mazzotta <cmmazzo@icloud.com>
---
drivers/hid/hid-lamparray.c | 73 ++++++++++++++++++++++++++++++-------
1 file changed, 59 insertions(+), 14 deletions(-)
diff --git a/drivers/hid/hid-lamparray.c b/drivers/hid/hid-lamparray.c
index 9a438aa2d305..f169929aecd6 100644
--- a/drivers/hid/hid-lamparray.c
+++ b/drivers/hid/hid-lamparray.c
@@ -164,6 +164,9 @@ static int lamparray_read_attributes_report(struct lamparray_device *ldev)
{
struct hid_device *hdev = ldev->hdev;
struct hid_report *report;
+ int ret;
+ u8 *buf;
+ size_t len;
if (!ldev->lamp_count.field) {
hid_dbg(hdev, "No LampCount field found\n");
@@ -182,25 +185,37 @@ static int lamparray_read_attributes_report(struct lamparray_device *ldev)
return -ENODEV;
}
+ len = hid_report_len(report);
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
mutex_lock(&ldev->dev_lock);
/* Update values */
- hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
- hid_hw_wait(hdev);
+ ret = hid_hw_raw_request(hdev, report->id, buf, len,
+ HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+ if (ret < 0) {
+ hid_dbg(hdev, "Failed to get LampCount value from device: %d\n", ret);
+ goto out;
+ }
- ldev->lamp_count_value = get_field_value(&ldev->lamp_count);
+ hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, len, ret, 0);
- if (ldev->lamp_count_value == 0) {
- mutex_unlock(&ldev->dev_lock);
- hid_dbg(hdev, "LampCount is %d (invalid)\n", ldev->lamp_count_value);
- return -EINVAL;
+ ldev->lamp_count_value = get_field_value(&ldev->lamp_count);
+ if (!ldev->lamp_count_value) {
+ hid_dbg(hdev, "LampCount is 0 (invalid)\n");
+ ret = -EINVAL;
+ goto out;
}
ldev->lamparray_kind_value = get_field_value(&ldev->lamparray_kind);
+ ret = 0;
+out:
mutex_unlock(&ldev->dev_lock);
-
- return 0;
+ kfree(buf);
+ return ret;
}
static int lamparray_parse_update_report(struct lamparray_device *ldev)
@@ -371,28 +386,58 @@ static int lamparray_get_lamp_attributes(struct lamparray_device *ldev)
{
struct hid_device *hdev = ldev->hdev;
struct hid_report *report;
+ int ret;
+ u8 *buf;
+ size_t len;
if (!lamparray_color_fields_is_complete(&ldev->color_levels))
return -ENODEV;
/*
- * Get value of any lamp.
+ * All four fields must share the same report since the
+ * attributes are fetched with a single GET_REPORT below.
*/
report = ldev->color_levels.red.field->report;
+ if (!report ||
+ ldev->color_levels.green.field->report != report ||
+ ldev->color_levels.blue.field->report != report ||
+ ldev->color_levels.intensity.field->report != report)
+ return -ENODEV;
+
+ len = hid_report_len(report);
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
mutex_lock(&ldev->dev_lock);
- hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
- hid_hw_wait(hdev);
+ /* Update values */
+ ret = hid_hw_raw_request(hdev, report->id, buf, len,
+ HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+ if (ret < 0) {
+ hid_dbg(hdev, "Failed to read LampAttributesResponseReport: %d\n", ret);
+ goto out;
+ }
+
+ hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, len, ret, 0);
ldev->max_r = get_field_value_as_u8(&ldev->color_levels.red);
ldev->max_g = get_field_value_as_u8(&ldev->color_levels.green);
ldev->max_b = get_field_value_as_u8(&ldev->color_levels.blue);
ldev->max_brightness = get_field_value_as_u8(&ldev->color_levels.intensity);
- mutex_unlock(&ldev->dev_lock);
+ if (!ldev->max_r || !ldev->max_g || !ldev->max_b || !ldev->max_brightness) {
+ hid_dbg(hdev, "LampArray device has no color levels\n");
+ ret = -EINVAL;
+ goto out;
+ }
- return 0;
+ ret = 0;
+
+out:
+ mutex_unlock(&ldev->dev_lock);
+ kfree(buf);
+ return ret;
}
/* Helper functions */
--
2.55.0
next prev parent reply other threads:[~2026-09-09 16:53 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 7:35 [PATCH v5 0/2] HID: generic: add LampArray support via hid-lamparray helper Aaron Erhardt
2026-09-03 7:35 ` [PATCH v5 1/2] HID: lamparray: add new LampArray helper module Aaron Erhardt
2026-09-03 7:48 ` sashiko-bot
2026-09-03 20:07 ` Werner Sembach
2026-09-04 8:51 ` Aaron Erhardt
2026-09-04 21:30 ` Armin Wolf
2026-09-07 16:13 ` Aaron Erhardt
2026-09-03 7:35 ` [PATCH v5 2/2] HID: generic: add LampArray support via hid-lamparray helper Aaron Erhardt
2026-09-03 7:46 ` sashiko-bot
2026-09-04 20:49 ` [PATCH v5 0/2] " Armin Wolf
2026-09-07 16:30 ` Aaron Erhardt
2026-09-09 16:52 ` [PATCH 0/4] HID: lamparray: fixes from testing on Acer Predator PT14-52T Cristian Mazzotta
2026-09-09 16:52 ` Cristian Mazzotta [this message]
2026-09-09 16:52 ` [PATCH 2/4] HID: lamparray: raise log level of fatal probe errors Cristian Mazzotta
2026-09-09 16:52 ` [PATCH 3/4] HID: lamparray: transfer control when use_leds_uapi changes Cristian Mazzotta
2026-09-09 16:52 ` [PATCH 4/4] HID: lamparray: blank lamps across suspend and restore on resume Cristian Mazzotta
2026-09-11 10:38 ` [PATCH 0/4] HID: lamparray: fixes from testing on Acer Predator PT14-52T Aaron Erhardt
2026-09-09 22:36 ` [PATCH v5 0/2] HID: generic: add LampArray support via hid-lamparray helper Armin Wolf
2026-09-11 10:01 ` Aaron Erhardt
2026-09-14 13:32 ` Aaron Erhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260909165257.352597-2-cmmazzo@icloud.com \
--to=cmmazzo@icloud.com \
--cc=W_Armin@gmx.de \
--cc=aer@tuxedocomputers.com \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=wse@tuxedocomputers.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.