From 4f18dc04961d4aebde79313f24e9cfa1ae3a1e53 Mon Sep 17 00:00:00 2001 From: Zelenoviy Date: Tue, 1 Nov 2022 03:26:55 +0700 Subject: [PATCH] usb_hid: Fix MaxReportSize computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While calculating buffer size for IN reports, only "Input" report type should been taken in account. Complex HID devices, such as "Gaming" keyboards and mice, often have "Feature"-reports declared (with size way bigger than "typical" kbd IN report) for vendor-specific device configurations. But "Feature"-reports are sent over control channel only and can't appear on interrupt channel. Should fix #14919, #17937, #17699 Change-Id: I4b9eb51938ca4aba2bc34247d00ae164eb2c19fc Reviewed-on: https://review.haiku-os.org/c/haiku/+/5771 Reviewed-by: Jérôme Duval Tested-by: Commit checker robot --- .../kernel/drivers/input/hid_shared/HIDParser.cpp | 10 ++++++++++ .../kernel/drivers/input/hid_shared/HIDParser.h | 1 + .../input/hid_shared/KeyboardProtocolHandler.cpp | 5 +++-- src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.cpp b/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.cpp index aaef7dce68..05d8729d2e 100644 --- a/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.cpp +++ b/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.cpp @@ -430,6 +430,13 @@ HIDParser::ReportAt(uint8 type, uint8 index) size_t HIDParser::MaxReportSize() +{ + return MaxReportSize(HID_REPORT_TYPE_ANY); +} + + +size_t +HIDParser::MaxReportSize(uint8 type) { size_t maxSize = 0; for (int32 i = 0; i < fReports.Count(); i++) { @@ -437,6 +444,9 @@ HIDParser::MaxReportSize() if (report == NULL) continue; + if (type != HID_REPORT_TYPE_ANY && report->Type() != type) + continue; + if (report->ReportSize() > maxSize) maxSize = report->ReportSize(); } diff --git a/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.h b/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.h index 75f1101158..b8523eb431 100644 --- a/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.h +++ b/src/add-ons/kernel/drivers/input/hid_shared/HIDParser.h @@ -30,6 +30,7 @@ public: uint8 CountReports(uint8 type); HIDReport * ReportAt(uint8 type, uint8 index); size_t MaxReportSize(); + size_t MaxReportSize(uint8 type); HIDCollection * RootCollection() { return fRootCollection; }; diff --git a/src/add-ons/kernel/drivers/input/hid_shared/KeyboardProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/hid_shared/KeyboardProtocolHandler.cpp index ad3128b482..da6619f109 100644 --- a/src/add-ons/kernel/drivers/input/hid_shared/KeyboardProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/hid_shared/KeyboardProtocolHandler.cpp @@ -110,7 +110,8 @@ KeyboardProtocolHandler::KeyboardProtocolHandler(HIDReport &inputReport, #ifdef USB_KDL sDebugKeyboardPipe = fInputReport.Device()->InterruptPipe(); #endif - sDebugKeyboardReportSize = fInputReport.Parser()->MaxReportSize(); + sDebugKeyboardReportSize = + fInputReport.Parser()->MaxReportSize(HID_REPORT_TYPE_INPUT); if (outputReport != NULL) sDebugKeyboardFound = true; } @@ -794,7 +795,7 @@ KeyboardProtocolHandler::_ReadReport(bigtime_t timeout, uint32 *cookie) = fInputReport.Device()->InterruptPipe(); #endif sDebugKeyboardReportSize - = fInputReport.Parser()->MaxReportSize(); + = fInputReport.Parser()->MaxReportSize(HID_REPORT_TYPE_INPUT); #endif char letter = current[i] - 4 + 'a'; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp index cbce1e65ee..7902bbf5ff 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp @@ -181,7 +181,7 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, return; } - fTransferBufferSize = fParser.MaxReportSize(); + fTransferBufferSize = fParser.MaxReportSize(HID_REPORT_TYPE_INPUT); if (fTransferBufferSize == 0) { TRACE_ALWAYS("report claims a report size of 0\n"); return;