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 <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
20719db962
commit
52a54e1b51
@@ -98,14 +98,21 @@ typedef struct {
|
|||||||
} mouse_movement;
|
} 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 {
|
typedef struct {
|
||||||
uint32 buttons;
|
uint32 buttons;
|
||||||
|
uint32 switches;
|
||||||
float xpos;
|
float xpos;
|
||||||
float ypos;
|
float ypos;
|
||||||
bool has_contact;
|
bool has_contact;
|
||||||
float pressure;
|
float pressure;
|
||||||
int32 clicks;
|
int32 clicks;
|
||||||
bool eraser;
|
|
||||||
bigtime_t timestamp;
|
bigtime_t timestamp;
|
||||||
int32 wheel_ydelta;
|
int32 wheel_ydelta;
|
||||||
int32 wheel_xdelta;
|
int32 wheel_xdelta;
|
||||||
|
|||||||
@@ -327,6 +327,10 @@ TabletDevice::_ControlThread()
|
|||||||
if (movements.has_contact) {
|
if (movements.has_contact) {
|
||||||
// Send single messages for each event
|
// 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;
|
uint32 buttons = lastButtons ^ movements.buttons;
|
||||||
if (buttons != 0) {
|
if (buttons != 0) {
|
||||||
bool pressedButton = (buttons & movements.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_x", movements.xpos);
|
||||||
message->AddFloat("be:tablet_y", movements.ypos);
|
message->AddFloat("be:tablet_y", movements.ypos);
|
||||||
message->AddFloat("be:tablet_pressure", movements.pressure);
|
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) {
|
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_x", movements.tilt_x);
|
||||||
message->AddFloat("be:tablet_tilt_y", movements.tilt_y);
|
message->AddFloat("be:tablet_tilt_y", movements.tilt_y);
|
||||||
|
|||||||
@@ -37,19 +37,19 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report,
|
|||||||
fWheel(NULL),
|
fWheel(NULL),
|
||||||
|
|
||||||
fPressure(NULL),
|
fPressure(NULL),
|
||||||
fRange(NULL),
|
fInRange(NULL),
|
||||||
fTip(NULL),
|
|
||||||
fBarrelSwitch(NULL),
|
|
||||||
fEraser(NULL),
|
|
||||||
fXTilt(NULL),
|
fXTilt(NULL),
|
||||||
fYTilt(NULL),
|
fYTilt(NULL),
|
||||||
|
|
||||||
fLastButtons(0),
|
fLastButtons(0),
|
||||||
|
fLastSwitches(0),
|
||||||
fClickCount(0),
|
fClickCount(0),
|
||||||
fLastClickTime(0),
|
fLastClickTime(0),
|
||||||
fClickSpeed(250000)
|
fClickSpeed(250000)
|
||||||
{
|
{
|
||||||
uint32 buttonCount = 0;
|
uint32 buttonCount = 0;
|
||||||
|
uint32 switchCount = 0;
|
||||||
|
|
||||||
for (uint32 i = 0; i < report.CountItems(); i++) {
|
for (uint32 i = 0; i < report.CountItems(); i++) {
|
||||||
HIDReportItem *item = report.ItemAt(i);
|
HIDReportItem *item = report.ItemAt(i);
|
||||||
if (!item->HasData())
|
if (!item->HasData())
|
||||||
@@ -59,9 +59,16 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report,
|
|||||||
&& item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS) {
|
&& item->UsageID() - 1 < B_MAX_MOUSE_BUTTONS) {
|
||||||
fButtons[buttonCount++] = item;
|
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;
|
fButtons[buttonCount] = NULL;
|
||||||
|
fSwitches[switchCount] = NULL;
|
||||||
|
|
||||||
fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP,
|
fWheel = report.FindItem(B_HID_USAGE_PAGE_GENERIC_DESKTOP,
|
||||||
B_HID_UID_GD_WHEEL);
|
B_HID_UID_GD_WHEEL);
|
||||||
@@ -69,29 +76,19 @@ TabletProtocolHandler::TabletProtocolHandler(HIDReport &report,
|
|||||||
fPressure = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
|
fPressure = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
|
||||||
B_HID_UID_DIG_TIP_PRESSURE);
|
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);
|
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,
|
fXTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
|
||||||
B_HID_UID_DIG_X_TILT);
|
B_HID_UID_DIG_X_TILT);
|
||||||
|
|
||||||
fYTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
|
fYTilt = report.FindItem(B_HID_USAGE_PAGE_DIGITIZER,
|
||||||
B_HID_UID_DIG_Y_TILT);
|
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",
|
"%spressure, and %stilt\n",
|
||||||
buttonCount,
|
buttonCount,
|
||||||
fTip == NULL ? "no " : "",
|
switchCount,
|
||||||
fEraser == NULL ? "no " : "",
|
|
||||||
fPressure == NULL ? "no " : "",
|
fPressure == NULL ? "no " : "",
|
||||||
fXTilt == NULL && fYTilt == NULL ? "no " : "");
|
fXTilt == NULL && fYTilt == NULL ? "no " : "");
|
||||||
|
|
||||||
@@ -275,6 +272,17 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
|||||||
buttons |= (button->Data() & 1) << (button->UsageID() - 1);
|
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;
|
float pressure = 1.0f;
|
||||||
if (fPressure != NULL && fPressure->Extract() == B_OK
|
if (fPressure != NULL && fPressure->Extract() == B_OK
|
||||||
&& fPressure->Valid()) {
|
&& fPressure->Valid()) {
|
||||||
@@ -290,12 +298,8 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
|||||||
yTilt = fYTilt->ScaledFloatData();
|
yTilt = fYTilt->ScaledFloatData();
|
||||||
|
|
||||||
bool inRange = true;
|
bool inRange = true;
|
||||||
if (fRange != NULL && fRange->Extract() == B_OK && fRange->Valid())
|
if (fInRange != NULL && fInRange->Extract() == B_OK && fInRange->Valid())
|
||||||
inRange = ((fRange->Data() & 1) != 0);
|
inRange = ((fInRange->Data() & 1) != 0);
|
||||||
|
|
||||||
bool eraser = false;
|
|
||||||
if (fEraser != NULL && fEraser->Extract() == B_OK && fEraser->Valid())
|
|
||||||
eraser = ((fEraser->Data() & 1) != 0);
|
|
||||||
|
|
||||||
fReport.DoneProcessing();
|
fReport.DoneProcessing();
|
||||||
TRACE("got tablet report\n");
|
TRACE("got tablet report\n");
|
||||||
@@ -316,6 +320,17 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
|||||||
|
|
||||||
fLastButtons = buttons;
|
fLastButtons = buttons;
|
||||||
|
|
||||||
|
if (switches != 0) {
|
||||||
|
if (fLastSwitches == 0) {
|
||||||
|
if (fLastClickTime + fClickSpeed > timestamp)
|
||||||
|
fClickCount++;
|
||||||
|
else
|
||||||
|
fClickCount = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fLastSwitches = switches;
|
||||||
|
|
||||||
tablet_movement *info = (tablet_movement *)buffer;
|
tablet_movement *info = (tablet_movement *)buffer;
|
||||||
memset(info, 0, sizeof(tablet_movement));
|
memset(info, 0, sizeof(tablet_movement));
|
||||||
|
|
||||||
@@ -323,10 +338,10 @@ TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
|||||||
info->ypos = axisAbsoluteData[1];
|
info->ypos = axisAbsoluteData[1];
|
||||||
info->has_contact = inRange;
|
info->has_contact = inRange;
|
||||||
info->pressure = pressure;
|
info->pressure = pressure;
|
||||||
info->eraser = eraser;
|
|
||||||
info->tilt_x = xTilt;
|
info->tilt_x = xTilt;
|
||||||
info->tilt_y = yTilt;
|
info->tilt_y = yTilt;
|
||||||
|
|
||||||
|
info->switches = switches;
|
||||||
info->buttons = buttons;
|
info->buttons = buttons;
|
||||||
info->clicks = clicks;
|
info->clicks = clicks;
|
||||||
info->timestamp = timestamp;
|
info->timestamp = timestamp;
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class HIDReportItem;
|
|||||||
# define B_MAX_MOUSE_BUTTONS 8
|
# define B_MAX_MOUSE_BUTTONS 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef B_MAX_DIGITIZER_SWITCHES
|
||||||
|
#define B_MAX_DIGITIZER_SWITCHES 5
|
||||||
|
#endif
|
||||||
|
|
||||||
class TabletProtocolHandler : public ProtocolHandler {
|
class TabletProtocolHandler : public ProtocolHandler {
|
||||||
public:
|
public:
|
||||||
@@ -44,9 +47,10 @@ private:
|
|||||||
HIDReportItem & fYAxis;
|
HIDReportItem & fYAxis;
|
||||||
HIDReportItem * fWheel;
|
HIDReportItem * fWheel;
|
||||||
HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
|
HIDReportItem * fButtons[B_MAX_MOUSE_BUTTONS];
|
||||||
|
HIDReportItem * fSwitches[B_MAX_DIGITIZER_SWITCHES];
|
||||||
|
|
||||||
HIDReportItem * fPressure;
|
HIDReportItem * fPressure;
|
||||||
HIDReportItem * fRange;
|
HIDReportItem * fInRange;
|
||||||
HIDReportItem * fTip;
|
HIDReportItem * fTip;
|
||||||
HIDReportItem * fBarrelSwitch;
|
HIDReportItem * fBarrelSwitch;
|
||||||
HIDReportItem * fEraser;
|
HIDReportItem * fEraser;
|
||||||
@@ -54,6 +58,7 @@ private:
|
|||||||
HIDReportItem * fYTilt;
|
HIDReportItem * fYTilt;
|
||||||
|
|
||||||
uint32 fLastButtons;
|
uint32 fLastButtons;
|
||||||
|
uint32 fLastSwitches;
|
||||||
uint32 fClickCount;
|
uint32 fClickCount;
|
||||||
bigtime_t fLastClickTime;
|
bigtime_t fLastClickTime;
|
||||||
bigtime_t fClickSpeed;
|
bigtime_t fClickSpeed;
|
||||||
|
|||||||
Reference in New Issue
Block a user