* Refactored the former touchevent_to_movement() code to get rid of the gotos,

and some code duplication.
* Fixed the missing click count in the former "movement" label (now in the
  move_to_movement() function); the click count was always 0 in that case,
  this was most obvious with Firefox where you couldn't click anything as long
  as you had a finger on the touchpad.
* Made the functions static that aren't exported to the outside.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33469 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-10-06 16:19:34 +00:00
parent fc548b41f3
commit 34eb485aea
3 changed files with 251 additions and 231 deletions
@@ -133,7 +133,7 @@ ps2_dev_detect_pointing(ps2_dev *dev, device_hooks **hooks)
dev_found:
if (dev == &(ps2_device[PS2_DEVICE_SYN_PASSTHROUGH]))
synaptics_pt_set_packagesize(dev, dev->packet_size);
synaptics_pass_through_set_packet_size(dev, dev->packet_size);
return B_OK;
}
@@ -4,6 +4,7 @@
*
* Authors (in chronological order):
* Clemens Zeidler (haiku@Clemens-Zeidler.de)
* Axel Dörfler, axeld@pinc-software.de
*/
@@ -32,51 +33,14 @@ static touchpad_info sTouchpadInfo;
static ps2_dev *sPassthroughDevice = &ps2_device[PS2_DEVICE_SYN_PASSTHROUGH];
void
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
status_t
synaptics_pt_set_packagesize(ps2_dev *dev, uint8 size)
{
synaptics_cookie *synapticsCookie = dev->parent_dev->cookie;
status_t status = ps2_dev_command(dev->parent_dev, PS2_CMD_DISABLE, NULL,
0, NULL, 0);
if (status < B_OK) {
INFO("SYNAPTICS: cannot disable touchpad %s\n", dev->parent_dev->name);
return B_ERROR;
}
synapticsCookie->packet_index = 0;
if (size == 4)
synapticsCookie->mode |= SYN_FOUR_BYTE_CHILD;
else
synapticsCookie->mode &= ~SYN_FOUR_BYTE_CHILD;
set_touchpad_mode(dev->parent_dev, synapticsCookie->mode);
status = ps2_dev_command(dev->parent_dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
if (status < B_OK) {
INFO("SYNAPTICS: cannot enable touchpad %s\n", dev->parent_dev->name);
return B_ERROR;
}
return status;
}
status_t
send_touchpad_arg(ps2_dev *dev, uint8 arg)
{
return send_touchpad_arg_timeout(dev, arg, 4000000);
}
status_t
static status_t
send_touchpad_arg_timeout(ps2_dev *dev, uint8 arg, bigtime_t timeout)
{
int8 i;
@@ -89,7 +53,14 @@ send_touchpad_arg_timeout(ps2_dev *dev, uint8 arg, bigtime_t timeout)
}
status_t
static status_t
send_touchpad_arg(ps2_dev *dev, uint8 arg)
{
return send_touchpad_arg_timeout(dev, arg, 4000000);
}
static status_t
set_touchpad_mode(ps2_dev *dev, uint8 mode)
{
uint8 sample_rate = SYN_CHANGE_MODE;
@@ -99,65 +70,7 @@ set_touchpad_mode(ps2_dev *dev, uint8 mode)
}
status_t
passthrough_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int outCount,
uint8 *in, int inCount, bigtime_t timeout)
{
status_t status;
uint8 passThroughCmd = SYN_PASSTHROUGH_CMD;
uint8 val;
uint32 passThroughInCount = (inCount + 1) * 6;
uint8 passThroughIn[passThroughInCount];
int8 i;
TRACE("SYNAPTICS: passthrough command 0x%x\n", cmd);
status = ps2_dev_command(dev->parent_dev, PS2_CMD_DISABLE, NULL, 0,
NULL, 0);
if (status != B_OK)
return status;
for (i = -1; i < outCount; i++) {
if (i == -1)
val = cmd;
else
val = out[i];
status = send_touchpad_arg_timeout(dev->parent_dev, val, timeout);
if (status != B_OK)
return status;
if (i != outCount -1) {
status = ps2_dev_command_timeout(dev->parent_dev,
PS2_CMD_SET_SAMPLE_RATE, &passThroughCmd, 1, NULL, 0, timeout);
if (status != B_OK)
return status;
}
}
status = ps2_dev_command_timeout(dev->parent_dev, PS2_CMD_SET_SAMPLE_RATE,
&passThroughCmd, 1, passThroughIn, passThroughInCount, timeout);
if (status != B_OK)
return status;
for (i = 0; i < inCount + 1; i++) {
uint8 *inPointer = &passThroughIn[i * 6];
if (!IS_SYN_PT_PACKAGE(inPointer)) {
TRACE("SYNAPTICS: not a pass throught package\n");
return B_OK;
}
if (i == 0)
continue;
in[i - 1] = passThroughIn[i * 6 + 1];
}
status = ps2_dev_command(dev->parent_dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
if (status != B_OK)
return status;
return B_OK;
}
bool
static bool
edge_motion(mouse_movement *movement, touch_event *event, bool validStart)
{
int32 xdelta = 0;
@@ -185,85 +98,89 @@ edge_motion(mouse_movement *movement, touch_event *event, bool validStart)
}
status_t
touchevent_to_movement(synaptics_cookie* cookie, touch_event *event,
/*! If a button has been clicked (movement->buttons must be set accordingly),
this function updates the click_count of the \a cookie, as well as the
\a movement's clicks field.
Also, it sets the cookie's button state from movement->buttons.
*/
static inline void
update_buttons(synaptics_cookie *cookie, mouse_movement *movement)
{
// set click count correctly according to double click timeout
if (movement->buttons != 0 && cookie->buttons_state == 0) {
if (cookie->click_last_time + cookie->click_speed > movement->timestamp)
cookie->click_count++;
else
cookie->click_count = 1;
cookie->click_last_time = movement->timestamp;
}
if (movement->buttons != 0)
movement->clicks = cookie->click_count;
cookie->buttons_state = movement->buttons;
}
static inline void
no_touch_to_movement(synaptics_cookie *cookie, touch_event *event,
mouse_movement *movement)
{
bool isSideScrollingV = false;
bool isSideScrollingH = false;
bool isInTouch = false;
bool isStartOfMovement = false;
float sens = 0;
bigtime_t currentTime = system_time();
touchpad_settings *settings = &cookie->settings;
uint32 buttons = event->buttons;
if (!movement)
return B_ERROR;
TRACE("SYNAPTICS: no touch event\n");
movement->xdelta = 0;
movement->ydelta = 0;
movement->buttons = 0;
movement->wheel_ydelta = 0;
movement->wheel_xdelta = 0;
movement->modifiers = 0;
movement->clicks = 0;
movement->timestamp = currentTime;
cookie->scrolling_started = false;
cookie->movement_started = false;
if ((currentTime - cookie->tap_time) > SYN_TAP_TIMEOUT) {
TRACE("SYNAPTICS: tap gesture timed out\n");
cookie->tap_started = false;
if (!cookie->double_click
|| (currentTime - cookie->tap_time) > 2 * SYN_TAP_TIMEOUT) {
cookie->tap_clicks = 0;
}
if (cookie->tapdrag_started
&& (movement->timestamp - cookie->tap_time) < SYN_TAP_TIMEOUT) {
buttons = 0x01;
}
if (event->buttons != 0) {
cookie->tap_clicks = 0;
// if the movement stopped switch off the tap drag when timeout is expired
if ((movement->timestamp - cookie->tap_time) > SYN_TAP_TIMEOUT) {
cookie->tapdrag_started = false;
cookie->tap_started = false;
cookie->valid_edge_motion = false;
TRACE("SYNAPTICS: tap drag gesture timed out\n");
}
if (event->zPressure >= MIN_PRESSURE && event->zPressure < MAX_PRESSURE
&& ((event->wValue >=4 && event->wValue <=7)
|| event->wValue == 0 || event->wValue == 1)
&& (event->xPosition != 0 || event->yPosition != 0)) {
isInTouch = true;
if (abs(cookie->tap_delta_x) > 15 || abs(cookie->tap_delta_y) > 15) {
cookie->tap_started = false;
cookie->tap_clicks = 0;
}
if (isInTouch) {
if ((SYN_AREA_END_X - SYN_AREA_WIDTH_X * settings->scroll_rightrange
< event->xPosition && !cookie->movement_started
&& settings->scroll_rightrange > 0.000001)
|| settings->scroll_rightrange > 0.999999) {
isSideScrollingV = true;
}
if ((SYN_AREA_START_Y + SYN_AREA_WIDTH_Y * settings->scroll_bottomrange
> event->yPosition && !cookie->movement_started
&& settings->scroll_bottomrange > 0.000001)
|| settings->scroll_bottomrange > 0.999999) {
isSideScrollingH = true;
}
if ((event->wValue == 0 || event->wValue == 1)
&& settings->scroll_twofinger) {
// two finger scrolling is enabled
isSideScrollingV = true;
isSideScrollingH = settings->scroll_twofinger_horizontal;
}
if (cookie->tap_started || cookie->double_click) {
TRACE("SYNAPTICS: tap gesture\n");
cookie->tap_clicks++;
if (isSideScrollingV || isSideScrollingH)
goto scrolling;
else
cookie->scrolling_started = false;
goto movement;
} else {
goto notouch;
if (cookie->tap_clicks > 1) {
TRACE("SYNAPTICS: empty click\n");
buttons = 0x00;
cookie->tap_clicks = 0;
cookie->double_click = true;
} else {
buttons = 0x01;
cookie->tap_started = false;
cookie->tapdrag_started = true;
cookie->double_click = false;
}
}
movement:
movement->buttons = buttons;
update_buttons(cookie, movement);
}
static inline void
move_to_movement(synaptics_cookie *cookie, touch_event *event,
mouse_movement *movement)
{
touchpad_settings *settings = &cookie->settings;
bool isStartOfMovement = false;
float pressure = 0;
TRACE("SYNAPTICS: movement event\n");
if (!cookie->movement_started) {
isStartOfMovement = true;
@@ -294,11 +211,11 @@ movement:
// use only a fraction of pressure range, the max pressure seems to be
// to high
sens = 20 * (event->zPressure - MIN_PRESSURE)
pressure = 20 * (event->zPressure - MIN_PRESSURE)
/ (MAX_PRESSURE - MIN_PRESSURE - 100);
if (!cookie->tap_started
&& isStartOfMovement
&& settings->tapgesture_sensibility > (20 - sens)) {
&& settings->tapgesture_sensibility > (20 - pressure)) {
TRACE("SYNAPTICS: tap started\n");
cookie->tap_started = true;
cookie->tap_time = system_time();
@@ -306,12 +223,49 @@ movement:
cookie->tap_delta_y = 0;
}
cookie->buttons_state = movement->buttons;
update_buttons(cookie, movement);
}
return B_OK;
scrolling:
/*! Checks if this is a scrolling event or not, and also actually does the
scrolling work if it is.
\return \c true if this was a scrolling event, \c false if not.
*/
static inline bool
check_scrolling_to_movement(synaptics_cookie *cookie, touch_event *event,
mouse_movement *movement)
{
touchpad_settings *settings = &cookie->settings;
bool isSideScrollingV = false;
bool isSideScrollingH = false;
if ((SYN_AREA_END_X - SYN_AREA_WIDTH_X * settings->scroll_rightrange
< event->xPosition && !cookie->movement_started
&& settings->scroll_rightrange > 0.000001)
|| settings->scroll_rightrange > 0.999999) {
isSideScrollingV = true;
}
if ((SYN_AREA_START_Y + SYN_AREA_WIDTH_Y * settings->scroll_bottomrange
> event->yPosition && !cookie->movement_started
&& settings->scroll_bottomrange > 0.000001)
|| settings->scroll_bottomrange > 0.999999) {
isSideScrollingH = true;
}
if ((event->wValue == 0 || event->wValue == 1)
&& settings->scroll_twofinger) {
// two finger scrolling is enabled
isSideScrollingV = true;
isSideScrollingH = settings->scroll_twofinger_horizontal;
}
if (!isSideScrollingV && !isSideScrollingH) {
cookie->scrolling_started = false;
return false;
}
TRACE("SYNAPTICS: scroll event\n");
cookie->tap_started = false;
cookie->tap_clicks = 0;
cookie->tapdrag_started = false;
@@ -332,67 +286,57 @@ scrolling:
cookie->buttons_state = movement->buttons;
return B_OK;
return true;
}
notouch:
TRACE("SYNAPTICS: no touch event\n");
cookie->scrolling_started = false;
cookie->movement_started = false;
if (cookie->tapdrag_started
&& (currentTime - cookie->tap_time) < SYN_TAP_TIMEOUT) {
buttons = 0x01;
}
static status_t
event_to_movement(synaptics_cookie *cookie, touch_event *event,
mouse_movement *movement)
{
if (!movement)
return B_ERROR;
// if the movement stopped switch off the tap drag when timeout is expired
if ((currentTime - cookie->tap_time) > SYN_TAP_TIMEOUT) {
cookie->tapdrag_started = false;
cookie->valid_edge_motion = false;
TRACE("SYNAPTICS: tap drag gesture timed out\n");
}
movement->xdelta = 0;
movement->ydelta = 0;
movement->buttons = 0;
movement->wheel_ydelta = 0;
movement->wheel_xdelta = 0;
movement->modifiers = 0;
movement->clicks = 0;
movement->timestamp = system_time();
if (abs(cookie->tap_delta_x) > 15 || abs(cookie->tap_delta_y) > 15) {
if ((movement->timestamp - cookie->tap_time) > SYN_TAP_TIMEOUT) {
TRACE("SYNAPTICS: tap gesture timed out\n");
cookie->tap_started = false;
cookie->tap_clicks = 0;
}
if (cookie->tap_started || cookie->double_click) {
TRACE("SYNAPTICS: tap gesture\n");
cookie->tap_clicks++;
if (cookie->tap_clicks > 1) {
TRACE("SYNAPTICS: empty click\n");
buttons = 0x00;
if (!cookie->double_click
|| (movement->timestamp - cookie->tap_time) > 2 * SYN_TAP_TIMEOUT) {
cookie->tap_clicks = 0;
cookie->double_click = true;
} else {
buttons = 0x01;
cookie->tap_started = false;
cookie->tapdrag_started = true;
cookie->double_click = false;
}
}
// set click count correctly according to double click timeout
if (buttons != 0 && cookie->buttons_state == 0) {
if (cookie->click_last_time + cookie->click_speed > currentTime)
cookie->click_count++;
else
cookie->click_count = 1;
cookie->click_last_time = currentTime;
if (event->buttons != 0) {
cookie->tap_clicks = 0;
cookie->tapdrag_started = false;
cookie->tap_started = false;
cookie->valid_edge_motion = false;
}
movement->buttons = buttons;
cookie->buttons_state = buttons;
if (buttons)
movement->clicks = cookie->click_count;
if (event->zPressure >= MIN_PRESSURE && event->zPressure < MAX_PRESSURE
&& ((event->wValue >=4 && event->wValue <=7)
|| event->wValue == 0 || event->wValue == 1)
&& (event->xPosition != 0 || event->yPosition != 0)) {
// The touch pad is in touch with at least one finger
if (!check_scrolling_to_movement(cookie, event, movement))
move_to_movement(cookie, event, movement);
} else
no_touch_to_movement(cookie, event, movement);
return B_OK;
}
status_t
static status_t
get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
{
status_t status;
@@ -455,13 +399,13 @@ get_synaptics_movment(synaptics_cookie *cookie, mouse_movement *movement)
yTwelfBit = event_buffer[3] >> 5 & 1;
event.yPosition += yTwelfBit << 12;
status = touchevent_to_movement(cookie, &event, movement);
status = event_to_movement(cookie, &event, movement);
return B_OK;
}
void
static void
query_capability(ps2_dev *dev)
{
uint8 val[3];
@@ -483,7 +427,95 @@ query_capability(ps2_dev *dev)
}
// #pragma mark -
// #pragma mark - exported functions
status_t
synaptics_pass_through_set_packet_size(ps2_dev *dev, uint8 size)
{
synaptics_cookie *synapticsCookie = dev->parent_dev->cookie;
status_t status = ps2_dev_command(dev->parent_dev, PS2_CMD_DISABLE, NULL,
0, NULL, 0);
if (status < B_OK) {
INFO("SYNAPTICS: cannot disable touchpad %s\n", dev->parent_dev->name);
return B_ERROR;
}
synapticsCookie->packet_index = 0;
if (size == 4)
synapticsCookie->mode |= SYN_FOUR_BYTE_CHILD;
else
synapticsCookie->mode &= ~SYN_FOUR_BYTE_CHILD;
set_touchpad_mode(dev->parent_dev, synapticsCookie->mode);
status = ps2_dev_command(dev->parent_dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
if (status < B_OK) {
INFO("SYNAPTICS: cannot enable touchpad %s\n", dev->parent_dev->name);
return B_ERROR;
}
return status;
}
status_t
passthrough_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int outCount,
uint8 *in, int inCount, bigtime_t timeout)
{
status_t status;
uint8 passThroughCmd = SYN_PASSTHROUGH_CMD;
uint8 val;
uint32 passThroughInCount = (inCount + 1) * 6;
uint8 passThroughIn[passThroughInCount];
int8 i;
TRACE("SYNAPTICS: passthrough command 0x%x\n", cmd);
status = ps2_dev_command(dev->parent_dev, PS2_CMD_DISABLE, NULL, 0,
NULL, 0);
if (status != B_OK)
return status;
for (i = -1; i < outCount; i++) {
if (i == -1)
val = cmd;
else
val = out[i];
status = send_touchpad_arg_timeout(dev->parent_dev, val, timeout);
if (status != B_OK)
return status;
if (i != outCount -1) {
status = ps2_dev_command_timeout(dev->parent_dev,
PS2_CMD_SET_SAMPLE_RATE, &passThroughCmd, 1, NULL, 0, timeout);
if (status != B_OK)
return status;
}
}
status = ps2_dev_command_timeout(dev->parent_dev, PS2_CMD_SET_SAMPLE_RATE,
&passThroughCmd, 1, passThroughIn, passThroughInCount, timeout);
if (status != B_OK)
return status;
for (i = 0; i < inCount + 1; i++) {
uint8 *inPointer = &passThroughIn[i * 6];
if (!IS_SYN_PT_PACKAGE(inPointer)) {
TRACE("SYNAPTICS: not a pass throught package\n");
return B_OK;
}
if (i == 0)
continue;
in[i - 1] = passThroughIn[i * 6 + 1];
}
status = ps2_dev_command(dev->parent_dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
if (status != B_OK)
return status;
return B_OK;
}
status_t
@@ -5,8 +5,8 @@
* Authors (in chronological order):
* Clemens Zeidler (haiku@Clemens-Zeidler.de)
*/
#ifndef SYNAPTICS_H
#define SYNAPTICS_H
#ifndef PS2_SYNAPTICS_H
#define PS2_SYNAPTICS_H
#include <KernelExport.h>
@@ -64,7 +64,6 @@ typedef struct {
bool capMultiFinger;
bool capPalmDetection;
bool capPassThrough;
} touchpad_info;
@@ -111,21 +110,10 @@ typedef struct {
} synaptics_cookie;
void default_settings(touchpad_settings *settings);
status_t synaptics_pt_set_packagesize(ps2_dev *dev, uint8 size);
status_t send_touchpad_arg(ps2_dev *dev, uint8 arg);
status_t send_touchpad_arg_timeout(ps2_dev *dev, uint8 arg, bigtime_t timeout);
status_t set_touchpad_mode(ps2_dev *dev, uint8 mode);
status_t synaptics_pass_through_set_packet_size(ps2_dev *dev, uint8 size);
status_t passthrough_command(ps2_dev *dev, uint8 cmd, const uint8 *out,
int out_count, uint8 *in, int in_count, bigtime_t timeout);
bool edge_motion(mouse_movement *movement, touch_event *event, bool validStart);
status_t touchevent_to_movement(synaptics_cookie* cookie, touch_event *event,
mouse_movement *movement);
status_t get_synaptics_movment(synaptics_cookie* cookie,
mouse_movement *movement);
void query_capability(ps2_dev *dev);
status_t probe_synaptics(ps2_dev *dev);
status_t synaptics_open(const char *name, uint32 flags, void **_cookie);
@@ -138,4 +126,4 @@ void synaptics_disconnect(ps2_dev *dev);
device_hooks gSynapticsDeviceHooks;
#endif
#endif // PS2_SYNAPTICS_H