[haiku-commits] haiku: hrev46015 - src/add-ons/kernel/drivers/input/usb_hid

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 3 Sep 2013 18:02:43 +0200 (CEST)

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


Other related posts: