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

View File

@ -87,6 +87,8 @@ KeyboardDevice::KeyboardDevice(HIDReport *inputReport, HIDReport *outputReport)
TRACE("keyboard device with %lu keys and %lu modifiers\n", fKeyCount,
fModifierCount);
TRACE("input report: %u; output report: %u\n", inputReport->ID(),
outputReport != NULL ? outputReport->ID() : 255);
fLastKeys = (uint16 *)malloc(fKeyCount * 2 * sizeof(uint16));
fCurrentKeys = &fLastKeys[fKeyCount];
@ -143,55 +145,46 @@ KeyboardDevice::~KeyboardDevice()
ProtocolHandler *
KeyboardDevice::AddHandler(HIDDevice *device)
KeyboardDevice::AddHandler(HIDDevice *device, HIDReport *input)
{
HIDParser *parser = device->Parser();
// try to find the keyboard usage in any input report
HIDReport *input = NULL;
bool mayHaveOutput = false;
bool foundKeyboardUsage = false;
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT);
for (uint32 i = 0; i < reportCount; i++) {
input = parser->ReportAt(HID_REPORT_TYPE_INPUT, i);
for (uint32 j = 0; j < input->CountItems(); j++) {
HIDReportItem *item = input->ItemAt(j);
if (item->UsagePage() == HID_USAGE_PAGE_KEYBOARD
|| (item->UsagePage() == HID_USAGE_PAGE_CONSUMER
&& item->Array())
|| (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)
for (uint32 i = 0; i < input->CountItems(); i++) {
HIDReportItem *item = input->ItemAt(i);
if (item->UsagePage() == HID_USAGE_PAGE_KEYBOARD
|| (item->UsagePage() == HID_USAGE_PAGE_CONSUMER && item->Array())
|| (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
mayHaveOutput = item->UsagePage() == HID_USAGE_PAGE_KEYBOARD;
foundKeyboardUsage = true;
break;
}
}
if (!foundKeyboardUsage)
return NULL;
// try to find the led output report
HIDReport *output = NULL;
bool foundOutputReport = false;
reportCount = parser->CountReports(HID_REPORT_TYPE_OUTPUT);
for (uint32 i = 0; i < reportCount; i++) {
output = parser->ReportAt(HID_REPORT_TYPE_OUTPUT, i);
if (mayHaveOutput) {
// try to find the led output report
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++) {
HIDReportItem *item = output->ItemAt(j);
if (item->UsagePage() == HID_USAGE_PAGE_LED) {
foundOutputReport = true;
break;
for (uint32 j = 0; j < output->CountItems(); j++) {
HIDReportItem *item = output->ItemAt(j);
if (item->UsagePage() == HID_USAGE_PAGE_LED) {
foundOutputReport = true;
break;
}
}
}
if (foundOutputReport)
break;
if (foundOutputReport)
break;
}
}
return new(std::nothrow) KeyboardDevice(input,

View File

@ -19,7 +19,8 @@ public:
HIDReport *outputReport);
virtual ~KeyboardDevice();
static ProtocolHandler * AddHandler(HIDDevice *device);
static ProtocolHandler * AddHandler(HIDDevice *device,
HIDReport *input);
virtual status_t Open(uint32 flags);
virtual status_t Control(uint32 op, void *buffer, size_t length);

View File

@ -47,31 +47,25 @@ MouseDevice::MouseDevice(HIDReport *report, HIDReportItem *xAxis,
fWheel = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
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 *
MouseDevice::AddHandler(HIDDevice *device)
MouseDevice::AddHandler(HIDDevice *device, HIDReport *report)
{
HIDParser *parser = device->Parser();
// try to find at least an x and y axis
HIDReport *report = NULL;
HIDReportItem *xAxis = NULL;
HIDReportItem *yAxis = NULL;
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT);
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);
HIDReportItem *xAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HID_USAGE_ID_X);
if (xAxis == NULL)
return NULL;
if (xAxis != NULL && yAxis != NULL)
break;
}
if (xAxis == NULL || yAxis == NULL)
HIDReportItem *yAxis = report->FindItem(HID_USAGE_PAGE_GENERIC_DESKTOP,
HID_USAGE_ID_Y);
if (yAxis == NULL)
return NULL;
return new(std::nothrow) MouseDevice(report, xAxis, yAxis);

View File

@ -20,7 +20,8 @@ public:
MouseDevice(HIDReport *report,
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);

View File

@ -63,36 +63,41 @@ ProtocolHandler::AddHandlers(HIDDevice *device, ProtocolHandler ***handlerList,
{
TRACE("adding protocol handlers\n");
uint32 count = 3;
ProtocolHandler *handlers[count];
handlers[0] = KeyboardDevice::AddHandler(device);
handlers[1] = MouseDevice::AddHandler(device);
handlers[2] = NULL; //GenericDevice::AddHandler(device);
HIDParser *parser = device->Parser();
uint32 reportCount = parser->CountReports(HID_REPORT_TYPE_INPUT);
*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 *)
* actualCount);
* reportCount * 2 /* handler type count */);
if (*handlerList == NULL) {
TRACE_ALWAYS("out of memory allocating handler list\n");
return;
}
for (uint32 i = 0; i < count; i++) {
if (handlers[i] != NULL)
(*handlerList)[(*handlerCount)++] = handlers[i];
uint32 usedCount = 0;
ProtocolHandler *handler = NULL;
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);
}