From bc64bf6ab46295838173e90e698171f14d7134b3 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 6 Jun 2011 00:10:56 +0000 Subject: [PATCH] Add support for absolute pointing devices. Supported are mice/pointers with absolute coordinates (qemu/kvm -usbdevice tablet) and various digitizers. If a tablet-like usage is determined the MouseProtocolHandler publishes to input/tablet instead of input/mouse and reports its info in a tablet_movement structure instead of a mouse_movement structure, allowing for absolute coordinates. Note that right now only the absolute coordinates are used, the other tablet specific inputs (eraser, pressure, tilt and contact) aren't yet filled in. I will add these as a second step. I've only tested this with kvm where this makes the "seamless" mouse integration work and therefore fixes #5989. Note that QEMU for BeOS/Haiku doesn't support that mode (patch pending on my side) and will lock the pointer into the upper left corner if -usbdevice tablet is used (whereas it previously just did nothing). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41951 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../input/usb_hid/MouseProtocolHandler.cpp | 115 +++++++++++++++--- .../input/usb_hid/MouseProtocolHandler.h | 4 +- 2 files changed, 99 insertions(+), 20 deletions(-) diff --git a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp index 4355c455ec..0ba0680f5a 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp @@ -22,11 +22,13 @@ #include -MouseProtocolHandler::MouseProtocolHandler(HIDReport &report, +MouseProtocolHandler::MouseProtocolHandler(HIDReport &report, bool tablet, HIDReportItem &xAxis, HIDReportItem &yAxis) : - ProtocolHandler(report.Device(), "input/mouse/usb/", 0), + ProtocolHandler(report.Device(), + tablet ? "input/tablet/usb" : "input/mouse/usb/", 0), fReport(report), + fTablet(tablet), fXAxis(xAxis), fYAxis(yAxis), fWheel(NULL), @@ -62,9 +64,40 @@ void MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, ProtocolHandler *&handlerList) { - if (collection.UsagePage() != B_HID_USAGE_PAGE_GENERIC_DESKTOP - || collection.UsageID() != B_HID_UID_GD_MOUSE) { - TRACE("collection not a mouse\n"); + bool tablet = false; + bool supported = false; + switch (collection.UsagePage()) { + case B_HID_USAGE_PAGE_GENERIC_DESKTOP: + { + switch (collection.UsageID()) { + case B_HID_UID_GD_MOUSE: + case B_HID_UID_GD_POINTER: + supported = true; + break; + } + + break; + } + + case B_HID_USAGE_PAGE_DIGITIZER: + { + switch (collection.UsageID()) { + case B_HID_UID_DIG_DIGITIZER: + case B_HID_UID_DIG_PEN: + case B_HID_UID_DIG_LIGHT_PEN: + case B_HID_UID_DIG_TOUCH_SCREEN: + case B_HID_UID_DIG_TOUCH_PAD: + case B_HID_UID_DIG_WHITE_BOARD: + supported = true; + tablet = true; + } + + break; + } + } + + if (!supported) { + TRACE("collection not a mouse/tablet/digitizer\n"); return; } @@ -92,8 +125,11 @@ MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, if (yAxis == NULL) continue; + if (!xAxis->Relative() && !yAxis->Relative()) + tablet = true; + ProtocolHandler *newHandler = new(std::nothrow) MouseProtocolHandler( - *inputReport, *xAxis, *yAxis); + *inputReport, tablet, *xAxis, *yAxis); if (newHandler == NULL) { TRACE("failed to allocated mouse protocol handler\n"); continue; @@ -112,8 +148,10 @@ MouseProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, switch (op) { case MS_READ: { - if (length < sizeof(mouse_movement)) + if ((!fTablet && length < sizeof(mouse_movement)) + || (fTablet && length < sizeof(tablet_movement))) { return B_BUFFER_OVERFLOW; + } while (true) { status_t result = _ReadReport(buffer); @@ -164,31 +202,42 @@ MouseProtocolHandler::_ReadReport(void *buffer) return B_INTERRUPTED; } - mouse_movement *info = (mouse_movement *)buffer; - memset(info, 0, sizeof(mouse_movement)); + float axisAbsoluteData[2]; + uint32 axisRelativeData[2]; + if (fXAxis.Extract() == B_OK && fXAxis.Valid()) { + if (fXAxis.Relative()) + axisRelativeData[0] = fXAxis.Data(); + else + axisAbsoluteData[0] = fXAxis.ScaledFloatData(); + } - if (fXAxis.Extract() == B_OK && fXAxis.Valid()) - info->xdelta = fXAxis.Data(); - if (fYAxis.Extract() == B_OK && fYAxis.Valid()) - info->ydelta = -fYAxis.Data(); + if (fYAxis.Extract() == B_OK && fYAxis.Valid()) { + if (fYAxis.Relative()) + axisRelativeData[1] = fYAxis.Data(); + else + axisAbsoluteData[1] = fYAxis.ScaledFloatData(); + } + uint32 wheelData = 0; if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid()) - info->wheel_ydelta = -fWheel->Data(); + wheelData = fWheel->Data(); + uint32 buttons = 0; for (uint32 i = 0; i < B_MAX_MOUSE_BUTTONS; i++) { HIDReportItem *button = fButtons[i]; if (button == NULL) break; if (button->Extract() == B_OK && button->Valid()) - info->buttons |= (button->Data() & 1) << (button->UsageID() - 1); + buttons |= (button->Data() & 1) << (button->UsageID() - 1); } fReport.DoneProcessing(); TRACE("got mouse report\n"); + int32 clicks = 0; bigtime_t timestamp = system_time(); - if (info->buttons != 0) { + if (buttons != 0) { if (fLastButtons == 0) { if (fLastClickTime + fClickSpeed > timestamp) fClickCount++; @@ -197,10 +246,38 @@ MouseProtocolHandler::_ReadReport(void *buffer) } fLastClickTime = timestamp; - info->clicks = fClickCount; + clicks = fClickCount; + } + + fLastButtons = buttons; + + if (fTablet) { + tablet_movement *info = (tablet_movement *)buffer; + memset(info, 0, sizeof(tablet_movement)); + + info->xpos = axisAbsoluteData[0]; + info->ypos = axisAbsoluteData[1]; + info->has_contact = true; + info->pressure = 1.0; + info->eraser = false; + info->tilt_x = 0.0; + info->tilt_y = 0.0; + + info->buttons = buttons; + info->clicks = clicks; + info->timestamp = timestamp; + info->wheel_ydelta = -wheelData; + } else { + mouse_movement *info = (mouse_movement *)buffer; + memset(info, 0, sizeof(mouse_movement)); + + info->buttons = buttons; + info->xdelta = axisRelativeData[0]; + info->ydelta = -axisRelativeData[1]; + info->clicks = clicks; + info->timestamp = timestamp; + info->wheel_ydelta = -wheelData; } - fLastButtons = info->buttons; - info->timestamp = timestamp; return B_OK; } diff --git a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h index 6ad2aa6b72..ec6121bbef 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.h @@ -23,7 +23,8 @@ class HIDReportItem; class MouseProtocolHandler : public ProtocolHandler { public: MouseProtocolHandler(HIDReport &report, - HIDReportItem &xAxis, HIDReportItem &yAxis); + bool tablet, HIDReportItem &xAxis, + HIDReportItem &yAxis); static void AddHandlers(HIDDevice &device, HIDCollection &collection, @@ -36,6 +37,7 @@ private: status_t _ReadReport(void *buffer); HIDReport & fReport; + bool fTablet; HIDReportItem & fXAxis; HIDReportItem & fYAxis;