From c9c3b32d3bb966e3851915bc03251b3dc4b5fad1 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 21 Aug 2009 18:46:24 +0000 Subject: [PATCH] Rework incoming report handling. We need to notify all reports when one comes in because all reports schedule transfers on the same endpoint and therefore need to possibly reschedule. Previously if we got a report that we didn't listen on all further reports would stop, because noone would schedule a new transfer. This fixes extra keys not working on my natural keyboard. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32580 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/input/usb_hid/HIDParser.cpp | 42 +++++++++---------- .../drivers/input/usb_hid/KeyboardDevice.cpp | 6 ++- .../drivers/input/usb_hid/MouseDevice.cpp | 7 +++- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/add-ons/kernel/drivers/input/usb_hid/HIDParser.cpp b/src/add-ons/kernel/drivers/input/usb_hid/HIDParser.cpp index 26e27a1ae4..0d62d35f36 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDParser.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDParser.cpp @@ -448,34 +448,34 @@ HIDParser::MaxReportSize() void HIDParser::SetReport(status_t status, uint8 *report, size_t length) { - if (status != B_OK) { - // in case of error we need to notify all input reports, as we don't - // know who has waiting listeners. - for (uint32 i = 0; i < fReportCount; i++) { - if (fReports[i] == NULL - || fReports[i]->Type() != HID_REPORT_TYPE_INPUT) - continue; + if (status != B_OK || length == 0) { + if (status == B_OK) + status = B_ERROR; - fReports[i]->SetReport(status, NULL, 0); - } - - return; + report = NULL; + length = 0; } - HIDReport *target = NULL; - if (fUsesReportIDs) { - target = FindReport(HID_REPORT_TYPE_INPUT, report[0]); + uint8 targetID = 0; + if (fUsesReportIDs && status == B_OK) { + targetID = report[0]; report++; length--; - } else - target = FindReport(HID_REPORT_TYPE_INPUT, 0); - - if (target == NULL) { - TRACE_ALWAYS("got report buffer but found no report to handle it\n"); - return; } - target->SetReport(status, report, length); + // We need to notify all input reports, as we don't know who has waiting + // listeners. Anyone other than the target report also waiting for a + // transfer to happen needs to reschedule one now. + for (uint32 i = 0; i < fReportCount; i++) { + if (fReports[i] == NULL + || fReports[i]->Type() != HID_REPORT_TYPE_INPUT) + continue; + + if (fReports[i]->ID() == targetID) + fReports[i]->SetReport(status, report, length); + else + fReports[i]->SetReport(B_INTERRUPTED, NULL, 0); + } } diff --git a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp index c614854534..f7971e637f 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardDevice.cpp @@ -334,8 +334,10 @@ KeyboardDevice::_ReadReport(bigtime_t timeout) return B_ERROR; } - if (result != B_TIMED_OUT) { - // we expect timeouts as we do repeat key handling this way + if (result != B_TIMED_OUT && result != B_INTERRUPTED) { + // we expect timeouts as we do repeat key handling this way, + // interrupts happen when other reports come in on the same + // endpoint TRACE_ALWAYS("error waiting for report: %s\n", strerror(result)); } diff --git a/src/add-ons/kernel/drivers/input/usb_hid/MouseDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/MouseDevice.cpp index aa01c5f42b..0efbff3f35 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/MouseDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseDevice.cpp @@ -116,7 +116,12 @@ MouseDevice::_ReadReport() return B_ERROR; } - TRACE_ALWAYS("error waiting for report: %s\n", strerror(result)); + if (result != B_INTERRUPTED) { + // interrupts happen when other reports come in on the same + // input as ours + TRACE_ALWAYS("error waiting for report: %s\n", strerror(result)); + } + // signal that we simply want to try again return B_OK; }