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 <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2022-07-15 13:24:29 -04:00 committed by waddlesplash
parent 1f26a521ac
commit 5e596efecf
16 changed files with 363 additions and 725 deletions

View File

@ -32,6 +32,7 @@ enum {
B_MOUSE_SPEED_CHANGED,
B_CLICK_SPEED_CHANGED,
B_MOUSE_ACCELERATION_CHANGED,
B_SET_TOUCHPAD_SETTINGS,
};
namespace BPrivate {

View File

@ -62,9 +62,10 @@ enum {
MS_GET_CLICKSPEED,
MS_SET_CLICKSPEED,
MS_NUM_SERIAL_MICE,
MS_IS_TOUCHPAD,
MS_SET_TOUCHPAD_SETTINGS,
MS_READ_TOUCHPAD,
IIC_WRITE = B_DEVICE_OP_CODES_END + 200,
RESTART_SYSTEM,
SHUTDOWN_SYSTEM
@ -127,6 +128,22 @@ typedef struct {
#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 {
uint8 buttons;
uint32 xPosition;
@ -137,8 +154,18 @@ typedef struct {
uint8 fingerWidth;
// 1 - 4 normal width
// 5 - 11 very wide finger or palm
// 12 maximum reportable width; extrem wide contact
// 12 maximum reportable width; extreme wide contact
} touchpad_movement;
typedef struct {
bigtime_t timeout;
int32 event;
union {
touchpad_movement touchpad;
mouse_movement mouse;
} u;
} touchpad_read;
#endif // _KB_MOUSE_DRIVER_H

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

View File

@ -4,4 +4,5 @@ UsePrivateHeaders input shared ;
Addon <input>mouse :
MouseInputDevice.cpp
movement_maker.cpp
: be input_server [ TargetLibsupc++ ] ;

View File

@ -34,6 +34,8 @@
#include <keyboard_mouse_driver.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#undef TRACE
//#define TRACE_MOUSE_DEVICE
@ -120,8 +122,7 @@ private:
void _UpdateSettings();
status_t _GetTouchpadSettingsPath(BPath& path);
status_t _ReadTouchpadSettingsMsg(BMessage* message);
status_t _UpdateTouchpadSettings();
status_t _UpdateTouchpadSettings(BMessage* message);
BMessage* _BuildMouseMessage(uint32 what,
uint64 when, uint32 buttons,
@ -147,7 +148,7 @@ private:
volatile bool fUpdateSettings;
bool fIsTouchpad;
touchpad_settings fTouchpadSettings;
TouchpadMovement fTouchpadMovementMaker;
BMessage* fTouchpadSettingsMessage;
BLocker fTouchpadSettingsLock;
};
@ -367,22 +368,26 @@ MouseDevice::_ControlThread()
}
// 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());
fIsTouchpad = true;
fTouchpadSettings = kDefaultTouchpadSettings;
touchpad_settings settings;
settings = kDefaultTouchpadSettings;
BPath path;
status_t status = _GetTouchpadSettingsPath(path);
BFile settingsFile(path.Path(), B_READ_ONLY);
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)) {
TRACE("failed to load settings\n");
}
}
_UpdateTouchpadSettings();
fTouchpadMovementMaker.SetSpecs(touchpadSpecs);
fTouchpadMovementMaker.SetSettings(settings);
}
_UpdateSettings();
@ -398,6 +403,10 @@ MouseDevice::_ControlThread()
bigtime_t nextTransferTime = system_time() + kTransferDelay;
#endif
// touchpads only
touchpad_movement lastTouchpadMovement;
bigtime_t touchpadEventTimeout = B_INFINITE_TIMEOUT;
while (fActive) {
mouse_movement movements;
@ -406,11 +415,40 @@ MouseDevice::_ControlThread()
nextTransferTime += kTransferDelay;
#endif
if (ioctl(fDevice, MS_READ, &movements, sizeof(movements)) != B_OK) {
LOG_ERR("Mouse device exiting, %s\n", strerror(errno));
_ControlThreadCleanup();
// TOAST!
return;
if (!fIsTouchpad) {
if (ioctl(fDevice, MS_READ, &movements, sizeof(movements)) != B_OK) {
LOG_ERR("Mouse device exiting, %s\n", strerror(errno));
_ControlThreadCleanup();
// TOAST!
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
@ -419,8 +457,7 @@ MouseDevice::_ControlThread()
if (fIsTouchpad) {
BAutolock _(fTouchpadSettingsLock);
if (fTouchpadSettingsMessage != NULL) {
_ReadTouchpadSettingsMsg(fTouchpadSettingsMessage);
_UpdateTouchpadSettings();
_UpdateTouchpadSettings(fTouchpadSettingsMessage);
delete fTouchpadSettingsMessage;
fTouchpadSettingsMessage = NULL;
} else
@ -524,10 +561,12 @@ MouseDevice::_UpdateSettings()
= ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
}
if (get_click_speed(&fSettings.click_speed) != B_OK)
LOG_ERR("error when get_click_speed\n");
else
if (get_click_speed(&fSettings.click_speed) == B_OK) {
if (fIsTouchpad)
fTouchpadMovementMaker.click_speed = 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)
LOG_ERR("error when get_mouse_speed\n");
@ -561,40 +600,33 @@ MouseDevice::_GetTouchpadSettingsPath(BPath& path)
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",
&fTouchpadSettings.scroll_twofinger_horizontal);
&settings.scroll_twofinger_horizontal);
message->FindFloat("scroll_rightrange",
&fTouchpadSettings.scroll_rightrange);
&settings.scroll_rightrange);
message->FindFloat("scroll_bottomrange",
&fTouchpadSettings.scroll_bottomrange);
&settings.scroll_bottomrange);
message->FindInt16("scroll_xstepsize",
(int16*)&fTouchpadSettings.scroll_xstepsize);
(int16*)&settings.scroll_xstepsize);
message->FindInt16("scroll_ystepsize",
(int16*)&fTouchpadSettings.scroll_ystepsize);
(int16*)&settings.scroll_ystepsize);
message->FindInt8("scroll_acceleration",
(int8*)&fTouchpadSettings.scroll_acceleration);
(int8*)&settings.scroll_acceleration);
message->FindInt8("tapgesture_sensibility",
(int8*)&fTouchpadSettings.tapgesture_sensibility);
(int8*)&settings.tapgesture_sensibility);
if (fIsTouchpad)
fTouchpadMovementMaker.SetSettings(settings);
return B_OK;
}
status_t
MouseDevice::_UpdateTouchpadSettings()
{
if (fIsTouchpad) {
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
return B_OK;
}
return B_ERROR;
}
BMessage*
MouseDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
int32 deltaX, int32 deltaY) const
@ -748,7 +780,7 @@ MouseInputDevice::Control(const char* name, void* cookie,
if (command == B_NODE_MONITOR)
return _HandleMonitor(message);
if (command == MS_SET_TOUCHPAD_SETTINGS)
if (command == B_SET_TOUCHPAD_SETTINGS)
return device->UpdateTouchpadSettings(message);
if (command >= B_MOUSE_TYPE_CHANGED

View File

@ -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 <stdlib.h>
#include <math.h>
#include <KernelExport.h>
@ -13,160 +19,9 @@
#endif
typedef union {
float value;
/* FIXME: Assumes 32 bit int. */
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;
}
// magic constants
#define SYN_WIDTH (4100)
#define SYN_HEIGHT (3140)
static int32
@ -179,21 +34,20 @@ make_small(float value)
}
void
MovementMaker::SetSettings(touchpad_settings* settings)
MovementMaker::SetSettings(const touchpad_settings& settings)
{
fSettings = settings;
}
void
MovementMaker::SetSpecs(hardware_specs* specs)
MovementMaker::SetSpecs(const touchpad_specs& specs)
{
fSpecs = specs;
fAreaWidth = fSpecs->areaEndX - fSpecs->areaStartX;
fAreaHeight = fSpecs->areaEndY - fSpecs->areaStartY;
fAreaWidth = fSpecs.areaEndX - fSpecs.areaStartX;
fAreaHeight = fSpecs.areaEndY - fSpecs.areaStartY;
// calibrated on the synaptics touchpad
fSpeed = SYN_WIDTH / fAreaWidth;
@ -204,10 +58,10 @@ MovementMaker::SetSpecs(hardware_specs* specs)
void
MovementMaker::StartNewMovment()
{
if (fSettings->scroll_xstepsize <= 0)
fSettings->scroll_xstepsize = 1;
if (fSettings->scroll_ystepsize <= 0)
fSettings->scroll_ystepsize = 1;
if (fSettings.scroll_xstepsize <= 0)
fSettings.scroll_xstepsize = 1;
if (fSettings.scroll_ystepsize <= 0)
fSettings.scroll_ystepsize = 1;
fMovementMakerStarted = true;
scrolling_x = 0;
@ -228,25 +82,25 @@ MovementMaker::GetScrolling(uint32 posX, uint32 posY)
int32 stepsX = 0, stepsY = 0;
_GetRawMovement(posX, posY);
_ComputeAcceleration(fSettings->scroll_acceleration);
_ComputeAcceleration(fSettings.scroll_acceleration);
if (fSettings->scroll_xstepsize > 0) {
if (fSettings.scroll_xstepsize > 0) {
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;
} else {
scrolling_x = 0;
xDelta = 0;
}
if (fSettings->scroll_ystepsize > 0) {
if (fSettings.scroll_ystepsize > 0) {
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;
} else {
scrolling_y = 0;
@ -326,7 +180,6 @@ MovementMaker::_GetRawMovement(uint32 posX, uint32 posY)
}
void
MovementMaker::_ComputeAcceleration(int8 accel_factor)
{
@ -348,8 +201,7 @@ MovementMaker::_ComputeAcceleration(int8 accel_factor)
#define fTapTimeOUT 200000
void
TouchpadMovement::Init()
TouchpadMovement::TouchpadMovement()
{
fMovementStarted = false;
fScrollingStarted = false;
@ -360,7 +212,8 @@ TouchpadMovement::Init()
status_t
TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement)
TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement* movement,
bigtime_t& repeatTimeout)
{
if (!movement)
return B_ERROR;
@ -391,10 +244,10 @@ TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement)
fValidEdgeMotion = false;
}
if (event->zPressure >= fSpecs->minPressure
&& event->zPressure < fSpecs->maxPressure
&& ((event->wValue >= 4 && event->wValue <= 7)
|| event->wValue == 0 || event->wValue == 1)
if (event->zPressure >= fSpecs.minPressure
&& event->zPressure < fSpecs.maxPressure
&& ((event->fingerWidth >= 4 && event->fingerWidth <= 7)
|| event->fingerWidth == 0 || event->fingerWidth == 1)
&& (event->xPosition != 0 || event->yPosition != 0)) {
// The touch pad is in touch with at least one finger
if (!_CheckScrollingToMovement(event, movement))
@ -402,6 +255,14 @@ TouchpadMovement::EventToMovement(touch_event *event, mouse_movement *movement)
} else
_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;
}
@ -411,7 +272,7 @@ const int32 kEdgeMotionSpeed = 200;
bool
TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event,
TouchpadMovement::_EdgeMotion(const touchpad_movement *event, mouse_movement *movement,
bool validStart)
{
float xdelta = 0;
@ -430,19 +291,19 @@ TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event,
bool inXEdge = false;
bool inYEdge = false;
if (int32(event->xPosition) < fSpecs->areaStartX + fSpecs->edgeMotionWidth) {
if (int32(event->xPosition) < fSpecs.areaStartX + fSpecs.edgeMotionWidth) {
inXEdge = true;
xdelta *= -1;
} else if (event->xPosition > uint16(
fSpecs->areaEndX - fSpecs->edgeMotionWidth)) {
fSpecs.areaEndX - fSpecs.edgeMotionWidth)) {
inXEdge = true;
}
if (int32(event->yPosition) < fSpecs->areaStartY + fSpecs->edgeMotionWidth) {
if (int32(event->yPosition) < fSpecs.areaStartY + fSpecs.edgeMotionWidth) {
inYEdge = true;
ydelta *= -1;
} else if (event->yPosition > uint16(
fSpecs->areaEndY - fSpecs->edgeMotionWidth)) {
fSpecs.areaEndY - fSpecs.edgeMotionWidth)) {
inYEdge = true;
}
@ -471,7 +332,7 @@ TouchpadMovement::_EdgeMotion(mouse_movement *movement, touch_event *event,
Also, it sets the button state from movement->buttons.
*/
void
TouchpadMovement::UpdateButtons(mouse_movement *movement)
TouchpadMovement::_UpdateButtons(mouse_movement *movement)
{
// set click count correctly according to double click timeout
if (movement->buttons != 0 && fButtonsState == 0) {
@ -491,7 +352,7 @@ TouchpadMovement::UpdateButtons(mouse_movement *movement)
void
TouchpadMovement::_NoTouchToMovement(touch_event *event,
TouchpadMovement::_NoTouchToMovement(const touchpad_movement *event,
mouse_movement *movement)
{
uint32 buttons = event->buttons;
@ -539,12 +400,12 @@ TouchpadMovement::_NoTouchToMovement(touch_event *event,
}
movement->buttons = buttons;
UpdateButtons(movement);
_UpdateButtons(movement);
}
void
TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
TouchpadMovement::_MoveToMovement(const touchpad_movement *event, mouse_movement *movement)
{
bool isStartOfMovement = false;
float pressure = 0;
@ -569,7 +430,7 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
movement->buttons = kLeftButton;
movement->clicks = 0;
fValidEdgeMotion = _EdgeMotion(movement, event, fValidEdgeMotion);
fValidEdgeMotion = _EdgeMotion(event, movement, fValidEdgeMotion);
TRACE("TouchpadMovement: tap drag\n");
} else {
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
// to high
pressure = 20 * (event->zPressure - fSpecs->minPressure)
/ (fSpecs->realMaxPressure - fSpecs->minPressure);
pressure = 20 * (event->zPressure - fSpecs.minPressure)
/ (fSpecs.realMaxPressure - fSpecs.minPressure);
if (!fTapStarted
&& isStartOfMovement
&& fSettings->tapgesture_sensibility > 0.
&& fSettings->tapgesture_sensibility > (20 - pressure)) {
&& fSettings.tapgesture_sensibility > 0.
&& fSettings.tapgesture_sensibility > (20 - pressure)) {
TRACE("TouchpadMovement: tap started\n");
fTapStarted = true;
fTapTime = system_time();
@ -591,7 +452,7 @@ TouchpadMovement::_MoveToMovement(touch_event *event, mouse_movement *movement)
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.
*/
bool
TouchpadMovement::_CheckScrollingToMovement(touch_event *event,
TouchpadMovement::_CheckScrollingToMovement(const touchpad_movement *event,
mouse_movement *movement)
{
bool isSideScrollingV = false;
@ -612,23 +473,23 @@ TouchpadMovement::_CheckScrollingToMovement(touch_event *event,
if (fButtonsState != 0)
return false;
if ((fSpecs->areaEndX - fAreaWidth * fSettings->scroll_rightrange
if ((fSpecs.areaEndX - fAreaWidth * fSettings.scroll_rightrange
< event->xPosition && !fMovementStarted
&& fSettings->scroll_rightrange > 0.000001)
|| fSettings->scroll_rightrange > 0.999999) {
&& fSettings.scroll_rightrange > 0.000001)
|| fSettings.scroll_rightrange > 0.999999) {
isSideScrollingV = true;
}
if ((fSpecs->areaStartY + fAreaHeight * fSettings->scroll_bottomrange
if ((fSpecs.areaStartY + fAreaHeight * fSettings.scroll_bottomrange
> event->yPosition && !fMovementStarted
&& fSettings->scroll_bottomrange > 0.000001)
|| fSettings->scroll_bottomrange > 0.999999) {
&& fSettings.scroll_bottomrange > 0.000001)
|| fSettings.scroll_bottomrange > 0.999999) {
isSideScrollingH = true;
}
if ((event->wValue == 0 || event->wValue == 1)
&& fSettings->scroll_twofinger) {
if ((event->fingerWidth == 0 || event->fingerWidth == 1)
&& fSettings.scroll_twofinger) {
// two finger scrolling is enabled
isSideScrollingV = true;
isSideScrollingH = fSettings->scroll_twofinger_horizontal;
isSideScrollingH = fSettings.scroll_twofinger_horizontal;
}
if (!isSideScrollingV && !isSideScrollingH) {

View File

@ -0,0 +1,104 @@
/*
* Copyright 2008-2011, Clemens Zeidler <haiku@clemens-zeidler.de>
* 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

View File

@ -15,5 +15,4 @@ KernelAddon ps2 :
ps2_synaptics.cpp
ps2_trackpoint.cpp
ps2_service.cpp
movement_maker.cpp
;

View File

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

View File

@ -15,6 +15,8 @@
#include <stdlib.h>
#include <string.h>
#include <keyboard_mouse_driver.h>
#include "ps2_service.h"
@ -26,71 +28,6 @@
#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] = {
"input/touchpad/ps2/alps_0",
"input/touchpad/ps2/alps_1",
@ -179,7 +116,7 @@ static alps_model_info* sFoundModel = NULL;
#define ALPS_HISTORY_SIZE 256
static hardware_specs gHardwareSpecs;
static touchpad_specs gHardwareSpecs;
/* 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
*/
static status_t
get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
get_alps_movment(alps_cookie *cookie, touchpad_read *_read)
{
status_t status;
touch_event event;
touchpad_movement event;
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)
return status;
@ -219,18 +157,18 @@ get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
// finger on touchpad
if (event_buffer[2] & 0x2) {
// finger with normal width
event.wValue = 4;
event.fingerWidth = 4;
} else {
event.wValue = 3;
event.fingerWidth = 3;
}
// tab gesture
if (event_buffer[2] & 0x1) {
event.zPressure = 60;
event.wValue = 4;
event.fingerWidth = 4;
}
// 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;
cookie->previousZ = event.zPressure;
@ -240,36 +178,29 @@ get_alps_movment(alps_cookie *cookie, mouse_movement *movement)
// check for trackpoint even (z pressure 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;
movement->ydelta = event.yPosition > 255
movement.ydelta = event.yPosition > 255
? event.yPosition - 512 : event.yPosition;
movement->wheel_xdelta = 0;
movement->wheel_ydelta = 0;
movement->buttons = event.buttons;
movement->timestamp = system_time();
cookie->movementMaker.UpdateButtons(movement);
movement.wheel_xdelta = 0;
movement.wheel_ydelta = 0;
movement.buttons = event.buttons;
movement.timestamp = system_time();
_read->event = MS_READ;
_read->u.mouse = movement;
} else {
event.yPosition = AREA_END_Y - (event.yPosition - AREA_START_Y);
status = cookie->movementMaker.EventToMovement(&event, movement);
}
if (cookie->movementMaker.WasEdgeMotion()
|| cookie->movementMaker.TapDragStarted()) {
gEventProducer.FireEvent(cookie, event_buffer);
_read->event = MS_READ_TOUCHPAD;
_read->u.touchpad = event;
}
return status;
}
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
status_t
probe_alps(ps2_dev* dev)
{
@ -393,7 +324,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
goto err1;
memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
cookie->previousZ = 0;
*_cookie = cookie;
@ -402,8 +332,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &alps_disconnect;
dev->handle_int = &alps_handle_int;
default_settings(&cookie->settings);
gHardwareSpecs.edgeMotionWidth = EDGE_MOTION_WIDTH;
gHardwareSpecs.areaStartX = AREA_START_X;
@ -415,9 +343,6 @@ alps_open(const char *name, uint32 flags, void **_cookie)
gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE;
gHardwareSpecs.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
dev->packet_size = PS2_PACKET_ALPS;
cookie->ring_buffer = create_packet_buffer(
@ -482,8 +407,6 @@ err1:
status_t
alps_close(void *_cookie)
{
gEventProducer.CancelEvent();
alps_cookie *cookie = (alps_cookie*)_cookie;
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_cookie *cookie = (alps_cookie*)_cookie;
mouse_movement movement;
touchpad_read read;
status_t status;
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:
TRACE("ALPS: MS_IS_TOUCHPAD\n");
return B_OK;
if (buffer == NULL)
return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS:
TRACE("ALPS: MS_SET_TOUCHPAD_SETTINGS");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings));
return B_OK;
case MS_SET_CLICKSPEED:
TRACE("ALPS: ioctl MS_SETCLICK (set click speed)\n");
return user_memcpy(&cookie->movementMaker.click_speed, buffer,
sizeof(bigtime_t));
case MS_READ_TOUCHPAD:
TRACE("ALPS: MS_READ get event\n");
if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
if ((status = get_alps_movment(cookie, &read)) != B_OK)
return status;
return user_memcpy(buffer, &read, sizeof(read));
default:
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;
// we got a real event cancel the fake event
gEventProducer.CancelEvent();
uint8 val;
val = cookie->dev->history[0].data;
if (cookie->packet_index == 0

View File

@ -10,9 +10,6 @@
#include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h"
#include "ps2_dev.h"
@ -27,9 +24,6 @@ typedef struct {
uint8 mode;
uint8 previousZ;
TouchpadMovement movementMaker;
touchpad_settings settings;
} alps_cookie;

View File

@ -15,6 +15,8 @@
#include <stdlib.h>
#include <string.h>
#include <keyboard_mouse_driver.h>
#include "ps2_service.h"
@ -26,71 +28,6 @@
#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] = {
"input/touchpad/ps2/elantech_0",
"input/touchpad/ps2/elantech_1",
@ -124,16 +61,17 @@ const char* kElantechPath[4] = {
#define HEAD_PACKET 0x1
#define MOTION_PACKET 0x2
static hardware_specs gHardwareSpecs;
static touchpad_specs gHardwareSpecs;
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];
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)
return status;
@ -208,25 +146,13 @@ get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement)
}
event.buttons = 0;
event.wValue = cookie->fingers == 1 ? 4 :0;
status = cookie->movementMaker.EventToMovement(&event, movement);
if (cookie->movementMaker.WasEdgeMotion()
|| cookie->movementMaker.TapDragStarted()) {
gEventProducer.FireEvent(cookie, packet);
}
event.fingerWidth = cookie->fingers == 1 ? 4 :0;
*_event = event;
return status;
}
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
static status_t
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;
memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
cookie->previousZ = 0;
*_cookie = cookie;
@ -543,8 +468,6 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &elantech_disconnect;
dev->handle_int = &elantech_handle_int;
default_settings(&cookie->settings);
dev->packet_size = PS2_PACKET_ELANTECH;
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.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)
goto err4;
@ -665,8 +585,6 @@ err1:
status_t
elantech_close(void *_cookie)
{
gEventProducer.CancelEvent();
elantech_cookie *cookie = (elantech_cookie*)_cookie;
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_cookie *cookie = (elantech_cookie*)_cookie;
mouse_movement movement;
touchpad_read read;
status_t status;
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:
TRACE("ELANTECH: MS_IS_TOUCHPAD\n");
return B_OK;
if (buffer == NULL)
return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS:
TRACE("ELANTECH: MS_SET_TOUCHPAD_SETTINGS\n");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings));
return B_OK;
case MS_SET_CLICKSPEED:
TRACE("ELANTECH: ioctl MS_SETCLICK (set click speed)\n");
return user_memcpy(&cookie->movementMaker.click_speed, buffer,
sizeof(bigtime_t));
case MS_READ_TOUCHPAD:
TRACE("ELANTECH: MS_READ get event\n");
if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
if ((status = get_elantech_movement(cookie, &read.u.touchpad, read.timeout)) != B_OK)
return status;
read.event = MS_READ_TOUCHPAD;
return user_memcpy(buffer, &read, sizeof(read));
default:
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;
// we got a real event cancel the fake event
gEventProducer.CancelEvent();
uint8 val;
val = cookie->dev->history[0].data;
cookie->buffer[cookie->packet_index] = val;
@ -771,9 +682,9 @@ elantech_handle_int(ps2_dev* dev)
if (packet_buffer_write(cookie->ring_buffer,
cookie->buffer, cookie->dev->packet_size)
!= cookie->dev->packet_size) {
// buffer is full, drop new data
return B_HANDLED_INTERRUPT;
}
// buffer is full, drop new data
return B_HANDLED_INTERRUPT;
}
release_sem_etc(cookie->sem, 1, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER;
}

View File

@ -14,9 +14,6 @@
#include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h"
#include "ps2_dev.h"
@ -28,9 +25,6 @@ typedef struct {
struct packet_buffer* ring_buffer;
size_t packet_index;
TouchpadMovement movementMaker;
touchpad_settings settings;
uint32 version;
uint32 fwVersion;
@ -47,7 +41,6 @@ typedef struct {
uint8 mode;
bool crcEnabled;
status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count);
} elantech_cookie;

View File

@ -28,6 +28,15 @@
# define TRACE(x...)
#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
#define SYN_EDGE_MOTION_WIDTH 50
#define SYN_AREA_OFFSET 40
@ -52,7 +61,7 @@ enum {
kTrackpointQuirk = 0x10
};
static hardware_specs gHardwareSpecs;
static touchpad_specs gHardwareSpecs;
const char* kSynapticsPath[4] = {
@ -67,13 +76,6 @@ static touchpad_info sTouchpadInfo;
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
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
get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
get_synaptics_movment(synaptics_cookie *cookie, touchpad_movement *_event, bigtime_t timeout)
{
status_t status;
touch_event event;
touchpad_movement event;
uint8 event_buffer[PS2_MAX_PACKET_SIZE];
uint8 wValue0, wValue1, wValue2, wValue3, wValue;
uint32 val32;
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)
return status;
@ -164,7 +167,7 @@ get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
wValue = wValue | (wValue2 << 2);
wValue = wValue | (wValue3 << 3);
event.wValue = wValue;
event.fingerWidth = wValue;
event.gesture = false;
// 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;
if (finger) {
// finger with normal width
event.wValue = 4;
event.fingerWidth = 4;
}
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;
event.yPosition += yTwelfBit << 12;
status = cookie->movementMaker.EventToMovement(&event, movement);
return status;
*_event = event;
return B_OK;
}
@ -460,7 +462,6 @@ synaptics_open(const char *name, uint32 flags, void **_cookie)
goto err1;
memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
*_cookie = cookie;
cookie->dev = dev;
@ -468,8 +469,6 @@ synaptics_open(const char *name, uint32 flags, void **_cookie)
dev->disconnect = &synaptics_disconnect;
dev->handle_int = &synaptics_handle_int;
default_settings(&cookie->settings);
gHardwareSpecs.edgeMotionWidth = SYN_EDGE_MOTION_WIDTH;
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.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
dev->packet_size = PS2_PACKET_SYNAPTICS;
cookie->synaptics_ring_buffer
@ -607,29 +603,25 @@ status_t
synaptics_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{
synaptics_cookie *cookie = (synaptics_cookie*)_cookie;
mouse_movement movement;
touchpad_read read;
status_t status;
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:
TRACE("SYNAPTICS: MS_IS_TOUCHPAD\n");
return B_OK;
if (buffer == NULL)
return B_OK;
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
case MS_SET_TOUCHPAD_SETTINGS:
TRACE("SYNAPTICS: MS_SET_TOUCHPAD_SETTINGS");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings));
return B_OK;
case MS_SET_CLICKSPEED:
TRACE("SYNAPTICS: ioctl MS_SETCLICK (set click speed)\n");
return user_memcpy(&cookie->movementMaker.click_speed, buffer,
sizeof(bigtime_t));
case MS_READ_TOUCHPAD:
TRACE("SYNAPTICS: MS_READ get event\n");
if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
sizeof(bigtime_t)) != B_OK)
return B_BAD_ADDRESS;
if ((status = get_synaptics_movment(cookie, &read.u.touchpad, read.timeout)) != B_OK)
return status;
read.event = MS_READ_TOUCHPAD;
return user_memcpy(buffer, &read, sizeof(read));
default:
TRACE("SYNAPTICS: unknown opcode: %" B_PRIu32 "\n", op);

View File

@ -11,9 +11,6 @@
#include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h"
#include "ps2_service.h"
@ -65,10 +62,6 @@ struct packet_buffer* synaptics_ring_buffer;
size_t packet_index;
uint8 buffer[PS2_PACKET_SYNAPTICS];
uint8 mode;
TouchpadMovement movementMaker;
touchpad_settings settings;
} synaptics_cookie;

View File

@ -15,7 +15,7 @@
#include <List.h>
#include <String.h>
#include <keyboard_mouse_driver.h>
#include <InputServerDevice.h>
TouchpadPref::TouchpadPref(BInputDevice* device)
@ -63,7 +63,7 @@ TouchpadPref::UpdateSettings()
msg.AddInt8("tapgesture_sensibility", fSettings.tapgesture_sensibility);
msg.AddInt32("padblocker_threshold", fSettings.padblocker_threshold);
return fTouchPad->Control(MS_SET_TOUCHPAD_SETTINGS, &msg);
return fTouchPad->Control(B_SET_TOUCHPAD_SETTINGS, &msg);
}