Author: axeld Date: 2009-10-06 18:19:34 +0200 (Tue, 06 Oct 2009) New Revision: 33469 Changeset: http://dev.haiku-os.org/changeset/33469/haiku Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.c haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h Log: * 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. Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c 2009-10-06 14:30:57 UTC (rev 33468) +++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c 2009-10-06 16:19:34 UTC (rev 33469) @@ -133,7 +133,7 @@ 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; } Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.c =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.c 2009-10-06 14:30:57 UTC (rev 33468) +++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.c 2009-10-06 16:19:34 UTC (rev 33469) @@ -4,6 +4,7 @@ * * Authors (in chronological order): * Clemens Zeidler (haiku@xxxxxxxxxxxxxxxxxx) + * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx */ @@ -32,51 +33,14 @@ 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 @@ } -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 @@ } -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 @@ } -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 (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; + cookie->tap_clicks = 0; + cookie->double_click = true; + } else { + buttons = 0x01; + cookie->tap_started = false; + cookie->tapdrag_started = true; + cookie->double_click = false; } - 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) - goto scrolling; - else - cookie->scrolling_started = false; + movement->buttons = buttons; + update_buttons(cookie, movement); +} - goto movement; - } else { - goto notouch; - } -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 @@ // 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 @@ 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 @@ 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 @@ 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,10 +427,98 @@ } -// #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 probe_synaptics(ps2_dev *dev) { uint8 val[3]; Modified: haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h 2009-10-06 14:30:57 UTC (rev 33468) +++ haiku/trunk/src/add-ons/kernel/bus_managers/ps2/ps2_synaptics.h 2009-10-06 16:19:34 UTC (rev 33469) @@ -5,8 +5,8 @@ * Authors (in chronological order): * Clemens Zeidler (haiku@xxxxxxxxxxxxxxxxxx) */ -#ifndef SYNAPTICS_H -#define SYNAPTICS_H +#ifndef PS2_SYNAPTICS_H +#define PS2_SYNAPTICS_H #include <KernelExport.h> @@ -64,7 +64,6 @@ bool capMultiFinger; bool capPalmDetection; bool capPassThrough; - } touchpad_info; @@ -111,21 +110,10 @@ } 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 @@ device_hooks gSynapticsDeviceHooks; -#endif +#endif // PS2_SYNAPTICS_H