Skip to content

Commit 3fe6acd

Browse files
dtorJiri Kosina
authored andcommitted
HID: vivaldi: fix handling devices not using numbered reports
Unfortunately details of USB HID transport bled into HID core and handling of numbered/unnumbered reports is quite a mess, with hid_report_len() calculating the length according to USB rules, and hid_hw_raw_request() adding report ID to the buffer for both numbered and unnumbered reports. Untangling it all requres a lot of changes in HID, so for now let's handle this in the driver. [jkosina@suse.cz: microoptimize field->report->id to report->id] Fixes: 14c9c01 ("HID: add vivaldi HID driver") Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Tested-by: Stephen Boyd <swboyd@chromium.org> # CoachZ Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent f3193ea commit 3fe6acd

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

drivers/hid/hid-vivaldi.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ static void vivaldi_feature_mapping(struct hid_device *hdev,
7474
struct hid_usage *usage)
7575
{
7676
struct vivaldi_data *drvdata = hid_get_drvdata(hdev);
77+
struct hid_report *report = field->report;
7778
int fn_key;
7879
int ret;
7980
u32 report_len;
80-
u8 *buf;
81+
u8 *report_data, *buf;
8182

8283
if (field->logical != HID_USAGE_FN_ROW_PHYSMAP ||
8384
(usage->hid & HID_USAGE_PAGE) != HID_UP_ORDINAL)
@@ -89,12 +90,24 @@ static void vivaldi_feature_mapping(struct hid_device *hdev,
8990
if (fn_key > drvdata->max_function_row_key)
9091
drvdata->max_function_row_key = fn_key;
9192

92-
buf = hid_alloc_report_buf(field->report, GFP_KERNEL);
93-
if (!buf)
93+
report_data = buf = hid_alloc_report_buf(report, GFP_KERNEL);
94+
if (!report_data)
9495
return;
9596

96-
report_len = hid_report_len(field->report);
97-
ret = hid_hw_raw_request(hdev, field->report->id, buf,
97+
report_len = hid_report_len(report);
98+
if (!report->id) {
99+
/*
100+
* hid_hw_raw_request() will stuff report ID (which will be 0)
101+
* into the first byte of the buffer even for unnumbered
102+
* reports, so we need to account for this to avoid getting
103+
* -EOVERFLOW in return.
104+
* Note that hid_alloc_report_buf() adds 7 bytes to the size
105+
* so we can safely say that we have space for an extra byte.
106+
*/
107+
report_len++;
108+
}
109+
110+
ret = hid_hw_raw_request(hdev, report->id, report_data,
98111
report_len, HID_FEATURE_REPORT,
99112
HID_REQ_GET_REPORT);
100113
if (ret < 0) {
@@ -103,7 +116,16 @@ static void vivaldi_feature_mapping(struct hid_device *hdev,
103116
goto out;
104117
}
105118

106-
ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
119+
if (!report->id) {
120+
/*
121+
* Undo the damage from hid_hw_raw_request() for unnumbered
122+
* reports.
123+
*/
124+
report_data++;
125+
report_len--;
126+
}
127+
128+
ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data,
107129
report_len, 0);
108130
if (ret) {
109131
dev_warn(&hdev->dev, "failed to report feature %d\n",

0 commit comments

Comments
 (0)