From 52a54e1b511df470416490a917cafcca625187d5 Mon Sep 17 00:00:00 2001 From: Lt-Henry Date: Mon, 11 May 2020 23:58:16 +0200 Subject: [PATCH] usb_hid: Enable digitizers to produce button events from tip and barrel switches Change-Id: Ifcf542e6b04f2f210c80528279e70e0fdd1bb4e3 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2685 Reviewed-by: Adrien Destugues --- headers/private/input/keyboard_mouse_driver.h | 9 ++- .../devices/tablet/TabletInputDevice.cpp | 7 ++- .../input/usb_hid/TabletProtocolHandler.cpp | 63 ++++++++++++------- .../input/usb_hid/TabletProtocolHandler.h | 7 ++- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/headers/private/input/keyboard_mouse_driver.h b/headers/private/input/keyboard_mouse_driver.h index 99306fd715..a93f37e4b1 100644 --- a/headers/private/input/keyboard_mouse_driver.h +++ b/headers/private/input/keyboard_mouse_driver.h @@ -98,14 +98,21 @@ typedef struct { } mouse_movement; +#define B_TIP_SWITCH 0x01 +#define B_SECONDARY_TIP_SWITCH 0x02 +#define B_BARREL_SWITCH 0x04 +#define B_ERASER 0x08 +#define B_TABLET_PICK 0x0F + + typedef struct { uint32 buttons; + uint32 switches; float xpos; float ypos; bool has_contact; float pressure; int32 clicks; - bool eraser; bigtime_t timestamp; int32 wheel_ydelta; int32 wheel_xdelta; diff --git a/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp b/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp index f5965d4149..439da1a455 100644 --- a/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp +++ b/src/add-ons/input_server/devices/tablet/TabletInputDevice.cpp @@ -327,6 +327,10 @@ TabletDevice::_ControlThread() if (movements.has_contact) { // Send single messages for each event + movements.buttons |= (movements.switches & B_TIP_SWITCH); + movements.buttons |= (movements.switches & B_BARREL_SWITCH) >> 1; + bool eraser = (movements.switches & B_ERASER) != 0; + uint32 buttons = lastButtons ^ movements.buttons; if (buttons != 0) { bool pressedButton = (buttons & movements.buttons) > 0; @@ -355,7 +359,8 @@ TabletDevice::_ControlThread() message->AddFloat("be:tablet_x", movements.xpos); message->AddFloat("be:tablet_y", movements.ypos); message->AddFloat("be:tablet_pressure", movements.pressure); - message->AddInt32("be:tablet_eraser", movements.eraser); + message->AddInt32("be:tablet_eraser", eraser); + if (movements.tilt_x != 0.0 || movements.tilt_y != 0.0) { message->AddFloat("be:tablet_tilt_x", movements.tilt_x); message->AddFloat("be:tablet_tilt_y", movements.tilt_y); diff --git a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp index ff17a51ae3..15fc249bee 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.cpp @@ -37,19 +37,19 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report, fWheel(NULL), fPressure(NULL), - fRange(NULL), - fTip(NULL), - fBarrelSwitch(NULL), - fEraser(NULL), + fInRange(NULL), fXTilt(NULL), fYTilt(NULL), fLastButtons(0), + fLastSwitches(0), fClickCount(0), fLastClickTime(0), fClickSpeed(250000) { uint32 buttonCount = 0; + uint32 switchCount = 0; + for (uint32 i = 0; i < report.CountItems(); i++) { HIDReportItem *item = report.ItemAt(i); if (!item->HasData()) @@ -59,9 +59,16 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report, && item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS) { fButtons[buttonCount++] = item; } + + if (item->UsagePage() == B_HID_USAGE_PAGE_DIGITIZER + && item->UsageID() >= B_HID_UID_DIG_TIP_SWITCH + && item->UsageID() <= B_HID_UID_DIG_TABLET_PICK) { + fSwitches[switchCount++] = item; + } } fButtons[buttonCount] = NULL; + fSwitches[switchCount] = NULL; fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_WHEEL); @@ -69,17 +76,8 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report, fPressure = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, B_HID_UID_DIG_TIP_PRESSURE); - fRange = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, + fInRange = 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); @@ -87,11 +85,10 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report, fYTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER, B_HID_UID_DIG_Y_TILT); - TRACE("tablet device with %" B_PRIu32 " buttons, %stip, %seraser, " + TRACE("tablet device with %" B_PRIu32 " buttons, %" B_PRIu32 " switches," "%spressure, and %stilt\n", buttonCount, - fTip == NULL ? "no " : "", - fEraser == NULL ? "no " : "", + switchCount, fPressure == NULL ? "no " : "", fXTilt == NULL && fYTilt == NULL ? "no " : ""); @@ -275,6 +272,17 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie) buttons |= (button->Data() & 1) << (button->UsageID() - 1); } + uint32 switches = 0; + for (uint32 i = 0; i < B_MAX_DIGITIZER_SWITCHES; i++) { + HIDReportItem *dswitch = fSwitches[i]; + if (dswitch == NULL) + break; + + if (dswitch->Extract() == B_OK && dswitch->Valid()) + switches |= (dswitch->Data() & 1) << (dswitch->UsageID() + - B_HID_UID_DIG_TIP_SWITCH); + } + float pressure = 1.0f; if (fPressure != NULL && fPressure->Extract() == B_OK && fPressure->Valid()) { @@ -290,12 +298,8 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie) yTilt = fYTilt->ScaledFloatData(); bool inRange = true; - if (fRange != NULL && fRange->Extract() == B_OK && fRange->Valid()) - inRange = ((fRange->Data() & 1) != 0); - - bool eraser = false; - if (fEraser != NULL && fEraser->Extract() == B_OK && fEraser->Valid()) - eraser = ((fEraser->Data() & 1) != 0); + if (fInRange != NULL && fInRange->Extract() == B_OK && fInRange->Valid()) + inRange = ((fInRange->Data() & 1) != 0); fReport.DoneProcessing(); TRACE("got tablet report\n"); @@ -316,6 +320,17 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie) fLastButtons = buttons; + if (switches != 0) { + if (fLastSwitches == 0) { + if (fLastClickTime + fClickSpeed > timestamp) + fClickCount++; + else + fClickCount = 1; + } + } + + fLastSwitches = switches; + tablet_movement *info = (tablet_movement *)buffer; memset(info, 0, sizeof(tablet_movement)); @@ -323,10 +338,10 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie) info->ypos = axisAbsoluteData[1]; info->has_contact = inRange; info->pressure = pressure; - info->eraser = eraser; info->tilt_x = xTilt; info->tilt_y = yTilt; + info->switches = switches; info->buttons = buttons; info->clicks = clicks; info->timestamp = timestamp; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h index 55a81bc531..bbce9615f1 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/TabletProtocolHandler.h @@ -21,6 +21,9 @@ class HIDReportItem; # define B_MAX_MOUSE_BUTTONS 8 #endif +#ifndef B_MAX_DIGITIZER_SWITCHES + #define B_MAX_DIGITIZER_SWITCHES 5 +#endif class TabletProtocolHandler : public ProtocolHandler { public: @@ -44,9 +47,10 @@ private: HIDReportItem & fYAxis; HIDReportItem * fWheel; HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS]; + HIDReportItem * fSwitches[B_MAX_DIGITIZER_SWITCHES]; HIDReportItem * fPressure; - HIDReportItem * fRange; + HIDReportItem * fInRange; HIDReportItem * fTip; HIDReportItem * fBarrelSwitch; HIDReportItem * fEraser; @@ -54,6 +58,7 @@ private: HIDReportItem * fYTilt; uint32 fLastButtons; + uint32 fLastSwitches; uint32 fClickCount; bigtime_t fLastClickTime; bigtime_t fClickSpeed;