Refactor touchpad movement generation by migrating MovementMaker to userland.

This considerably overhauls touchpad event generation, simplifying and
cleaning it up considerably:

 * Return the touchpad specifications through the MS_IS_TOUCHPAD ioctl.

 * There is now a dedicated MS_READ_TOUCHPAD ioctl, as touchpads
   can either return touchpad_movement structures or mouse_movement
   ones depending on what mode they are operating in.

 * Event repeating on timeouts is now handled in MovementMaker and
   the input_server control thread, so MS_READ_TOUCHPAD takes
   a timeout value. This means we can drop all the EventProducers.

 * Use the real floating-point math functions in MovementMaker now
   that we are running in userland.

 * Drop unused structures, constants, headers, and other things
   related to touchpad support.

Change-Id: I28cdb28e4100393a9338a8ebb865573cec13fc1e
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5455
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2022-07-18 16:00:29 +00:00
committed by waddlesplash
parent 1f26a521ac
commit 5e596efecf
16 changed files with 363 additions and 725 deletions
@@ -32,6 +32,7 @@ enum {
B_MOUSE_SPEED_CHANGED, B_MOUSE_SPEED_CHANGED,
B_CLICK_SPEED_CHANGED, B_CLICK_SPEED_CHANGED,
B_MOUSE_ACCELERATION_CHANGED, B_MOUSE_ACCELERATION_CHANGED,
B_SET_TOUCHPAD_SETTINGS,
}; };
namespace BPrivate { namespace BPrivate {
+29 -2
View File
@@ -62,8 +62,9 @@ enum {
MS_GET_CLICKSPEED, MS_GET_CLICKSPEED,
MS_SET_CLICKSPEED, MS_SET_CLICKSPEED,
MS_NUM_SERIAL_MICE, MS_NUM_SERIAL_MICE,
MS_IS_TOUCHPAD, MS_IS_TOUCHPAD,
MS_SET_TOUCHPAD_SETTINGS, MS_READ_TOUCHPAD,
IIC_WRITE = B_DEVICE_OP_CODES_END + 200, IIC_WRITE = B_DEVICE_OP_CODES_END + 200,
RESTART_SYSTEM, RESTART_SYSTEM,
@@ -127,6 +128,22 @@ typedef struct {
#define B_PEN 0x08 #define B_PEN 0x08
typedef struct {
uint16 edgeMotionWidth;
uint16 width;
uint16 areaStartX;
uint16 areaEndX;
uint16 areaStartY;
uint16 areaEndY;
uint16 minPressure;
// the value you reach when you hammer really hard on the touchpad
uint16 realMaxPressure;
uint16 maxPressure;
} touchpad_specs;
typedef struct { typedef struct {
uint8 buttons; uint8 buttons;
uint32 xPosition; uint32 xPosition;
@@ -137,8 +154,18 @@ typedef struct {
uint8 fingerWidth; uint8 fingerWidth;
// 1 - 4 normal width // 1 - 4 normal width
// 5 - 11 very wide finger or palm // 5 - 11 very wide finger or palm
// 12 maximum reportable width; extrem wide contact // 12 maximum reportable width; extreme wide contact
} touchpad_movement; } touchpad_movement;
typedef struct {
bigtime_t timeout;
int32 event;
union {
touchpad_movement touchpad;
mouse_movement mouse;
} u;
} touchpad_read;
#endif // _KB_MOUSE_DRIVER_H #endif // _KB_MOUSE_DRIVER_H
-38
View File
@@ -1,38 +0,0 @@
//
// kb_mouse_driver.h
//
#ifndef _TOUCHPAD_DRIVER_H
#define _TOUCHPAD_DRIVER_H
#include <SupportDefs.h>
#include <Drivers.h>
#ifdef __cplusplus
extern "C" {
#endif
#define B_ONE_FINGER 0x01
#define B_TWO_FINGER 0x02
#define B_MULTI_FINGER 0x04
#define B_PEN 0x08
typedef struct {
uint8 buttons;
uint32 xPosition;
uint32 yPosition;
uint8 zPressure;
uint8 fingers;
bool gesture;
uint8 fingerWidth;
// 1 - 4 normal width
// 5 - 11 very wide finger or palm
// 12 maximum reportable width; extrem wide contact
} touchpad_movement;
#ifdef __cplusplus
}
#endif
#endif
@@ -4,4 +4,5 @@ UsePrivateHeaders input shared ;
Addon <input>mouse : Addon <input>mouse :
MouseInputDevice.cpp MouseInputDevice.cpp
movement_maker.cpp
: be input_server [ TargetLibsupc++ ] ; : be input_server [ TargetLibsupc++ ] ;
@@ -34,6 +34,8 @@
#include <keyboard_mouse_driver.h> #include <keyboard_mouse_driver.h>
#include <touchpad_settings.h> #include <touchpad_settings.h>
#include "movement_maker.h"
#undef TRACE #undef TRACE
//#define TRACE_MOUSE_DEVICE //#define TRACE_MOUSE_DEVICE
@@ -120,8 +122,7 @@ private:
void _UpdateSettings(); void _UpdateSettings();
status_t _GetTouchpadSettingsPath(BPath& path); status_t _GetTouchpadSettingsPath(BPath& path);
status_t _ReadTouchpadSettingsMsg(BMessage* message); status_t _UpdateTouchpadSettings(BMessage* message);
status_t _UpdateTouchpadSettings();
BMessage* _BuildMouseMessage(uint32 what, BMessage* _BuildMouseMessage(uint32 what,
uint64 when, uint32 buttons, uint64 when, uint32 buttons,
@@ -147,7 +148,7 @@ private:
volatile bool fUpdateSettings; volatile bool fUpdateSettings;
bool fIsTouchpad; bool fIsTouchpad;
touchpad_settings fTouchpadSettings; TouchpadMovement fTouchpadMovementMaker;
BMessage* fTouchpadSettingsMessage; BMessage* fTouchpadSettingsMessage;
BLocker fTouchpadSettingsLock; BLocker fTouchpadSettingsLock;
}; };
@@ -367,22 +368,26 @@ MouseDevice::_ControlThread()
} }
// touchpad settings // touchpad settings
if (ioctl(fDevice, MS_IS_TOUCHPAD, NULL) == B_OK) { touchpad_specs touchpadSpecs;
if (ioctl(fDevice, MS_IS_TOUCHPAD, &touchpadSpecs, sizeof(touchpadSpecs)) == B_OK) {
TRACE("is touchpad %s\n", fPath.String()); TRACE("is touchpad %s\n", fPath.String());
fIsTouchpad = true; fIsTouchpad = true;
fTouchpadSettings = kDefaultTouchpadSettings; touchpad_settings settings;
settings = kDefaultTouchpadSettings;
BPath path; BPath path;
status_t status = _GetTouchpadSettingsPath(path); status_t status = _GetTouchpadSettingsPath(path);
BFile settingsFile(path.Path(), B_READ_ONLY); BFile settingsFile(path.Path(), B_READ_ONLY);
if (status == B_OK && settingsFile.InitCheck() == B_OK) { if (status == B_OK && settingsFile.InitCheck() == B_OK) {
if (settingsFile.Read(&fTouchpadSettings, sizeof(touchpad_settings)) if (settingsFile.Read(&settings, sizeof(touchpad_settings))
!= sizeof(touchpad_settings)) { != sizeof(touchpad_settings)) {
TRACE("failed to load settings\n"); TRACE("failed to load settings\n");
} }
} }
_UpdateTouchpadSettings();
fTouchpadMovementMaker.SetSpecs(touchpadSpecs);
fTouchpadMovementMaker.SetSettings(settings);
} }
_UpdateSettings(); _UpdateSettings();
@@ -398,6 +403,10 @@ MouseDevice::_ControlThread()
bigtime_t nextTransferTime = system_time() + kTransferDelay; bigtime_t nextTransferTime = system_time() + kTransferDelay;
#endif #endif
// touchpads only
touchpad_movement lastTouchpadMovement;
bigtime_t touchpadEventTimeout = B_INFINITE_TIMEOUT;
while (fActive) { while (fActive) {
mouse_movement movements; mouse_movement movements;
@@ -406,12 +415,41 @@ MouseDevice::_ControlThread()
nextTransferTime += kTransferDelay; nextTransferTime += kTransferDelay;
#endif #endif
if (!fIsTouchpad) {
if (ioctl(fDevice, MS_READ, &movements, sizeof(movements)) != B_OK) { if (ioctl(fDevice, MS_READ, &movements, sizeof(movements)) != B_OK) {
LOG_ERR("Mouse device exiting, %s\n", strerror(errno)); LOG_ERR("Mouse device exiting, %s\n", strerror(errno));
_ControlThreadCleanup(); _ControlThreadCleanup();
// TOAST! // TOAST!
return; return;
} }
} else {
touchpad_read read;
read.timeout = touchpadEventTimeout;
status_t status = ioctl(fDevice, MS_READ_TOUCHPAD, &read, sizeof(read));
if (status != B_OK && status != B_TIMED_OUT) {
LOG_ERR("Mouse device exiting, %s\n", strerror(errno));
_ControlThreadCleanup();
// TOAST!
return;
}
if (status == B_TIMED_OUT) {
read.event = MS_READ_TOUCHPAD;
read.u.touchpad = lastTouchpadMovement;
}
if (read.event == MS_READ_TOUCHPAD) {
lastTouchpadMovement = read.u.touchpad;
status = fTouchpadMovementMaker.EventToMovement(&read.u.touchpad,
&movements, touchpadEventTimeout);
} else if (read.event == MS_READ) {
movements = read.u.mouse;
touchpadEventTimeout = -1;
}
if (status != B_OK)
continue;
}
// take care of updating the settings first, if necessary // take care of updating the settings first, if necessary
if (fUpdateSettings) { if (fUpdateSettings) {
@@ -419,8 +457,7 @@ MouseDevice::_ControlThread()
if (fIsTouchpad) { if (fIsTouchpad) {
BAutolock _(fTouchpadSettingsLock); BAutolock _(fTouchpadSettingsLock);
if (fTouchpadSettingsMessage != NULL) { if (fTouchpadSettingsMessage != NULL) {
_ReadTouchpadSettingsMsg(fTouchpadSettingsMessage); _UpdateTouchpadSettings(fTouchpadSettingsMessage);
_UpdateTouchpadSettings();
delete fTouchpadSettingsMessage; delete fTouchpadSettingsMessage;
fTouchpadSettingsMessage = NULL; fTouchpadSettingsMessage = NULL;
} else } else
@@ -524,10 +561,12 @@ MouseDevice::_UpdateSettings()
= ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK; = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
} }
if (get_click_speed(&fSettings.click_speed) != B_OK) if (get_click_speed(&fSettings.click_speed) == B_OK) {
LOG_ERR("error when get_click_speed\n"); if (fIsTouchpad)
else fTouchpadMovementMaker.click_speed = fSettings.click_speed;
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed); ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
} else
LOG_ERR("error when get_click_speed\n");
if (get_mouse_speed(fDeviceRef.name, &fSettings.accel.speed) != B_OK) if (get_mouse_speed(fDeviceRef.name, &fSettings.accel.speed) != B_OK)
LOG_ERR("error when get_mouse_speed\n"); LOG_ERR("error when get_mouse_speed\n");
@@ -561,40 +600,33 @@ MouseDevice::_GetTouchpadSettingsPath(BPath& path)
status_t status_t
MouseDevice::_ReadTouchpadSettingsMsg(BMessage* message) MouseDevice::_UpdateTouchpadSettings(BMessage* message)
{ {
message->FindBool("scroll_twofinger", &fTouchpadSettings.scroll_twofinger); touchpad_settings settings;
message->FindBool("scroll_twofinger", &settings.scroll_twofinger);
message->FindBool("scroll_twofinger_horizontal", message->FindBool("scroll_twofinger_horizontal",
&fTouchpadSettings.scroll_twofinger_horizontal); &settings.scroll_twofinger_horizontal);
message->FindFloat("scroll_rightrange", message->FindFloat("scroll_rightrange",
&fTouchpadSettings.scroll_rightrange); &settings.scroll_rightrange);
message->FindFloat("scroll_bottomrange", message->FindFloat("scroll_bottomrange",
&fTouchpadSettings.scroll_bottomrange); &settings.scroll_bottomrange);
message->FindInt16("scroll_xstepsize", message->FindInt16("scroll_xstepsize",
(int16*)&fTouchpadSettings.scroll_xstepsize); (int16*)&settings.scroll_xstepsize);
message->FindInt16("scroll_ystepsize", message->FindInt16("scroll_ystepsize",
(int16*)&fTouchpadSettings.scroll_ystepsize); (int16*)&settings.scroll_ystepsize);
message->FindInt8("scroll_acceleration", message->FindInt8("scroll_acceleration",
(int8*)&fTouchpadSettings.scroll_acceleration); (int8*)&settings.scroll_acceleration);
message->FindInt8("tapgesture_sensibility", message->FindInt8("tapgesture_sensibility",
(int8*)&fTouchpadSettings.tapgesture_sensibility); (int8*)&settings.tapgesture_sensibility);
if (fIsTouchpad)
fTouchpadMovementMaker.SetSettings(settings);
return B_OK; return B_OK;
} }
status_t
MouseDevice::_UpdateTouchpadSettings()
{
if (fIsTouchpad) {
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
return B_OK;
}
return B_ERROR;
}
BMessage* BMessage*
MouseDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons, MouseDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
int32 deltaX, int32 deltaY) const int32 deltaX, int32 deltaY) const
@@ -748,7 +780,7 @@ MouseInputDevice::Control(const char* name, void* cookie,
if (command == B_NODE_MONITOR) if (command == B_NODE_MONITOR)
return _HandleMonitor(message); return _HandleMonitor(message);
if (command == MS_SET_TOUCHPAD_SETTINGS) if (command == B_SET_TOUCHPAD_SETTINGS)
return device->UpdateTouchpadSettings(message); return device->UpdateTouchpadSettings(message);
if (command >= B_MOUSE_TYPE_CHANGED if (command >= B_MOUSE_TYPE_CHANGED
@@ -1,6 +1,12 @@
/*
* Copyright 2008-2011, Clemens Zeidler <haiku@clemens-zeidler.de>
* Copyright 2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "movement_maker.h" #include "movement_maker.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include <KernelExport.h> #include <KernelExport.h>
@@ -13,160 +19,9 @@
#endif #endif
typedef union { // magic constants
float value; #define SYN_WIDTH (4100)
/* FIXME: Assumes 32 bit int. */ #define SYN_HEIGHT (3140)
unsigned int word;
} ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define GET_FLOAT_WORD(i,d) \
do { \
ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
} while (0)
/* Set a float from a 32 bit int. */
#define SET_FLOAT_WORD(d,i) \
do { \
ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
} while (0)
static const float huge = 1.0e30;
float
floorf(float x)
{
int32 i0,j0;
uint32 i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if (j0<23) {
if (j0<0) { /* raise inexact if x != 0 */
if (huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if (i0>=0) {i0=0;}
else if ((i0&0x7fffffff)!=0)
{ i0=0xbf800000;}
}
} else {
i = (0x007fffff)>>j0;
if ((i0&i)==0) return x; /* x is integral */
if (huge+x>(float)0.0) { /* raise inexact flag */
if (i0<0) i0 += (0x00800000)>>j0;
i0 &= (~i);
}
}
} else {
if (j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
float
ceilf(float x)
{
int32 i0,j0;
uint32 i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if (j0<23) {
if (j0<0) { /* raise inexact if x != 0 */
if (huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if (i0<0) {i0=0x80000000;}
else if (i0!=0) { i0=0x3f800000;}
}
} else {
i = (0x007fffff)>>j0;
if ((i0&i)==0) return x; /* x is integral */
if (huge+x>(float)0.0) { /* raise inexact flag */
if (i0>0) i0 += (0x00800000)>>j0;
i0 &= (~i);
}
}
} else {
if (j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
static const float one = 1.0, tiny=1.0e-30;
float
sqrtf(float x)
{
float z;
int32 sign = (int)0x80000000;
int32 ix,s,q,m,t,i;
uint32 r;
GET_FLOAT_WORD(ix,x);
/* take care of Inf and NaN */
if ((ix&0x7f800000)==0x7f800000) {
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
sqrt(-inf)=sNaN */
}
/* take care of zero */
if (ix<=0) {
if ((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
else if (ix<0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix>>23);
if (m==0) { /* subnormal x */
for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
m -= i-1;
}
m -= 127; /* unbias exponent */
ix = (ix&0x007fffff)|0x00800000;
if (m&1) /* odd m, double x to make it even */
ix += ix;
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix += ix;
q = s = 0; /* q = sqrt(x) */
r = 0x01000000; /* r = moving bit from right to left */
while(r!=0) {
t = s+r;
if (t<=ix) {
s = t+r;
ix -= t;
q += r;
}
ix += ix;
r>>=1;
}
/* use floating add to find out rounding direction */
if (ix!=0) {
z = one-tiny; /* trigger inexact flag */
if (z>=one) {
z = one+tiny;
if (z>one)
q += 2;
else
q += (q&1);
}
}
ix = (q>>1)+0x3f000000;
ix += (m <<23);
SET_FLOAT_WORD(z,ix);
return z;
}
static int32 static int32
@@ -179,21 +34,20 @@ make_small(float value)
} }
void void
MovementMaker::SetSettings(touchpad_settings* settings) MovementMaker::SetSettings(const touchpad_settings& settings)
{ {
fSettings = settings; fSettings = settings;
} }
void void
MovementMaker::SetSpecs(hardware_specs* specs) MovementMaker::SetSpecs(const touchpad_specs& specs)
{ {
fSpecs = specs; fSpecs = specs;
fAreaWidth = fSpecs->areaEndX - fSpecs->areaStartX; fAreaWidth = fSpecs.areaEndX - fSpecs.areaStartX;
fAreaHeight = fSpecs->areaEndY - fSpecs->areaStartY; fAreaHeight = fSpecs.areaEndY - fSpecs.areaStartY;
// calibrated on the synaptics touchpad // calibrated on the synaptics touchpad
fSpeed = SYN_WIDTH / fAreaWidth; fSpeed = SYN_WIDTH / fAreaWidth;
@@ -204,10 +58,10 @@ MovementMaker::SetSpecs(hardware_specs* specs)
void void
MovementMaker::StartNewMovment() MovementMaker::StartNewMovment()
{ {
if (fSettings->scroll_xstepsize <= 0) if (fSettings.scroll_xstepsize <= 0)
fSettings->scroll_xstepsize = 1; fSettings.scroll_xstepsize = 1;
if (fSettings->scroll_ystepsize <= 0) if (fSettings.scroll_ystepsize <= 0)
fSettings->scroll_ystepsize = 1; fSettings.scroll_ystepsize = 1;
fMovementMakerStarted = true; fMovementMakerStarted = true;
scrolling_x = 0; scrolling_x = 0;
@@ -228,25 +82,25 @@ MovementMaker::GetScrolling(uint32 posX, uint32 posY)
int32 stepsX = 0, stepsY = 0; int32 stepsX = 0, stepsY = 0;
_GetRawMovement(posX, posY); _GetRawMovement(posX, posY);
_ComputeAcceleration(fSettings->scroll_acceleration); _ComputeAcceleration(fSettings.scroll_acceleration);
if (fSettings->scroll_xstepsize > 0) { if (fSettings.scroll_xstepsize > 0) {
scrolling_x += xDelta; scrolling_x += xDelta;
stepsX = make_small(scrolling_x / fSettings->scroll_xstepsize); stepsX = make_small(scrolling_x / fSettings.scroll_xstepsize);
scrolling_x -= stepsX * fSettings->scroll_xstepsize; scrolling_x -= stepsX * fSettings.scroll_xstepsize;
xDelta = stepsX; xDelta = stepsX;
} else { } else {
scrolling_x = 0; scrolling_x = 0;
xDelta = 0; xDelta = 0;
} }
if (fSettings->scroll_ystepsize > 0) { if (fSettings.scroll_ystepsize > 0) {
scrolling_y += yDelta; scrolling_y += yDelta;
stepsY = make_small(scrolling_y / fSettings->scroll_ystepsize); stepsY = make_small(scrolling_y / fSettings.scroll_ystepsize);
scrolling_y -= stepsY * fSettings->scroll_ystepsize; scrolling_y -= stepsY * fSettings.scroll_ystepsize;
yDelta = -1 * stepsY; yDelta = -1 * stepsY;
} else { } else {
scrolling_y = 0; scrolling_y = 0;
@@ -326,7 +180,6 @@ MovementMaker::_GetRawMovement(uint32 posX, uint32 posY)
} }
void void
MovementMaker::_ComputeAcceleration(int8 accel_factor) MovementMaker::_ComputeAcceleration(int8 accel_factor)
{ {
@@ -348,8 +201,7 @@ MovementMaker::_ComputeAcceleration(int8 accel_factor)
#define fTapTimeOUT 200000 #define fTapTimeOUT 200000
void TouchpadMovement::TouchpadMovement()
TouchpadMovement::Init()
{ {
fMovementStarted = false; fMovementStarted = false;
fScrollingStarted = false; fScrollingStarted = false;
@@ -360,7 +212,8 @@ TouchpadMovement::Init()
status_t status_t
TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement) TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement* movement,
bigtime_t& repeatTimeout)
{ {
if (!movement) if (!movement)
return B_ERROR; return B_ERROR;
@@ -391,10 +244,10 @@ TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement)
fValidEdgeMotion = false; fValidEdgeMotion = false;
} }
if (event->zPressure >= fSpecs->minPressure if (event->zPressure >= fSpecs.minPressure
&& event->zPressure < fSpecs->maxPressure && event->zPressure < fSpecs.maxPressure
&& ((event->wValue >= 4 && event->wValue <= 7) && ((event->fingerWidth >= 4 && event->fingerWidth <= 7)
|| event->wValue == 0 || event->wValue == 1) || event->fingerWidth == 0 || event->fingerWidth == 1)
&& (event->xPosition != 0 || event->yPosition != 0)) { && (event->xPosition != 0 || event->yPosition != 0)) {
// The touch pad is in touch with at least one finger // The touch pad is in touch with at least one finger
if (!_CheckScrollingToMovement(event, movement)) if (!_CheckScrollingToMovement(event, movement))
@@ -402,6 +255,14 @@ TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement)
} else } else
_NoTouchToMovement(event, movement); _NoTouchToMovement(event, movement);
if (fTapdragStarted || fValidEdgeMotion) {
// We want the current event to be repeated in 50ms if no other
// events occur in the interim.
repeatTimeout = 1000 * 50;
} else
repeatTimeout = B_INFINITE_TIMEOUT;
return B_OK; return B_OK;
} }
@@ -411,7 +272,7 @@ const int32 kEdgeMotionSpeed = 200;
bool bool
TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event, TouchpadMovement::_EdgeMotion(const touchpad_movement *event, mouse_movement *movement,
bool validStart) bool validStart)
{ {
float xdelta = 0; float xdelta = 0;
@@ -430,19 +291,19 @@ TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event,
bool inXEdge = false; bool inXEdge = false;
bool inYEdge = false; bool inYEdge = false;
if (int32(event->xPosition) < fSpecs->areaStartX + fSpecs->edgeMotionWidth) { if (int32(event->xPosition) < fSpecs.areaStartX + fSpecs.edgeMotionWidth) {
inXEdge = true; inXEdge = true;
xdelta *= -1; xdelta *= -1;
} else if (event->xPosition > uint16( } else if (event->xPosition > uint16(
fSpecs->areaEndX - fSpecs->edgeMotionWidth)) { fSpecs.areaEndX - fSpecs.edgeMotionWidth)) {
inXEdge = true; inXEdge = true;
} }
if (int32(event->yPosition) < fSpecs->areaStartY + fSpecs->edgeMotionWidth) { if (int32(event->yPosition) < fSpecs.areaStartY + fSpecs.edgeMotionWidth) {
inYEdge = true; inYEdge = true;
ydelta *= -1; ydelta *= -1;
} else if (event->yPosition > uint16( } else if (event->yPosition > uint16(
fSpecs->areaEndY - fSpecs->edgeMotionWidth)) { fSpecs.areaEndY - fSpecs.edgeMotionWidth)) {
inYEdge = true; inYEdge = true;
} }
@@ -471,7 +332,7 @@ TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event,
Also, it sets the button state from movement->buttons. Also, it sets the button state from movement->buttons.
*/ */
void void
TouchpadMovement::UpdateButtons(mouse_movement *movement) TouchpadMovement::_UpdateButtons(mouse_movement *movement)
{ {
// set click count correctly according to double click timeout // set click count correctly according to double click timeout
if (movement->buttons != 0 && fButtonsState == 0) { if (movement->buttons != 0 && fButtonsState == 0) {
@@ -491,7 +352,7 @@ TouchpadMovement::UpdateButtons(mouse_movement *movement)
void void
TouchpadMovement::_NoTouchToMovement(touch_event *event, TouchpadMovement::_NoTouchToMovement(const touchpad_movement *event,
mouse_movement *movement) mouse_movement *movement)
{ {
uint32 buttons = event->buttons; uint32 buttons = event->buttons;
@@ -539,12 +400,12 @@ TouchpadMovement::_NoTouchToMovement(touch_event *event,
} }
movement->buttons = buttons; movement->buttons = buttons;
UpdateButtons(movement); _UpdateButtons(movement);
} }
void void
TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement) TouchpadMovement::_MoveToMovement(const touchpad_movement *event, mouse_movement *movement)
{ {
bool isStartOfMovement = false; bool isStartOfMovement = false;
float pressure = 0; float pressure = 0;
@@ -569,7 +430,7 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
movement->buttons = kLeftButton; movement->buttons = kLeftButton;
movement->clicks = 0; movement->clicks = 0;
fValidEdgeMotion = _EdgeMotion(movement, event, fValidEdgeMotion); fValidEdgeMotion = _EdgeMotion(event, movement, fValidEdgeMotion);
TRACE("TouchpadMovement: tap drag\n"); TRACE("TouchpadMovement: tap drag\n");
} else { } else {
TRACE("TouchpadMovement: movement set buttons\n"); TRACE("TouchpadMovement: movement set buttons\n");
@@ -578,12 +439,12 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
// use only a fraction of pressure range, the max pressure seems to be // use only a fraction of pressure range, the max pressure seems to be
// to high // to high
pressure = 20 * (event->zPressure - fSpecs->minPressure) pressure = 20 * (event->zPressure - fSpecs.minPressure)
/ (fSpecs->realMaxPressure - fSpecs->minPressure); / (fSpecs.realMaxPressure - fSpecs.minPressure);
if (!fTapStarted if (!fTapStarted
&& isStartOfMovement && isStartOfMovement
&& fSettings->tapgesture_sensibility > 0. && fSettings.tapgesture_sensibility > 0.
&& fSettings->tapgesture_sensibility > (20 - pressure)) { && fSettings.tapgesture_sensibility > (20 - pressure)) {
TRACE("TouchpadMovement: tap started\n"); TRACE("TouchpadMovement: tap started\n");
fTapStarted = true; fTapStarted = true;
fTapTime = system_time(); fTapTime = system_time();
@@ -591,7 +452,7 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
fTapDeltaY = 0; fTapDeltaY = 0;
} }
UpdateButtons(movement); _UpdateButtons(movement);
} }
@@ -601,7 +462,7 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
\return \c true if this was a scrolling event, \c false if not. \return \c true if this was a scrolling event, \c false if not.
*/ */
bool bool
TouchpadMovement::_CheckScrollingToMovement(touch_event *event, TouchpadMovement::_CheckScrollingToMovement(const touchpad_movement *event,
mouse_movement *movement) mouse_movement *movement)
{ {
bool isSideScrollingV = false; bool isSideScrollingV = false;
@@ -612,23 +473,23 @@ TouchpadMovement::_CheckScrollingToMovement(touch_event *event,
if (fButtonsState != 0) if (fButtonsState != 0)
return false; return false;
if ((fSpecs->areaEndX - fAreaWidth * fSettings->scroll_rightrange if ((fSpecs.areaEndX - fAreaWidth * fSettings.scroll_rightrange
< event->xPosition && !fMovementStarted < event->xPosition && !fMovementStarted
&& fSettings->scroll_rightrange > 0.000001) && fSettings.scroll_rightrange > 0.000001)
|| fSettings->scroll_rightrange > 0.999999) { || fSettings.scroll_rightrange > 0.999999) {
isSideScrollingV = true; isSideScrollingV = true;
} }
if ((fSpecs->areaStartY + fAreaHeight * fSettings->scroll_bottomrange if ((fSpecs.areaStartY + fAreaHeight * fSettings.scroll_bottomrange
> event->yPosition && !fMovementStarted > event->yPosition && !fMovementStarted
&& fSettings->scroll_bottomrange > 0.000001) && fSettings.scroll_bottomrange > 0.000001)
|| fSettings->scroll_bottomrange > 0.999999) { || fSettings.scroll_bottomrange > 0.999999) {
isSideScrollingH = true; isSideScrollingH = true;
} }
if ((event->wValue == 0 || event->wValue == 1) if ((event->fingerWidth == 0 || event->fingerWidth == 1)
&& fSettings->scroll_twofinger) { && fSettings.scroll_twofinger) {
// two finger scrolling is enabled // two finger scrolling is enabled
isSideScrollingV = true; isSideScrollingV = true;
isSideScrollingH = fSettings->scroll_twofinger_horizontal; isSideScrollingH = fSettings.scroll_twofinger_horizontal;
} }
if (!isSideScrollingV && !isSideScrollingH) { if (!isSideScrollingV && !isSideScrollingH) {
@@ -0,0 +1,104 @@
/*
* Copyright 2008-2011, Clemens Zeidler <[email protected]>
* Copyright 2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef MOVEMENT_MAKER_H
#define MOVEMENT_MAKER_H
#include <OS.h>
#include <keyboard_mouse_driver.h>
#include <touchpad_settings.h>
class MovementMaker {
public:
void SetSpecs(const touchpad_specs& specs);
void SetSettings(const touchpad_settings& settings);
float xDelta;
float yDelta;
float scrolling_x;
float scrolling_y;
protected:
void StartNewMovment();
void GetMovement(uint32 posX, uint32 posY);
void GetScrolling(uint32 posX, uint32 posY);
touchpad_specs fSpecs;
touchpad_settings fSettings;
int8 fSpeed;
int16 fAreaWidth;
int16 fAreaHeight;
private:
void _GetRawMovement(uint32 posX, uint32 posY);
void _ComputeAcceleration(int8 accel_factor);
bool fMovementMakerStarted;
uint32 fPreviousX;
uint32 fPreviousY;
float fDeltaSumX;
float fDeltaSumY;
int8 fSmallMovement;
};
enum button_ids
{
kNoButton = 0x00,
kLeftButton = 0x01,
kRightButton = 0x02,
kMiddleButton = 0x04
};
class TouchpadMovement : public MovementMaker {
public:
TouchpadMovement();
status_t EventToMovement(const touchpad_movement *event,
mouse_movement *movement, bigtime_t &repeatTimeout);
bigtime_t click_speed;
private:
void _UpdateButtons(mouse_movement *movement);
bool _EdgeMotion(const touchpad_movement *event,
mouse_movement *movement, bool validStart);
inline void _NoTouchToMovement(const touchpad_movement *event,
mouse_movement *movement);
inline void _MoveToMovement(const touchpad_movement *event,
mouse_movement *movement);
inline bool _CheckScrollingToMovement(const touchpad_movement *event,
mouse_movement *movement);
bool fMovementStarted;
bool fScrollingStarted;
bool fTapStarted;
bigtime_t fTapTime;
int32 fTapDeltaX;
int32 fTapDeltaY;
int32 fTapClicks;
bool fTapdragStarted;
bool fValidEdgeMotion;
bigtime_t fLastEdgeMotion;
float fRestEdgeMotion;
bool fDoubleClick;
bigtime_t fClickLastTime;
int32 fClickCount;
uint32 fButtonsState;
};
#endif
@@ -15,5 +15,4 @@ KernelAddon ps2 :
ps2_synaptics.cpp ps2_synaptics.cpp
ps2_trackpoint.cpp ps2_trackpoint.cpp
ps2_service.cpp ps2_service.cpp
movement_maker.cpp
; ;
@@ -1,147 +0,0 @@
#ifndef MOVEMENT_MAKER_H
#define MOVEMENT_MAKER_H
#include <OS.h>
#include <keyboard_mouse_driver.h>
#include <touchpad_settings.h>
float floorf(float x);
float ceilf(float x);
float sqrtf(float x);
struct touch_event {
uint8 buttons;
uint32 xPosition;
uint32 yPosition;
uint8 zPressure;
// absolut mode (unused)
bool finger;
bool gesture;
// absolut w mode
uint8 wValue;
};
struct hardware_specs {
uint16 edgeMotionWidth;
uint16 areaStartX;
uint16 areaEndX;
uint16 areaStartY;
uint16 areaEndY;
uint16 minPressure;
// the value you reach when you hammer really hard on the touchpad
uint16 realMaxPressure;
uint16 maxPressure;
};
/*! The raw movement calculation is calibrated on ths synaptics touchpad. */
// increase the touchpad size a little bit
#define SYN_AREA_TOP_LEFT_OFFSET 40
#define SYN_AREA_BOTTOM_RIGHT_OFFSET 60
#define SYN_AREA_START_X (1472 - SYN_AREA_TOP_LEFT_OFFSET)
#define SYN_AREA_END_X (5472 + SYN_AREA_BOTTOM_RIGHT_OFFSET)
#define SYN_WIDTH (SYN_AREA_END_X - SYN_AREA_START_X)
#define SYN_AREA_START_Y (1408 - SYN_AREA_TOP_LEFT_OFFSET)
#define SYN_AREA_END_Y (4448 + SYN_AREA_BOTTOM_RIGHT_OFFSET)
#define SYN_HEIGHT (SYN_AREA_END_Y - SYN_AREA_START_Y)
class MovementMaker {
public:
void SetSettings(touchpad_settings* settings);
void SetSpecs(hardware_specs* specs);
float xDelta;
float yDelta;
float scrolling_x;
float scrolling_y;
protected:
void StartNewMovment();
void GetMovement(uint32 posX, uint32 posY);
void GetScrolling(uint32 posX, uint32 posY);
touchpad_settings* fSettings;
hardware_specs* fSpecs;
int8 fSpeed;
int16 fAreaWidth;
int16 fAreaHeight;
private:
void _GetRawMovement(uint32 posX, uint32 posY);
void _ComputeAcceleration(int8 accel_factor);
bool fMovementMakerStarted;
uint32 fPreviousX;
uint32 fPreviousY;
float fDeltaSumX;
float fDeltaSumY;
int8 fSmallMovement;
};
enum button_ids
{
kNoButton = 0x00,
kLeftButton = 0x01,
kRightButton = 0x02,
kMiddleButton = 0x04
};
class TouchpadMovement : public MovementMaker {
public:
void Init();
status_t EventToMovement(touch_event *event,
mouse_movement *movement);
bool TapDragStarted() { return fTapdragStarted; }
bool WasEdgeMotion() { return fValidEdgeMotion; }
void UpdateButtons(mouse_movement *movement);
bigtime_t click_speed;
private:
bool _EdgeMotion(mouse_movement *movement,
touch_event *event, bool validStart);
inline void _NoTouchToMovement(touch_event *event,
mouse_movement *movement);
inline void _MoveToMovement(touch_event *event,
mouse_movement *movement);
inline bool _CheckScrollingToMovement(touch_event *event,
mouse_movement *movement);
bool fMovementStarted;
bool fScrollingStarted;
bool fTapStarted;
bigtime_t fTapTime;
int32 fTapDeltaX;
int32 fTapDeltaY;
int32 fTapClicks;
bool fTapdragStarted;
bool fValidEdgeMotion;
bigtime_t fLastEdgeMotion;
float fRestEdgeMotion;
bool fDoubleClick;
bigtime_t fClickLastTime;
int32 fClickCount;
uint32 fButtonsState;
};
#endif
+34 -119
View File
@@ -15,6 +15,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <keyboard_mouse_driver.h>
#include "ps2_service.h" #include "ps2_service.h"
@@ -26,71 +28,6 @@
#endif #endif
static int32 generate_event(timer* timer);
const bigtime_t kEventInterval = 1000 * 50;
class EventProducer {
public:
EventProducer()
{
fFired = false;
}
status_t
FireEvent(alps_cookie* cookie, uint8* package)
{
fCookie = cookie;
memcpy(fLastPackage, package, sizeof(uint8) * PS2_PACKET_ALPS);
status_t status = add_timer(&fEventTimer, &generate_event,
kEventInterval, B_ONE_SHOT_RELATIVE_TIMER);
if (status == B_OK)
fFired = true;
return status;
}
bool
CancelEvent()
{
if (!fFired)
return false;
fFired = false;
return cancel_timer(&fEventTimer);
}
void
InjectEvent()
{
if (packet_buffer_write(fCookie->ring_buffer, fLastPackage,
PS2_PACKET_ALPS) != PS2_PACKET_ALPS) {
// buffer is full, drop new data
return;
}
release_sem_etc(fCookie->sem, 1, B_DO_NOT_RESCHEDULE);
}
private:
bool fFired;
uint8 fLastPackage[PS2_PACKET_ALPS];
timer fEventTimer;
alps_cookie* fCookie;
};
static EventProducer gEventProducer;
static int32
generate_event(timer* timer)
{
gEventProducer.InjectEvent();
return B_HANDLED_INTERRUPT;
}
const char* kALPSPath[4] = { const char* kALPSPath[4] = {
"input/touchpad/ps2/alps_0", "input/touchpad/ps2/alps_0",
"input/touchpad/ps2/alps_1", "input/touchpad/ps2/alps_1",
@@ -179,7 +116,7 @@ static alps_model_info* sFoundModel = NULL;
#define ALPS_HISTORY_SIZE 256 #define ALPS_HISTORY_SIZE 256
static hardware_specs gHardwareSpecs; static touchpad_specs gHardwareSpecs;
/* Data taken from linux driver: /* Data taken from linux driver:
@@ -192,13 +129,14 @@ byte 4: 0 y6 y5 y4 y3 y2 y1 y0
byte 5: 0 z6 z5 z4 z3 z2 z1 z0 byte 5: 0 z6 z5 z4 z3 z2 z1 z0
*/ */
static status_t static status_t
get_alps_movment(alps_cookie *cookie, mouse_movement *movement) get_alps_movment(alps_cookie *cookie, touchpad_read *_read)
{ {
status_t status; status_t status;
touch_event event; touchpad_movement event;
uint8 event_buffer[PS2_PACKET_ALPS]; uint8 event_buffer[PS2_PACKET_ALPS];
status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0); status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
_read->timeout);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -219,18 +157,18 @@ get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
// finger on touchpad // finger on touchpad
if (event_buffer[2] & 0x2) { if (event_buffer[2] & 0x2) {
// finger with normal width // finger with normal width
event.wValue = 4; event.fingerWidth = 4;
} else { } else {
event.wValue = 3; event.fingerWidth = 3;
} }
// tab gesture // tab gesture
if (event_buffer[2] & 0x1) { if (event_buffer[2] & 0x1) {
event.zPressure = 60; event.zPressure = 60;
event.wValue = 4; event.fingerWidth = 4;
} }
// if hardware tab gesture is off a z pressure of 16 is reported // if hardware tab gesture is off a z pressure of 16 is reported
if (cookie->previousZ == 0 && event.wValue == 4 && event.zPressure == 16) if (cookie->previousZ == 0 && event.fingerWidth == 4 && event.zPressure == 16)
event.zPressure = 60; event.zPressure = 60;
cookie->previousZ = event.zPressure; cookie->previousZ = event.zPressure;
@@ -240,36 +178,29 @@ get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
// check for trackpoint even (z pressure 127) // check for trackpoint even (z pressure 127)
if (sFoundModel->flags & ALPS_DUALPOINT && event.zPressure == 127) { if (sFoundModel->flags & ALPS_DUALPOINT && event.zPressure == 127) {
movement->xdelta = event.xPosition > 383 ? event.xPosition - 768 mouse_movement movement;
movement.xdelta = event.xPosition > 383 ? event.xPosition - 768
: event.xPosition; : event.xPosition;
movement->ydelta = event.yPosition > 255 movement.ydelta = event.yPosition > 255
? event.yPosition - 512 : event.yPosition; ? event.yPosition - 512 : event.yPosition;
movement->wheel_xdelta = 0; movement.wheel_xdelta = 0;
movement->wheel_ydelta = 0; movement.wheel_ydelta = 0;
movement->buttons = event.buttons; movement.buttons = event.buttons;
movement->timestamp = system_time(); movement.timestamp = system_time();
cookie->movementMaker.UpdateButtons(movement);
_read->event = MS_READ;
_read->u.mouse = movement;
} else { } else {
event.yPosition = AREA_END_Y - (event.yPosition - AREA_START_Y); event.yPosition = AREA_END_Y - (event.yPosition - AREA_START_Y);
status = cookie->movementMaker.EventToMovement(&event, movement);
}
if (cookie->movementMaker.WasEdgeMotion() _read->event = MS_READ_TOUCHPAD;
|| cookie->movementMaker.TapDragStarted()) { _read->u.touchpad = event;
gEventProducer.FireEvent(cookie, event_buffer);
} }
return status; return status;
} }
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
status_t status_t
probe_alps(ps2_dev* dev) probe_alps(ps2_dev* dev)
{ {
@@ -393,7 +324,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
goto err1; goto err1;
memset(cookie, 0, sizeof(*cookie)); memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
cookie->previousZ = 0; cookie->previousZ = 0;
*_cookie = cookie; *_cookie = cookie;
@@ -402,8 +332,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &alps_disconnect; dev->disconnect = &alps_disconnect;
dev->handle_int = &alps_handle_int; dev->handle_int = &alps_handle_int;
default_settings(&cookie->settings);
gHardwareSpecs.edgeMotionWidth = EDGE_MOTION_WIDTH; gHardwareSpecs.edgeMotionWidth = EDGE_MOTION_WIDTH;
gHardwareSpecs.areaStartX = AREA_START_X; gHardwareSpecs.areaStartX = AREA_START_X;
@@ -415,9 +343,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE; gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE;
gHardwareSpecs.maxPressure = MAX_PRESSURE; gHardwareSpecs.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
dev->packet_size = PS2_PACKET_ALPS; dev->packet_size = PS2_PACKET_ALPS;
cookie->ring_buffer = create_packet_buffer( cookie->ring_buffer = create_packet_buffer(
@@ -482,8 +407,6 @@ err1:
status_t status_t
alps_close(void *_cookie) alps_close(void *_cookie)
{ {
gEventProducer.CancelEvent();
alps_cookie *cookie = (alps_cookie*)_cookie; alps_cookie *cookie = (alps_cookie*)_cookie;
ps2_dev_command_timeout(cookie->dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0, ps2_dev_command_timeout(cookie->dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0,
@@ -521,29 +444,24 @@ status_t
alps_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) alps_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{ {
alps_cookie *cookie = (alps_cookie*)_cookie; alps_cookie *cookie = (alps_cookie*)_cookie;
mouse_movement movement; touchpad_read read;
status_t status; status_t status;
switch (op) { switch (op) {
case MS_READ:
TRACE("ALPS: MS_READ get event\n");
if ((status = get_alps_movment(cookie, &movement)) != B_OK)
return status;
return user_memcpy(buffer, &movement, sizeof(movement));
case MS_IS_TOUCHPAD: case MS_IS_TOUCHPAD:
TRACE("ALPS: MS_IS_TOUCHPAD\n"); TRACE("ALPS: MS_IS_TOUCHPAD\n");
if (buffer == NULL)
return B_OK; return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS: case MS_READ_TOUCHPAD:
TRACE("ALPS: MS_SET_TOUCHPAD_SETTINGS"); TRACE("ALPS: MS_READ get event\n");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings)); if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
return B_OK; sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
case MS_SET_CLICKSPEED: if ((status = get_alps_movment(cookie, &read)) != B_OK)
TRACE("ALPS: ioctl MS_SETCLICK (set click speed)\n"); return status;
return user_memcpy(&cookie->movementMaker.click_speed, buffer, return user_memcpy(buffer, &read, sizeof(read));
sizeof(bigtime_t));
default: default:
TRACE("ALPS: unknown opcode: %" B_PRIu32 "\n", op); TRACE("ALPS: unknown opcode: %" B_PRIu32 "\n", op);
@@ -573,9 +491,6 @@ alps_handle_int(ps2_dev* dev)
{ {
alps_cookie* cookie = (alps_cookie*)dev->cookie; alps_cookie* cookie = (alps_cookie*)dev->cookie;
// we got a real event cancel the fake event
gEventProducer.CancelEvent();
uint8 val; uint8 val;
val = cookie->dev->history[0].data; val = cookie->dev->history[0].data;
if (cookie->packet_index == 0 if (cookie->packet_index == 0
@@ -10,9 +10,6 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h" #include "packet_buffer.h"
#include "ps2_dev.h" #include "ps2_dev.h"
@@ -27,9 +24,6 @@ typedef struct {
uint8 mode; uint8 mode;
uint8 previousZ; uint8 previousZ;
TouchpadMovement movementMaker;
touchpad_settings settings;
} alps_cookie; } alps_cookie;
@@ -15,6 +15,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <keyboard_mouse_driver.h>
#include "ps2_service.h" #include "ps2_service.h"
@@ -26,71 +28,6 @@
#endif #endif
static int32 generate_event(timer* timer);
const bigtime_t kEventInterval = 1000 * 50;
class EventProducer {
public:
EventProducer()
{
fFired = false;
}
status_t
FireEvent(elantech_cookie* cookie, uint8* package)
{
fCookie = cookie;
memcpy(fLastPackage, package, sizeof(uint8) * PS2_PACKET_ELANTECH);
status_t status = add_timer(&fEventTimer, &generate_event,
kEventInterval, B_ONE_SHOT_RELATIVE_TIMER);
if (status == B_OK)
fFired = true;
return status;
}
bool
CancelEvent()
{
if (!fFired)
return false;
fFired = false;
return cancel_timer(&fEventTimer);
}
void
InjectEvent()
{
if (packet_buffer_write(fCookie->ring_buffer, fLastPackage,
PS2_PACKET_ELANTECH) != PS2_PACKET_ELANTECH) {
// buffer is full, drop new data
return;
}
release_sem_etc(fCookie->sem, 1, B_DO_NOT_RESCHEDULE);
}
private:
bool fFired;
uint8 fLastPackage[PS2_PACKET_ELANTECH];
timer fEventTimer;
elantech_cookie* fCookie;
};
static EventProducer gEventProducer;
static int32
generate_event(timer* timer)
{
gEventProducer.InjectEvent();
return B_HANDLED_INTERRUPT;
}
const char* kElantechPath[4] = { const char* kElantechPath[4] = {
"input/touchpad/ps2/elantech_0", "input/touchpad/ps2/elantech_0",
"input/touchpad/ps2/elantech_1", "input/touchpad/ps2/elantech_1",
@@ -124,16 +61,17 @@ const char* kElantechPath[4] = {
#define HEAD_PACKET 0x1 #define HEAD_PACKET 0x1
#define MOTION_PACKET 0x2 #define MOTION_PACKET 0x2
static hardware_specs gHardwareSpecs; static touchpad_specs gHardwareSpecs;
static status_t static status_t
get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement) get_elantech_movement(elantech_cookie *cookie, touchpad_movement *_event, bigtime_t timeout)
{ {
touch_event event; touchpad_movement event;
uint8 packet[PS2_PACKET_ELANTECH]; uint8 packet[PS2_PACKET_ELANTECH];
status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0); status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
timeout);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -208,25 +146,13 @@ get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement)
} }
event.buttons = 0; event.buttons = 0;
event.wValue = cookie->fingers == 1 ? 4 :0; event.fingerWidth = cookie->fingers == 1 ? 4 :0;
status = cookie->movementMaker.EventToMovement(&event, movement);
if (cookie->movementMaker.WasEdgeMotion()
|| cookie->movementMaker.TapDragStarted()) {
gEventProducer.FireEvent(cookie, packet);
}
*_event = event;
return status; return status;
} }
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
static status_t static status_t
synaptics_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count) synaptics_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count)
{ {
@@ -534,7 +460,6 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
goto err1; goto err1;
memset(cookie, 0, sizeof(*cookie)); memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
cookie->previousZ = 0; cookie->previousZ = 0;
*_cookie = cookie; *_cookie = cookie;
@@ -543,8 +468,6 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &elantech_disconnect; dev->disconnect = &elantech_disconnect;
dev->handle_int = &elantech_handle_int; dev->handle_int = &elantech_handle_int;
default_settings(&cookie->settings);
dev->packet_size = PS2_PACKET_ELANTECH; dev->packet_size = PS2_PACKET_ELANTECH;
cookie->ring_buffer = create_packet_buffer( cookie->ring_buffer = create_packet_buffer(
@@ -637,9 +560,6 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE; gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE;
gHardwareSpecs.maxPressure = MAX_PRESSURE; gHardwareSpecs.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
if (ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0) != B_OK) if (ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0) != B_OK)
goto err4; goto err4;
@@ -665,8 +585,6 @@ err1:
status_t status_t
elantech_close(void *_cookie) elantech_close(void *_cookie)
{ {
gEventProducer.CancelEvent();
elantech_cookie *cookie = (elantech_cookie*)_cookie; elantech_cookie *cookie = (elantech_cookie*)_cookie;
ps2_dev_command_timeout(cookie->dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0, ps2_dev_command_timeout(cookie->dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0,
@@ -704,29 +622,25 @@ status_t
elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{ {
elantech_cookie *cookie = (elantech_cookie*)_cookie; elantech_cookie *cookie = (elantech_cookie*)_cookie;
mouse_movement movement; touchpad_read read;
status_t status; status_t status;
switch (op) { switch (op) {
case MS_READ:
TRACE("ELANTECH: MS_READ get event\n");
if ((status = get_elantech_movement(cookie, &movement)) != B_OK)
return status;
return user_memcpy(buffer, &movement, sizeof(movement));
case MS_IS_TOUCHPAD: case MS_IS_TOUCHPAD:
TRACE("ELANTECH: MS_IS_TOUCHPAD\n"); TRACE("ELANTECH: MS_IS_TOUCHPAD\n");
if (buffer == NULL)
return B_OK; return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS: case MS_READ_TOUCHPAD:
TRACE("ELANTECH: MS_SET_TOUCHPAD_SETTINGS\n"); TRACE("ELANTECH: MS_READ get event\n");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings)); if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
return B_OK; sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
case MS_SET_CLICKSPEED: if ((status = get_elantech_movement(cookie, &read.u.touchpad, read.timeout)) != B_OK)
TRACE("ELANTECH: ioctl MS_SETCLICK (set click speed)\n"); return status;
return user_memcpy(&cookie->movementMaker.click_speed, buffer, read.event = MS_READ_TOUCHPAD;
sizeof(bigtime_t)); return user_memcpy(buffer, &read, sizeof(read));
default: default:
INFO("ELANTECH: unknown opcode: 0x%" B_PRIx32 "\n", op); INFO("ELANTECH: unknown opcode: 0x%" B_PRIx32 "\n", op);
@@ -756,9 +670,6 @@ elantech_handle_int(ps2_dev* dev)
{ {
elantech_cookie* cookie = (elantech_cookie*)dev->cookie; elantech_cookie* cookie = (elantech_cookie*)dev->cookie;
// we got a real event cancel the fake event
gEventProducer.CancelEvent();
uint8 val; uint8 val;
val = cookie->dev->history[0].data; val = cookie->dev->history[0].data;
cookie->buffer[cookie->packet_index] = val; cookie->buffer[cookie->packet_index] = val;
@@ -14,9 +14,6 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h" #include "packet_buffer.h"
#include "ps2_dev.h" #include "ps2_dev.h"
@@ -28,9 +25,6 @@ typedef struct {
struct packet_buffer* ring_buffer; struct packet_buffer* ring_buffer;
size_t packet_index; size_t packet_index;
TouchpadMovement movementMaker;
touchpad_settings settings;
uint32 version; uint32 version;
uint32 fwVersion; uint32 fwVersion;
@@ -47,7 +41,6 @@ typedef struct {
uint8 mode; uint8 mode;
bool crcEnabled; bool crcEnabled;
status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count); status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count);
} elantech_cookie; } elantech_cookie;
@@ -28,6 +28,15 @@
# define TRACE(x...) # define TRACE(x...)
#endif #endif
/*! The raw movement calculation is calibrated on ths synaptics touchpad. */
// increase the touchpad size a little bit
#define SYN_AREA_TOP_LEFT_OFFSET 40
#define SYN_AREA_BOTTOM_RIGHT_OFFSET 60
#define SYN_AREA_START_X (1472 - SYN_AREA_TOP_LEFT_OFFSET)
#define SYN_AREA_END_X (5472 + SYN_AREA_BOTTOM_RIGHT_OFFSET)
#define SYN_AREA_START_Y (1408 - SYN_AREA_TOP_LEFT_OFFSET)
#define SYN_AREA_END_Y (4448 + SYN_AREA_BOTTOM_RIGHT_OFFSET)
// synaptics touchpad proportions // synaptics touchpad proportions
#define SYN_EDGE_MOTION_WIDTH 50 #define SYN_EDGE_MOTION_WIDTH 50
#define SYN_AREA_OFFSET 40 #define SYN_AREA_OFFSET 40
@@ -52,7 +61,7 @@ enum {
kTrackpointQuirk = 0x10 kTrackpointQuirk = 0x10
}; };
static hardware_specs gHardwareSpecs; static touchpad_specs gHardwareSpecs;
const char* kSynapticsPath[4] = { const char* kSynapticsPath[4] = {
@@ -67,13 +76,6 @@ static touchpad_info sTouchpadInfo;
static ps2_dev *sPassthroughDevice = &ps2_device[PS2_DEVICE_SYN_PASSTHROUGH]; static ps2_dev *sPassthroughDevice = &ps2_device[PS2_DEVICE_SYN_PASSTHROUGH];
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
static status_t static status_t
send_touchpad_arg_timeout(ps2_dev *dev, uint8 arg, bigtime_t timeout) send_touchpad_arg_timeout(ps2_dev *dev, uint8 arg, bigtime_t timeout)
{ {
@@ -126,16 +128,17 @@ get_information_query(ps2_dev *dev, uint8 extendedQueries, uint8 query,
static status_t static status_t
get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement) get_synaptics_movment(synaptics_cookie *cookie, touchpad_movement *_event, bigtime_t timeout)
{ {
status_t status; status_t status;
touch_event event; touchpad_movement event;
uint8 event_buffer[PS2_MAX_PACKET_SIZE]; uint8 event_buffer[PS2_MAX_PACKET_SIZE];
uint8 wValue0, wValue1, wValue2, wValue3, wValue; uint8 wValue0, wValue1, wValue2, wValue3, wValue;
uint32 val32; uint32 val32;
uint32 xTwelfBit, yTwelfBit; uint32 xTwelfBit, yTwelfBit;
status = acquire_sem_etc(cookie->synaptics_sem, 1, B_CAN_INTERRUPT, 0); status = acquire_sem_etc(cookie->synaptics_sem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
timeout);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -164,7 +167,7 @@ get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
wValue = wValue | (wValue2 << 2); wValue = wValue | (wValue2 << 2);
wValue = wValue | (wValue3 << 3); wValue = wValue | (wValue3 << 3);
event.wValue = wValue; event.fingerWidth = wValue;
event.gesture = false; event.gesture = false;
// Clickpad pretends that all clicks on the touchpad are middle clicks. // Clickpad pretends that all clicks on the touchpad are middle clicks.
@@ -204,7 +207,7 @@ get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
bool finger = event_buffer[0] >> 5 & 1; bool finger = event_buffer[0] >> 5 & 1;
if (finger) { if (finger) {
// finger with normal width // finger with normal width
event.wValue = 4; event.fingerWidth = 4;
} }
event.gesture = event_buffer[0] >> 2 & 1; event.gesture = event_buffer[0] >> 2 & 1;
} }
@@ -222,9 +225,8 @@ get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
yTwelfBit = event_buffer[3] >> 5 & 1; yTwelfBit = event_buffer[3] >> 5 & 1;
event.yPosition += yTwelfBit << 12; event.yPosition += yTwelfBit << 12;
status = cookie->movementMaker.EventToMovement(&event, movement); *_event = event;
return B_OK;
return status;
} }
@@ -460,7 +462,6 @@ synaptics_open(const char *name, uint32 flags, void **_cookie)
goto err1; goto err1;
memset(cookie, 0, sizeof(*cookie)); memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
*_cookie = cookie; *_cookie = cookie;
cookie->dev = dev; cookie->dev = dev;
@@ -468,8 +469,6 @@ synaptics_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &synaptics_disconnect; dev->disconnect = &synaptics_disconnect;
dev->handle_int = &synaptics_handle_int; dev->handle_int = &synaptics_handle_int;
default_settings(&cookie->settings);
gHardwareSpecs.edgeMotionWidth = SYN_EDGE_MOTION_WIDTH; gHardwareSpecs.edgeMotionWidth = SYN_EDGE_MOTION_WIDTH;
gHardwareSpecs.areaStartX = SYN_AREA_START_X; gHardwareSpecs.areaStartX = SYN_AREA_START_X;
@@ -481,9 +480,6 @@ synaptics_open(const char *name, uint32 flags, void **_cookie)
gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE; gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE;
gHardwareSpecs.maxPressure = MAX_PRESSURE; gHardwareSpecs.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
dev->packet_size = PS2_PACKET_SYNAPTICS; dev->packet_size = PS2_PACKET_SYNAPTICS;
cookie->synaptics_ring_buffer cookie->synaptics_ring_buffer
@@ -607,29 +603,25 @@ status_t
synaptics_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) synaptics_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{ {
synaptics_cookie *cookie = (synaptics_cookie*)_cookie; synaptics_cookie *cookie = (synaptics_cookie*)_cookie;
mouse_movement movement; touchpad_read read;
status_t status; status_t status;
switch (op) { switch (op) {
case MS_READ:
if ((status = get_synaptics_movment(cookie, &movement)) != B_OK)
return status;
TRACE("SYNAPTICS: MS_READ get event\n");
return user_memcpy(buffer, &movement, sizeof(movement));
case MS_IS_TOUCHPAD: case MS_IS_TOUCHPAD:
TRACE("SYNAPTICS: MS_IS_TOUCHPAD\n"); TRACE("SYNAPTICS: MS_IS_TOUCHPAD\n");
if (buffer == NULL)
return B_OK; return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS: case MS_READ_TOUCHPAD:
TRACE("SYNAPTICS: MS_SET_TOUCHPAD_SETTINGS"); TRACE("SYNAPTICS: MS_READ get event\n");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings)); if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
return B_OK; sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
case MS_SET_CLICKSPEED: if ((status = get_synaptics_movment(cookie, &read.u.touchpad, read.timeout)) != B_OK)
TRACE("SYNAPTICS: ioctl MS_SETCLICK (set click speed)\n"); return status;
return user_memcpy(&cookie->movementMaker.click_speed, buffer, read.event = MS_READ_TOUCHPAD;
sizeof(bigtime_t)); return user_memcpy(buffer, &read, sizeof(read));
default: default:
TRACE("SYNAPTICS: unknown opcode: %" B_PRIu32 "\n", op); TRACE("SYNAPTICS: unknown opcode: %" B_PRIu32 "\n", op);
@@ -11,9 +11,6 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h" #include "packet_buffer.h"
#include "ps2_service.h" #include "ps2_service.h"
@@ -65,10 +62,6 @@ struct packet_buffer* synaptics_ring_buffer;
size_t packet_index; size_t packet_index;
uint8 buffer[PS2_PACKET_SYNAPTICS]; uint8 buffer[PS2_PACKET_SYNAPTICS];
uint8 mode; uint8 mode;
TouchpadMovement movementMaker;
touchpad_settings settings;
} synaptics_cookie; } synaptics_cookie;
+2 -2
View File
@@ -15,7 +15,7 @@
#include <List.h> #include <List.h>
#include <String.h> #include <String.h>
#include <keyboard_mouse_driver.h> #include <InputServerDevice.h>
TouchpadPref::TouchpadPref(BInputDevice* device) TouchpadPref::TouchpadPref(BInputDevice* device)
@@ -63,7 +63,7 @@ TouchpadPref::UpdateSettings()
msg.AddInt8("tapgesture_sensibility", fSettings.tapgesture_sensibility); msg.AddInt8("tapgesture_sensibility", fSettings.tapgesture_sensibility);
msg.AddInt32("padblocker_threshold", fSettings.padblocker_threshold); msg.AddInt32("padblocker_threshold", fSettings.padblocker_threshold);
return fTouchPad->Control(MS_SET_TOUCHPAD_SETTINGS, &msg); return fTouchPad->Control(B_SET_TOUCHPAD_SETTINGS, &msg);
} }