hrev46015 adds 2 changesets to branch 'master' old head: 2019bf1e17bd833bb884552e61949a2e6feced37 new head: 6e47dfbeaf66b98863b4274617203bb3491b791e overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=6e47dfb+%5E2019bf1 ---------------------------------------------------------------------------- 526e95c: USB HID: Fixed warnings about unused variables. 6e47dfb: USB HID: Split out tablet support into TabletProtocolHandler * The previous approach of combining tablet and mouse support in MouseProtocolHandler was unintuitive and had the potential problem that if a device has multiple HID descriptors, one simulating a simple mouse, that one may be found first and there is no mechanism of choosing the best handler for a device. Now we can look for tablets before looking for mice. * Implement pressure, eraser and tilt support. Untested. This mostly comes from the patch in #7354, but eraser support should work more like intended by the Be API. * It appears that my Wacom Intuos 2 cannot be accessed via the HID framework, except as regular mouse. So I couldn't actually test these changes. I believe what worked before, i.e. QEMU absolute mouse position support, should work as good as before. Please shout if not! * If more recent Wacom tablets /could/ work with these changes, they will not, because the HID driver still explicitely ignores Wacom devices and the dedicated Wacom driver will not pick up newer devices, with its hard-coded and un-generic device support. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 431 insertions(+), 81 deletions(-) src/add-ons/kernel/drivers/input/usb_hid/Jamfile | 1 + .../input/usb_hid/JoystickProtocolHandler.cpp | 7 +- .../input/usb_hid/KeyboardProtocolHandler.cpp | 4 +- .../input/usb_hid/MouseProtocolHandler.cpp | 98 ++---- .../drivers/input/usb_hid/MouseProtocolHandler.h | 3 +- .../drivers/input/usb_hid/ProtocolHandler.cpp | 15 +- .../input/usb_hid/TabletProtocolHandler.cpp | 322 +++++++++++++++++++ .../input/usb_hid/TabletProtocolHandler.h | 62 ++++ ############################################################################ Commit: 526e95c5cde3c120d82b74a711acd1dbf6b502d4 URL: http://cgit.haiku-os.org/haiku/commit/?id=526e95c Author: Stephan Aßmus <superstippi@xxxxxx> Date: Tue Sep 3 15:54:13 2013 UTC USB HID: Fixed warnings about unused variables. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp index e7aff13..20ab159 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/JoystickProtocolHandler.cpp @@ -79,13 +79,14 @@ JoystickProtocolHandler::JoystickProtocolHandler(HIDReport &report) break; } - uint16 axis = 0; +// TODO: "axis" is set but not used! +// uint16 axis = 0; if (item->UsageID() >= B_HID_UID_GD_X && item->UsageID() <= B_HID_UID_GD_WHEEL) { - axis = item->UsageID() - B_HID_UID_GD_X; +// axis = item->UsageID() - B_HID_UID_GD_X; } else if (item->UsageID() >= B_HID_UID_GD_VX && item->UsageID() <= B_HID_UID_GD_VNO) { - axis = item->UsageID() - B_HID_UID_GD_VX; +// axis = item->UsageID() - B_HID_UID_GD_VX; } else break; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardProtocolHandler.cpp index 083c5fe..a04f896 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/KeyboardProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/KeyboardProtocolHandler.cpp @@ -224,7 +224,7 @@ KeyboardProtocolHandler::AddHandlers(HIDDevice &device, for (uint32 i = 0; i < inputReportCount; i++) { HIDReport *inputReport = inputReports[i]; - bool mayHaveOutput = false; +// bool mayHaveOutput = false; bool foundKeyboardUsage = false; for (uint32 j = 0; j < inputReport->CountItems(); j++) { HIDReportItem *item = inputReport->ItemAt(j); @@ -238,7 +238,7 @@ KeyboardProtocolHandler::AddHandlers(HIDDevice &device, && 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() == B_HID_USAGE_PAGE_KEYBOARD; +// mayHaveOutput = item->UsagePage() == B_HID_USAGE_PAGE_KEYBOARD; foundKeyboardUsage = true; break; } ############################################################################ Revision: hrev46015 Commit: 6e47dfbeaf66b98863b4274617203bb3491b791e URL: http://cgit.haiku-os.org/haiku/commit/?id=6e47dfb Author: Stephan Aßmus <superstippi@xxxxxx> Date: Tue Sep 3 15:55:02 2013 UTC Ticket: https://dev.haiku-os.org/ticket/7354 USB HID: Split out tablet support into TabletProtocolHandler * The previous approach of combining tablet and mouse support in MouseProtocolHandler was unintuitive and had the potential problem that if a device has multiple HID descriptors, one simulating a simple mouse, that one may be found first and there is no mechanism of choosing the best handler for a device. Now we can look for tablets before looking for mice. * Implement pressure, eraser and tilt support. Untested. This mostly comes from the patch in #7354, but eraser support should work more like intended by the Be API. * It appears that my Wacom Intuos 2 cannot be accessed via the HID framework, except as regular mouse. So I couldn't actually test these changes. I believe what worked before, i.e. QEMU absolute mouse position support, should work as good as before. Please shout if not! * If more recent Wacom tablets /could/ work with these changes, they will not, because the HID driver still explicitely ignores Wacom devices and the dedicated Wacom driver will not pick up newer devices, with its hard-coded and un-generic device support. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/drivers/input/usb_hid/Jamfile b/src/add-ons/kernel/drivers/input/usb_hid/Jamfile index a521899..63d6180 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/Jamfile +++ b/src/add-ons/kernel/drivers/input/usb_hid/Jamfile @@ -24,4 +24,5 @@ KernelAddon usb_hid : JoystickProtocolHandler.cpp KeyboardProtocolHandler.cpp MouseProtocolHandler.cpp + TabletProtocolHandler.cpp ; 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 0ba0680..4533ec4 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/MouseProtocolHandler.cpp @@ -22,16 +22,16 @@ #include <keyboard_mouse_driver.h> -MouseProtocolHandler::MouseProtocolHandler(HIDReport &report, bool tablet, +MouseProtocolHandler::MouseProtocolHandler(HIDReport &report, HIDReportItem &xAxis, HIDReportItem &yAxis) : - ProtocolHandler(report.Device(), - tablet ? "input/tablet/usb" : "input/mouse/usb/", 0), + ProtocolHandler(report.Device(), "input/mouse/usb/", 0), fReport(report), - fTablet(tablet), + fXAxis(xAxis), fYAxis(yAxis), fWheel(NULL), + fLastButtons(0), fClickCount(0), fLastClickTime(0), @@ -64,7 +64,6 @@ void MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, ProtocolHandler *&handlerList) { - bool tablet = false; bool supported = false; switch (collection.UsagePage()) { case B_HID_USAGE_PAGE_GENERIC_DESKTOP: @@ -78,26 +77,10 @@ MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, 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"); + TRACE("collection not a mouse\n"); return; } @@ -114,22 +97,19 @@ MouseProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, for (uint32 i = 0; i < inputReportCount; i++) { HIDReport *inputReport = inputReports[i]; - // try to find at least an x and y axis + // try to find at least an absolute x and y axis HIDReportItem *xAxis = inputReport->FindItem( B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); - if (xAxis == NULL) + if (xAxis == NULL || !xAxis->Relative()) continue; HIDReportItem *yAxis = inputReport->FindItem( B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y); - if (yAxis == NULL) + if (yAxis == NULL || !yAxis->Relative()) continue; - if (!xAxis->Relative() && !yAxis->Relative()) - tablet = true; - ProtocolHandler *newHandler = new(std::nothrow) MouseProtocolHandler( - *inputReport, tablet, *xAxis, *yAxis); + *inputReport, *xAxis, *yAxis); if (newHandler == NULL) { TRACE("failed to allocated mouse protocol handler\n"); continue; @@ -148,10 +128,8 @@ MouseProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, switch (op) { case MS_READ: { - if ((!fTablet && length < sizeof(mouse_movement)) - || (fTablet && length < sizeof(tablet_movement))) { + if (length < sizeof(mouse_movement)) return B_BUFFER_OVERFLOW; - } while (true) { status_t result = _ReadReport(buffer); @@ -202,21 +180,15 @@ MouseProtocolHandler::_ReadReport(void *buffer) return B_INTERRUPTED; } - 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(); - } + axisRelativeData[0] = 0; + axisRelativeData[1] = 0; - if (fYAxis.Extract() == B_OK && fYAxis.Valid()) { - if (fYAxis.Relative()) - axisRelativeData[1] = fYAxis.Data(); - else - axisAbsoluteData[1] = fYAxis.ScaledFloatData(); - } + if (fXAxis.Extract() == B_OK && fXAxis.Valid()) + axisRelativeData[0] = fXAxis.Data(); + + if (fYAxis.Extract() == B_OK && fYAxis.Valid()) + axisRelativeData[1] = fYAxis.Data(); uint32 wheelData = 0; if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid()) @@ -251,33 +223,15 @@ MouseProtocolHandler::_ReadReport(void *buffer) 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; - } + 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; 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 ec6121b..eb9ffdd 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,7 @@ class HIDReportItem; class MouseProtocolHandler : public ProtocolHandler { public: MouseProtocolHandler(HIDReport &report, - bool tablet, HIDReportItem &xAxis, + HIDReportItem &xAxis, HIDReportItem &yAxis); static void AddHandlers(HIDDevice &device, @@ -37,7 +37,6 @@ private: status_t _ReadReport(void *buffer); HIDReport & fReport; - bool fTablet; HIDReportItem & fXAxis; HIDReportItem & fYAxis; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/ProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/ProtocolHandler.cpp index f1c2f55..52a8af7 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/ProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/ProtocolHandler.cpp @@ -14,9 +14,10 @@ #include "ProtocolHandler.h" // includes for the different protocol handlers +#include "JoystickProtocolHandler.h" #include "KeyboardProtocolHandler.h" #include "MouseProtocolHandler.h" -#include "JoystickProtocolHandler.h" +#include "TabletProtocolHandler.h" ProtocolHandler::ProtocolHandler(HIDDevice *device, const char *basePath, @@ -86,9 +87,19 @@ ProtocolHandler::AddHandlers(HIDDevice &device, ProtocolHandler *&handlerList, TRACE("collection usage page %u usage id %u\n", collection->UsagePage(), collection->UsageID()); + // NOTE: There isn't currently a mechanism in place that figures out the + // "best" handler for a device. Consider the case of a tablet input + // device: It might advertise itself as regular mouse in one descriptor. + // If the MouseProtocolHandler is given a chance to look at the device + // first, it might be happy with that descriptor and provide the + // protocol handler. That is why the TabletProtocolHandler and + // JostickProtocolHandlers are given a chance first, so they might look + // for more interesting descriptors that unlock the specific device + // functions best. KeyboardProtocolHandler::AddHandlers(device, *collection, handlerList); - MouseProtocolHandler::AddHandlers(device, *collection, handlerList); JoystickProtocolHandler::AddHandlers(device, *collection, handlerList); + TabletProtocolHandler::AddHandlers(device, *collection, handlerList); + MouseProtocolHandler::AddHandlers(device, *collection, handlerList); } ProtocolHandler *handler = handlerList; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp new file mode 100644 index 0000000..936584f --- /dev/null +++ b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp @@ -0,0 +1,322 @@ +/* + * Copyright 2013 Stephan Aßmus <superstippi@xxxxxx> + * Copyright 2010-2011 Enrique Medina Gremaldos <quiqueiii@xxxxxxxxx> + * Copyright 2008-2011 Michael Lotz <mmlr@xxxxxxxx> + * Distributed under the terms of the MIT license. + */ + + +//! Driver for USB Human Interface Devices. + + +#include "Driver.h" +#include "TabletProtocolHandler.h" + +#include "HIDCollection.h" +#include "HIDDevice.h" +#include "HIDReport.h" +#include "HIDReportItem.h" + +#include <new> +#include <string.h> +#include <usb/USB_hid.h> + +#include <keyboard_mouse_driver.h> + + +TabletProtocolHandler::TabletProtocolHandler(HIDReport &report, + HIDReportItem &xAxis, HIDReportItem &yAxis) + : + ProtocolHandler(report.Device(), "input/tablet/usb", 0), + fReport(report), + + fXAxis(xAxis), + fYAxis(yAxis), + fWheel(NULL), + + fPressure(NULL), + fRange(NULL), + fTip(NULL), + fBarrelSwitch(NULL), + fEraser(NULL), + fXTilt(NULL), + fYTilt(NULL), + + fLastButtons(0), + fClickCount(0), + fLastClickTime(0), + fClickSpeed(250000) +{ + uint32 buttonCount = 0; + for (uint32 i = 0; i < report.CountItems(); i++) { + HIDReportItem *item = report.ItemAt(i); + if (!item->HasData()) + continue; + + if (item->UsagePage() == B_HID_USAGE_PAGE_BUTTON + && item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS) { + fButtons[buttonCount++] = item; + } + } + + fButtons[buttonCount] = NULL; + + fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP, + B_HID_UID_GD_WHEEL); + + fPressure = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_TIP_PRESSURE); + + fRange = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_IN_RANGE); + + fTip = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_TIP_SWITCH); + + fBarrelSwitch = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_BARREL_SWITCH); + + fEraser = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_ERASER); + + fXTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_X_TILT); + + fYTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + B_HID_UID_DIG_Y_TILT); + + TRACE("tablet device with %lu buttons, %stip, %seraser, " + "%spressure, and %stilt\n", + buttonCount, + fTip == NULL ? "no " : "", + fEraser == NULL ? "no " : "", + fPressure == NULL ? "no " : "", + fXTilt == NULL && fYTilt == NULL ? "no " : ""); + + TRACE("report id: %u\n", report.ID()); +} + + +void +TabletProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, + ProtocolHandler *&handlerList) +{ + 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: + // NOTE: Maybe it is supported if X-axis and Y-axis are + // absolute. This is determined below by scanning the + // report items for absolute X and Y axis. + 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: + TRACE("found tablet/digitizer\n"); + supported = true; + break; + } + + break; + } + } + + if (!supported) { + TRACE("collection not a tablet/digitizer\n"); + return; + } + + HIDParser &parser = device.Parser(); + uint32 maxReportCount = parser.CountReports(HID_REPORT_TYPE_INPUT); + if (maxReportCount == 0) + return; + + uint32 inputReportCount = 0; + HIDReport *inputReports[maxReportCount]; + collection.BuildReportList(HID_REPORT_TYPE_INPUT, inputReports, + inputReportCount); + + for (uint32 i = 0; i < inputReportCount; i++) { + HIDReport *inputReport = inputReports[i]; + + // try to find at least an absolute x and y axis + HIDReportItem *xAxis = inputReport->FindItem( + B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); + if (xAxis == NULL || xAxis->Relative()) + continue; + + HIDReportItem *yAxis = inputReport->FindItem( + B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y); + if (yAxis == NULL || yAxis->Relative()) + continue; + + ProtocolHandler *newHandler = new(std::nothrow) TabletProtocolHandler( + *inputReport, *xAxis, *yAxis); + if (newHandler == NULL) { + TRACE("failed to allocated tablet protocol handler\n"); + continue; + } + + newHandler->SetNextHandler(handlerList); + handlerList = newHandler; + } +} + + +status_t +TabletProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, + size_t length) +{ + switch (op) { + case MS_READ: + { + if (length < sizeof(tablet_movement)) + return B_BUFFER_OVERFLOW; + + while (true) { + status_t result = _ReadReport(buffer); + if (result != B_INTERRUPTED) + return result; + } + } + + case MS_NUM_EVENTS: + { + if (fReport.Device()->IsRemoved()) + return B_DEV_NOT_READY; + + // we are always on demand, so 0 queued events + return 0; + } + + case MS_SET_CLICKSPEED: +#ifdef __HAIKU__ + return user_memcpy(&fClickSpeed, buffer, sizeof(bigtime_t)); +#else + fClickSpeed = *(bigtime_t *)buffer; + return B_OK; +#endif + } + + return B_ERROR; +} + + +status_t +TabletProtocolHandler::_ReadReport(void *buffer) +{ + status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT); + if (result != B_OK) { + if (fReport.Device()->IsRemoved()) { + TRACE("device has been removed\n"); + return B_DEV_NOT_READY; + } + + 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_INTERRUPTED; + } + + float axisAbsoluteData[2]; + axisAbsoluteData[0] = 0.0f; + axisAbsoluteData[1] = 0.0f; + + if (fXAxis.Extract() == B_OK && fXAxis.Valid()) + axisAbsoluteData[0] = fXAxis.ScaledFloatData(); + + if (fYAxis.Extract() == B_OK && fYAxis.Valid()) + axisAbsoluteData[1] = fYAxis.ScaledFloatData(); + + uint32 wheelData = 0; + if (fWheel != NULL && fWheel->Extract() == B_OK && fWheel->Valid()) + 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()) + buttons |= (button->Data() & 1) << (button->UsageID() - 1); + } + + float pressure = 1.0f; + if (fPressure != NULL && fPressure->Extract() == B_OK + && fPressure->Valid()) { + pressure = fPressure->ScaledFloatData(); + } + + float xTilt = 0.0f; + if (fXTilt != NULL && fXTilt->Extract() == B_OK && fXTilt->Valid()) + xTilt = fXTilt->ScaledFloatData(); + + float yTilt = 0.0f; + if (fXTilt != NULL && fYTilt->Extract() == B_OK && fYTilt->Valid()) + yTilt = fYTilt->ScaledFloatData(); + + bool inRange = true; + if (fRange != NULL) + inRange = fRange->Extract() == B_OK && fRange->Valid(); + + bool eraser = false; + if (fEraser != NULL && fEraser->Extract() == B_OK && fEraser->Valid()) + eraser = (fEraser->Data() & 1) != 0; + + fReport.DoneProcessing(); + TRACE("got tablet report\n"); + + int32 clicks = 0; + bigtime_t timestamp = system_time(); + if (buttons != 0) { + if (fLastButtons == 0) { + if (fLastClickTime + fClickSpeed > timestamp) + fClickCount++; + else + fClickCount = 1; + } + + fLastClickTime = timestamp; + clicks = fClickCount; + } + + fLastButtons = buttons; + + tablet_movement *info = (tablet_movement *)buffer; + memset(info, 0, sizeof(tablet_movement)); + + info->xpos = axisAbsoluteData[0]; + info->ypos = axisAbsoluteData[1]; + info->has_contact = inRange; + info->pressure = pressure; + info->eraser = eraser; + info->tilt_x = xTilt; + info->tilt_y = yTilt; + + info->buttons = buttons; + info->clicks = clicks; + info->timestamp = timestamp; + info->wheel_ydelta = -wheelData; + + return B_OK; +} diff --git a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h new file mode 100644 index 0000000..342a466 --- /dev/null +++ b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Stephan Aßmus <superstippi@xxxxxx> + * Copyright 2010-2011 Enrique Medina Gremaldos <quiqueiii@xxxxxxxxx> + * Copyright 2008-2011 Michael Lotz <mmlr@xxxxxxxx> + * Distributed under the terms of the MIT license. + */ +#ifndef USB_TABLET_PROTOCOL_HANDLER_H +#define USB_TABLET_PROTOCOL_HANDLER_H + + +#include <InterfaceDefs.h> + +#include "ProtocolHandler.h" + + +class HIDCollection; +class HIDReportItem; + + +#ifndef B_MAX_MOUSE_BUTTONS +# define B_MAX_MOUSE_BUTTONS 8 +#endif + + +class TabletProtocolHandler : public ProtocolHandler { +public: + TabletProtocolHandler(HIDReport &report, + HIDReportItem &xAxis, + HIDReportItem &yAxis); + + static void AddHandlers(HIDDevice &device, + HIDCollection &collection, + ProtocolHandler *&handlerList); + + virtual status_t Control(uint32 *cookie, uint32 op, void *buffer, + size_t length); + +private: + status_t _ReadReport(void *buffer); + + HIDReport & fReport; + + HIDReportItem & fXAxis; + HIDReportItem & fYAxis; + HIDReportItem * fWheel; + HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS]; + + HIDReportItem * fPressure; + HIDReportItem * fRange; + HIDReportItem * fTip; + HIDReportItem * fBarrelSwitch; + HIDReportItem * fEraser; + HIDReportItem * fXTilt; + HIDReportItem * fYTilt; + + uint32 fLastButtons; + uint32 fClickCount; + bigtime_t fLastClickTime; + bigtime_t fClickSpeed; +}; + +#endif // USB_TABLET_PROTOCOL_HANDLER_H