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 <pulkomandy@gmail.com>
This commit is contained in:
Lt-Henry 2020-05-11 23:58:16 +02:00 committed by Adrien Destugues
parent 20719db962
commit 52a54e1b51
4 changed files with 59 additions and 27 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;