Reworked the handler adding to be based on input reports. This way multiple

handlers may be added to a single device if it provides more than one report
for a kind of device. Should fix #5549 where two mouse reports are present
and only the first one was picked up and made available as device.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35796 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2010-03-10 01:06:14 +00:00
parent b11dde545b
commit 18074c28fa
5 changed files with 70 additions and 76 deletions
@@ -87,6 +87,8 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
TRACE("keyboard device with %lu keys and %lu modifiers\n", fKeyCount, TRACE("keyboard device with %lu keys and %lu modifiers\n", fKeyCount,
fModifierCount); fModifierCount);
TRACE("input report: %u; output report: %u\n", inputReport->ID(),
outputReport != NULL ? outputReport->ID() : 255);
fLastKeys = (uint16 *)malloc(fKeyCount * 2 * sizeof(uint16)); fLastKeys = (uint16 *)malloc(fKeyCount * 2 * sizeof(uint16));
fCurrentKeys = &fLastKeys[fKeyCount]; fCurrentKeys = &fLastKeys[fKeyCount];
@@ -143,55 +145,46 @@ KeyboardDevice::~KeyboardDevice()
ProtocolHandler * ProtocolHandler *
KeyboardDevice::AddHandler(HIDDevice *device) KeyboardDevice::AddHandler(HIDDevice *device, HIDReport *input)
{ {
HIDParser *parser = device->Parser(); bool mayHaveOutput = false;
// try to find the keyboard usage in any input report
HIDReport *input = NULL;
bool foundKeyboardUsage = false; bool foundKeyboardUsage = false;
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT); for (uint32 i = 0; i < input->CountItems(); i++) {
for (uint32 i = 0; i < reportCount; i++) { HIDReportItem *item = input->ItemAt(i);
input = parser->ReportAt(HID_REPORT_TYPE_INPUT, i); if (item->UsagePage() == HID_USAGE_PAGE_KEYBOARD
|| (item->UsagePage() == HID_USAGE_PAGE_CONSUMER && item->Array())
for (uint32 j = 0; j < input->CountItems(); j++) { || (item->UsagePage() == HID_USAGE_PAGE_BUTTON && item->Array())) {
HIDReportItem *item = input->ItemAt(j); // found at least one item with a keyboard usage or with
if (item->UsagePage() == HID_USAGE_PAGE_KEYBOARD // a consumer/button usage that is handled like a key
|| (item->UsagePage() == HID_USAGE_PAGE_CONSUMER mayHaveOutput = item->UsagePage() == HID_USAGE_PAGE_KEYBOARD;
&& item->Array()) foundKeyboardUsage = true;
|| (item->UsagePage() == HID_USAGE_PAGE_BUTTON
&& item->Array())) {
// found at least one item with a keyboard usage or with
// a consumer/button usage that is handled like a key
foundKeyboardUsage = true;
break;
}
}
if (foundKeyboardUsage)
break; break;
}
} }
if (!foundKeyboardUsage) if (!foundKeyboardUsage)
return NULL; return NULL;
// try to find the led output report
HIDReport *output = NULL; HIDReport *output = NULL;
bool foundOutputReport = false; bool foundOutputReport = false;
reportCount = parser->CountReports(HID_REPORT_TYPE_OUTPUT); if (mayHaveOutput) {
for (uint32 i = 0; i < reportCount; i++) { // try to find the led output report
output = parser->ReportAt(HID_REPORT_TYPE_OUTPUT, i); HIDParser *parser = device->Parser();
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_OUTPUT);
for (uint32 i = 0; i < reportCount; i++) {
output = parser->ReportAt(HID_REPORT_TYPE_OUTPUT, i);
for (uint32 j = 0; j < output->CountItems(); j++) { for (uint32 j = 0; j < output->CountItems(); j++) {
HIDReportItem *item = output->ItemAt(j); HIDReportItem *item = output->ItemAt(j);
if (item->UsagePage() == HID_USAGE_PAGE_LED) { if (item->UsagePage() == HID_USAGE_PAGE_LED) {
foundOutputReport = true; foundOutputReport = true;
break; break;
}
} }
}
if (foundOutputReport) if (foundOutputReport)
break; break;
}
} }
return new(std::nothrow) KeyboardDevice(input, return new(std::nothrow) KeyboardDevice(input,
@@ -19,7 +19,8 @@ public:
HIDReport *outputReport); HIDReport *outputReport);
virtual ~KeyboardDevice(); virtual ~KeyboardDevice();
static ProtocolHandler * AddHandler(HIDDevice *device); static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *input);
virtual status_t Open(uint32 flags); virtual status_t Open(uint32 flags);
virtual status_t Control(uint32 op, void *buffer, size_t length); virtual status_t Control(uint32 op, void *buffer, size_t length);
@@ -47,31 +47,25 @@ MouseDevice::MouseDevice(HIDReport *report, HIDReportItem *xAxis,
fWheel = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP, fWheel = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HID_USAGE_ID_WHEEL); HID_USAGE_ID_WHEEL);
TRACE("mouse device with %lu buttons and %swheel\n", buttonCount,
fWheel == NULL ? "no " : "");
TRACE("report id: %u\n", report->ID());
} }
ProtocolHandler * ProtocolHandler *
MouseDevice::AddHandler(HIDDevice *device) MouseDevice::AddHandler(HIDDevice *device, HIDReport *report)
{ {
HIDParser *parser = device->Parser();
// try to find at least an x and y axis // try to find at least an x and y axis
HIDReport *report = NULL; HIDReportItem *xAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HIDReportItem *xAxis = NULL; HID_USAGE_ID_X);
HIDReportItem *yAxis = NULL; if (xAxis == NULL)
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT); return NULL;
for (uint32 i = 0; i < reportCount; i++) {
report = parser->ReportAt(HID_REPORT_TYPE_INPUT, i);
xAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HID_USAGE_ID_X);
yAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HID_USAGE_ID_Y);
if (xAxis != NULL && yAxis != NULL) HIDReportItem *yAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
break; HID_USAGE_ID_Y);
} if (yAxis == NULL)
if (xAxis == NULL || yAxis == NULL)
return NULL; return NULL;
return new(std::nothrow) MouseDevice(report, xAxis, yAxis); return new(std::nothrow) MouseDevice(report, xAxis, yAxis);
@@ -20,7 +20,8 @@ public:
MouseDevice(HIDReport *report, MouseDevice(HIDReport *report,
HIDReportItem *xAxis, HIDReportItem *yAxis); HIDReportItem *xAxis, HIDReportItem *yAxis);
static ProtocolHandler * AddHandler(HIDDevice *device); static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *report);
virtual status_t Control(uint32 op, void *buffer, size_t length); virtual status_t Control(uint32 op, void *buffer, size_t length);
@@ -63,36 +63,41 @@ ProtocolHandler::AddHandlers(HIDDevice *device, ProtocolHandler ***handlerList,
{ {
TRACE("adding protocol handlers\n"); TRACE("adding protocol handlers\n");
uint32 count = 3; HIDParser *parser = device->Parser();
ProtocolHandler *handlers[count]; uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT);
handlers[0] = KeyboardDevice::AddHandler(device);
handlers[1] = MouseDevice::AddHandler(device);
handlers[2] = NULL; //GenericDevice::AddHandler(device);
*handlerCount = 0; *handlerCount = 0;
uint32 actualCount = 0;
for (uint32 i = 0; i < count; i++) {
if (handlers[i] != NULL)
actualCount++;
}
if (actualCount == 0) {
TRACE_ALWAYS("no handlers for hid device\n");
return;
}
*handlerList = (ProtocolHandler **)malloc(sizeof(ProtocolHandler *) *handlerList = (ProtocolHandler **)malloc(sizeof(ProtocolHandler *)
* actualCount); * reportCount * 2 /* handler type count */);
if (*handlerList == NULL) { if (*handlerList == NULL) {
TRACE_ALWAYS("out of memory allocating handler list\n"); TRACE_ALWAYS("out of memory allocating handler list\n");
return; return;
} }
for (uint32 i = 0; i < count; i++) { uint32 usedCount = 0;
if (handlers[i] != NULL) ProtocolHandler *handler = NULL;
(*handlerList)[(*handlerCount)++] = handlers[i]; for (uint32 i = 0; i < reportCount; i++) {
HIDReport *report = parser->ReportAt(HID_REPORT_TYPE_INPUT, i);
handler = KeyboardDevice::AddHandler(device, report);
if (handler != NULL)
(*handlerList)[usedCount++] = handler;
handler = MouseDevice::AddHandler(device, report);
if (handler != NULL)
(*handlerList)[usedCount++] = handler;
} }
if (usedCount == 0) {
TRACE_ALWAYS("no handlers for hid device\n");
return;
}
*handlerCount = usedCount;
ProtocolHandler **shrunkList = (ProtocolHandler **)realloc(
*handlerList, sizeof(ProtocolHandler *) * usedCount);
if (shrunkList != NULL)
*handlerList = shrunkList;
TRACE("added %ld handlers for hid device\n", *handlerCount); TRACE("added %ld handlers for hid device\n", *handlerCount);
} }