Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -uprN a/include/synaptics-properties.h b/include/synaptics-properties.h
- --- a/include/synaptics-properties.h 2011-02-20 20:46:37.000000000 -0500
- +++ b/include/synaptics-properties.h 2011-03-19 18:07:43.268845823 -0400
- @@ -155,6 +155,15 @@
- /* 32 bit, 4 values, left, right, top, bottom */
- #define SYNAPTICS_PROP_AREA "Synaptics Area"
- +/* 8 bit (BOOL, read-only), has_led */
- +#define SYNAPTICS_PROP_LED "Synaptics LED"
- +
- +/* 8 bit (BOOL), led_status (on/off) */
- +#define SYNAPTICS_PROP_LED_STATUS "Synaptics LED Status"
- +
- +/* 8 bit (BOOL), double-tap action on LED corner (on/off) */
- +#define SYNAPTICS_PROP_LED_DOUBLE_TAP "Synaptics LED Dobule Tap"
- +
- /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */
- #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation"
- diff -uprN a/man/synaptics.man b/man/synaptics.man
- --- a/man/synaptics.man 2011-02-20 20:50:51.000000000 -0500
- +++ b/man/synaptics.man 2011-03-19 18:07:43.269845760 -0400
- @@ -564,6 +564,19 @@ coordinates are less than MaxTapMove uni
- A "touch" event happens when the Z value goes above FingerHigh, and an
- "untouch" event happens when the Z value goes below FingerLow.
- .
- +.TP
- +.BI "Option \*qLEDDoubleTap\*q \*q" boolean \*q
- +.
- +Enables/disables the touchpad-control by double-tapping on the top-left
- +corner LED.
- +.
- +Some devices have an LED on the top-left corner to indicate the
- +touchpad state. User can double-tap on the LED to toggle the touchpad
- +state. This option controls whether this action is enabled or not.
- +The double-tap size is same as specified in MaxDoubleTapTime.
- +The default value is ON.
- +Property: "Synaptics LED Double Tap"
- +.
- .LP
- The MaxDoubleTapTime parameter has the same function as the MaxTapTime
- parameter, but for the second, third, etc tap in a tap sequence.
- @@ -753,6 +766,15 @@ and finger movement distance.
- Trackstick mode is exited when the finger pressure drops below
- FingerLow or when the finger is moved further than MaxTapMove away
- from the initial position.
- +.
- +When the input device reports a device with a single left button
- +and without multi-fingers, the driver assumes it's a Synaptics
- +Clickpad device and handles it in ClickZone mode. In this mode,
- +a left/right/middle button event is generated according to the
- +position you click. When Clickpad is enabled, the touchpad area
- +is shrunk as default in 20% and the bottom area is used as the
- +click-button area. The area can be configurable via options or
- +properties below.
- .SH "DEVICE PROPERTIES"
- Synaptics 1.0 and higher support input device properties if the driver is
- @@ -927,6 +949,19 @@ right button, two-finger detection, thre
- .BI "Synaptics Pad Resolution"
- 32 bit unsigned, 2 values (read-only), vertical, horizontal in units/millimeter.
- +.TP 7
- +.BI "Synaptics LED"
- +8 bit (BOOL, read-only), indicating whether the device has an embedded
- +LED support or not.
- +
- +.TP 7
- +.BI "Synaptics LED Status"
- +8 bit (BOOL), the light status of the embedded LED.
- +
- +.TP 7
- +.BI "Synaptics LED Double Tap"
- +8 bit (BOOL), enable/disable the double-tap on LED.
- +
- .SH "NOTES"
- There is an example hal policy file in
- .I ${sourcecode}/fdi/11-x11-synaptics.fdi
- diff -uprN a/src/eventcomm.c b/src/eventcomm.c
- --- a/src/eventcomm.c 2011-03-03 21:35:56.000000000 -0500
- +++ b/src/eventcomm.c 2011-03-19 18:07:39.623954123 -0400
- @@ -51,6 +51,8 @@
- #define LONG(x) ((x) / LONG_BITS)
- #define TEST_BIT(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
- +#define SYNAPTICS_LED_SYS_FILE "/sys/class/leds/psmouse::synaptics/brightness"
- +
- /*****************************************************************************
- * Function Definitions
- ****************************************************************************/
- @@ -166,6 +168,32 @@ event_query_info(InputInfoPtr pInfo)
- }
- }
- +static void
- +event_query_led(InputInfoPtr pInfo)
- +{
- + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
- +
- + priv->synpara.has_led = !access(SYNAPTICS_LED_SYS_FILE, W_OK);
- +}
- +
- +static void EventUpdateLED(InputInfoPtr pInfo)
- +{
- + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
- +
- + if (priv->synpara.has_led) {
- + char *val = priv->synpara.led_status ? "255" : "0";
- + int fd = open(SYNAPTICS_LED_SYS_FILE, O_WRONLY);
- + int err;
- +
- + if (fd < 0)
- + return;
- + err = write(fd, val, strlen(val));
- + close(fd);
- + if (err < 0)
- + xf86Msg(X_WARNING, "%s can't write LED value %s\n", pInfo->name, val);
- + }
- +}
- +
- /* Query device for axis ranges */
- static void
- event_query_axis_ranges(InputInfoPtr pInfo)
- @@ -266,6 +294,13 @@ event_query_axis_ranges(InputInfoPtr pIn
- strcat(buf, " double");
- if ((priv->has_triple = (TEST_BIT(BTN_TOOL_TRIPLETAP, keybits) != 0)))
- strcat(buf, " triple");
- +
- + /* clickpad device reports only the single left button mask */
- + if (priv->has_left && !priv->has_right && !priv->has_middle) {
- + priv->is_clickpad = TRUE;
- + xf86Msg(X_INFO, "%s: is Clickpad device\n", pInfo->name);
- + }
- +
- if ((TEST_BIT(BTN_0, keybits) != 0) ||
- (TEST_BIT(BTN_1, keybits) != 0) ||
- @@ -436,6 +471,7 @@ EventReadDevDimensions(InputInfoPtr pInf
- if (event_query_is_touchpad(pInfo->fd, (need_grab) ? *need_grab : TRUE))
- event_query_axis_ranges(pInfo);
- event_query_info(pInfo);
- + event_query_led(pInfo);
- }
- static Bool
- @@ -495,5 +531,6 @@ struct SynapticsProtocolOperations event
- EventQueryHardware,
- EventReadHwState,
- EventAutoDevProbe,
- - EventReadDevDimensions
- + EventReadDevDimensions,
- + EventUpdateLED,
- };
- diff -uprN a/src/properties.c b/src/properties.c
- --- a/src/properties.c 2011-02-20 20:46:37.000000000 -0500
- +++ b/src/properties.c 2011-03-19 18:07:43.271845640 -0400
- @@ -82,6 +82,9 @@ Atom prop_gestures = 0;
- Atom prop_capabilities = 0;
- Atom prop_resolution = 0;
- Atom prop_area = 0;
- +Atom prop_led = 0;
- +Atom prop_led_status = 0;
- +Atom prop_led_double_tap = 0;
- Atom prop_noise_cancellation = 0;
- static Atom
- @@ -280,6 +283,11 @@ InitDeviceProperties(InputInfoPtr pInfo)
- values[3] = para->area_bottom_edge;
- prop_area = InitAtom(pInfo->dev, SYNAPTICS_PROP_AREA, 32, 4, values);
- + prop_led = InitAtom(pInfo->dev, SYNAPTICS_PROP_LED, 8, 1, ¶->has_led);
- + prop_led_status = InitAtom(pInfo->dev, SYNAPTICS_PROP_LED_STATUS, 8, 1, ¶->led_status);
- + prop_led_double_tap = InitAtom(pInfo->dev, SYNAPTICS_PROP_LED_DOUBLE_TAP, 8, 1, ¶->led_double_tap);
- +
- +
- values[0] = para->hyst_x;
- values[1] = para->hyst_y;
- prop_noise_cancellation = InitAtom(pInfo->dev,
- @@ -510,6 +518,19 @@ SetProperty(DeviceIntPtr dev, Atom prope
- return BadValue;
- para->touchpad_off = off;
- + if (!checkonly && para->has_led &&
- + para->led_status != para->touchpad_off) {
- + para->led_status = para->touchpad_off;
- + if (priv->proto_ops && priv->proto_ops->UpdateLED)
- + priv->proto_ops->UpdateLED(pInfo);
- + }
- + } else if (property == prop_led_double_tap)
- + {
- + if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
- + return BadMatch;
- +
- + para->led_double_tap = *(CARD8*)prop->data;
- +
- } else if (property == prop_gestures)
- {
- BOOL *gestures;
- @@ -656,6 +677,16 @@ SetProperty(DeviceIntPtr dev, Atom prope
- para->area_right_edge = area[1];
- para->area_top_edge = area[2];
- para->area_bottom_edge = area[3];
- + } else if (property == prop_led_status)
- + {
- + if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
- + return BadMatch;
- +
- + if (para->has_led) {
- + para->led_status = *(BOOL*)prop->data;
- + if (priv->proto_ops && priv->proto_ops->UpdateLED)
- + priv->proto_ops->UpdateLED(pInfo);
- + }
- } else if (property == prop_noise_cancellation) {
- INT32 *hyst;
- if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
- @@ -671,3 +702,13 @@ SetProperty(DeviceIntPtr dev, Atom prope
- return Success;
- }
- +void SynapticsToggleOffProperty(DeviceIntPtr dev, Bool off)
- +{
- + uint8_t val;
- +
- + if (!prop_off)
- + return;
- + val = off;
- + XIChangeDeviceProperty(dev, prop_off, XA_INTEGER, 8,
- + PropModeReplace, 1, &val, FALSE);
- +}
- diff -uprN a/src/synaptics.c b/src/synaptics.c
- --- a/src/synaptics.c 2011-03-03 21:36:15.000000000 -0500
- +++ b/src/synaptics.c 2011-03-19 18:07:43.273845526 -0400
- @@ -134,6 +134,7 @@ static void CalculateScalingCoeffs(Synap
- void InitDeviceProperties(InputInfoPtr pInfo);
- int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
- BOOL checkonly);
- +void SynapticsToggleOffProperty(DeviceIntPtr dev, Bool off);
- InputDriverRec SYNAPTICS = {
- 1,
- @@ -513,6 +514,18 @@ static void set_default_parameters(Input
- vertResolution = priv->resy;
- }
- + /* Clickpad mode -- bottom area is used as buttons */
- + if (priv->is_clickpad) {
- + int button_bottom;
- + /* Clickpad devices usually the button area at the bottom, and
- + * its size seems ca. 20% of the touchpad height no matter how
- + * large the pad is.
- + */
- + button_bottom = priv->maxy - (abs(priv->maxy - priv->miny) * 20) / 100;
- + if (button_bottom < b && button_bottom >= t)
- + b = button_bottom;
- + }
- +
- /* set the parameters */
- pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l);
- pars->right_edge = xf86SetIntOption(opts, "RightEdge", r);
- @@ -593,6 +606,7 @@ static void set_default_parameters(Input
- pars->tap_and_drag_gesture = xf86SetBoolOption(opts, "TapAndDragGesture", TRUE);
- pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution);
- pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution);
- + pars->led_double_tap = xf86SetBoolOption(opts, "LEDDoubleTap", TRUE);
- /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
- if (pars->top_edge > pars->bottom_edge) {
- @@ -876,6 +890,10 @@ DeviceOn(DeviceIntPtr dev)
- xf86AddEnabledDevice(pInfo);
- dev->public.on = TRUE;
- + /* update LED */
- + if (priv->proto_ops && priv->proto_ops->UpdateLED)
- + priv->proto_ops->UpdateLED(pInfo);
- +
- return Success;
- }
- @@ -1213,6 +1231,7 @@ timerFunc(OsTimerPtr timer, CARD32 now,
- {
- InputInfoPtr pInfo = arg;
- SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- + SynapticsParameters *para = &priv->synpara;
- struct SynapticsHwState hw;
- int delay;
- int sigstate;
- @@ -1224,6 +1243,13 @@ timerFunc(OsTimerPtr timer, CARD32 now,
- hw.millis = now;
- delay = HandleState(pInfo, &hw);
- +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
- + if (priv->prop_change_pending & 1) {
- + SynapticsToggleOffProperty(pInfo->dev, para->touchpad_off);
- + priv->prop_change_pending = 0;
- + }
- +#endif
- +
- /*
- * Workaround for wraparound bug in the TimerSet function. This bug is already
- * fixed in CVS, but this driver needs to work with XFree86 versions 4.2.x and
- @@ -1274,6 +1300,10 @@ ReadInput(InputInfoPtr pInfo)
- hw.millis = GetTimeInMillis();
- priv->hwState = hw;
- delay = HandleState(pInfo, &hw);
- +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
- + if (priv->prop_change_pending)
- + delay = MIN(10, delay);
- +#endif
- newDelay = TRUE;
- }
- @@ -2241,6 +2271,125 @@ handle_clickfinger(SynapticsParameters *
- }
- }
- +#define LED_TOGGLE_X_AREA 0.10
- +#define LED_TOGGLE_Y_AREA 0.08
- +
- +static int
- +in_led_toggle_area(InputInfoPtr pInfo, struct SynapticsHwState *hw)
- +{
- + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- + int click_led_x, click_led_y;
- +
- + click_led_x = (priv->maxx - priv->minx) * LED_TOGGLE_X_AREA + priv->minx;
- + click_led_y = (priv->maxy - priv->miny) * LED_TOGGLE_Y_AREA + priv->miny;
- + return (hw->x < click_led_x && hw->y < click_led_y);
- +}
- +
- +/* clicpad button toggle point:
- + * some devices have a LED at the upper-left corner, and double-tapping it
- + * toggles the touchpad enable/disable
- + */
- +static int
- +handle_toggle_led(InputInfoPtr pInfo, struct SynapticsHwState *hw, int finger)
- +{
- + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- + SynapticsParameters *para = &priv->synpara;
- + int diff;
- +
- + if (finger) {
- + if (!in_led_toggle_area(pInfo, hw)) {
- + /* outside the toggle area */
- + priv->led_touch_state = FALSE;
- + priv->led_tapped = FALSE;
- + return finger;
- + }
- + if (!priv->led_touch_state) {
- + /* touch start */
- + priv->led_touch_millis = hw->millis;
- + priv->led_touch_state = TRUE;
- + }
- + return 0; /* already processed; ignore this finger event */
- + }
- +
- + if (!priv->led_touch_state)
- + return finger; /* nothing happened */
- +
- + /* touch-released */
- + priv->led_touch_state = FALSE;
- + diff = TIME_DIFF(priv->led_touch_millis + para->tap_time, hw->millis);
- + if (diff < 0) { /* non-tap? */
- + priv->led_tapped = FALSE;
- + return finger;
- + }
- + if (priv->led_tapped) {
- + /* double-tapped? */
- + diff = TIME_DIFF(priv->led_tap_millis + para->tap_time_2, hw->millis);
- + if (diff >= 0) {
- + para->touchpad_off = !para->touchpad_off;
- + if (priv->proto_ops && priv->proto_ops->UpdateLED)
- + priv->proto_ops->UpdateLED(pInfo);
- + priv->prop_change_pending = 1;
- + priv->led_tapped = FALSE;
- + }
- + } else
- + priv->led_tapped = TRUE;
- + priv->led_tap_millis = hw->millis;
- + return 0; /* already processed; ignore this finger event */
- +}
- +
- +/* clickpad event handling */
- +static void
- +handle_clickpad(InputInfoPtr pInfo, struct SynapticsHwState *hw, edge_type edge)
- +{
- + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- + SynapticsParameters *para = &priv->synpara;
- +
- + if (edge & BOTTOM_EDGE) {
- + /* button area */
- + int width = priv->maxx - priv->minx;
- + int left_button_x, right_button_x;
- +
- + /* left and right clickpad button ranges;
- + * the gap between them is interpreted as a middle-button click
- + */
- + left_button_x = width * 2/ 5 + priv->minx;
- + right_button_x = width * 3 / 5 + priv->minx;
- +
- + /* clickpad reports only one button, and we need
- + * to fake left/right buttons depending on the touch position
- + */
- + if (hw->left) { /* clicked? */
- + hw->left = 0;
- + if (hw->x < left_button_x)
- + hw->left = 1;
- + else if (hw->x > right_button_x)
- + hw->right = 1;
- + else
- + hw->middle = 1;
- + }
- +
- + /* Don't move pointer position in the button area during clicked,
- + * except for horiz/vert scrolling is enabled.
- + *
- + * The synaptics driver tends to be pretty sensitive. This hack
- + * is to avoid that the pointer moves slightly and misses the
- + * poistion you aimed to click.
- + *
- + * Also, when the pointer movement is reported, the dragging
- + * (with a sort of multi-touching) doesn't work well, too.
- + */
- + if (hw->left || !(para->scroll_edge_horiz ||
- + ((edge & RIGHT_EDGE) && para->scroll_edge_vert)))
- + hw->z = 0; /* don't move pointer */
- +
- + } else if (hw->left) {
- + /* dragging */
- + hw->left = priv->prev_hw.left;
- + hw->right = priv->prev_hw.right;
- + hw->middle = priv->prev_hw.middle;
- + }
- + priv->prev_hw = *hw;
- +}
- /* Update the hardware state in shared memory. This is read-only these days,
- * nothing in the driver reads back from SHM. SHM configuration is a thing of the past.
- @@ -2314,6 +2463,12 @@ update_hw_button_state(const InputInfoPt
- SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- SynapticsParameters *para = &priv->synpara;
- + edge_type edge = edge_detection(priv, hw->x, hw->y);
- +
- + /* Clickpad handling for button area */
- + if (para->touchpad_off != 1 && priv->is_clickpad)
- + handle_clickpad(pInfo, hw, edge);
- +
- /* Treat the first two multi buttons as up/down for now. */
- hw->up |= hw->multi[0];
- hw->down |= hw->multi[1];
- @@ -2429,7 +2584,7 @@ HandleState(InputInfoPtr pInfo, struct S
- update_shm(pInfo, hw);
- /* If touchpad is switched off, we skip the whole thing and return delay */
- - if (para->touchpad_off == 1)
- + if (para->touchpad_off == 1 && !(para->has_led && para->led_double_tap))
- return delay;
- /* apply hysteresis before doing anything serious. This cancels
- @@ -2473,6 +2628,15 @@ HandleState(InputInfoPtr pInfo, struct S
- finger = SynapticsDetectFinger(priv, hw);
- }
- + if (para->has_led && para->led_double_tap) {
- + if (inside_active_area)
- + finger = handle_toggle_led(pInfo, hw, finger);
- + if (para->touchpad_off == 1) {
- + priv->finger_state = finger;
- + return delay;
- + }
- + }
- +
- /* tap and drag detection. Needs to be performed even if the finger is in
- * the dead area to reset the state. */
- timeleft = HandleTapProcessing(priv, hw, finger, inside_active_area);
- diff -uprN a/src/synapticsstr.h b/src/synapticsstr.h
- --- a/src/synapticsstr.h 2011-03-03 21:35:56.000000000 -0500
- +++ b/src/synapticsstr.h 2011-03-19 18:07:43.276845370 -0400
- @@ -160,6 +160,9 @@ typedef struct _SynapticsParameters
- unsigned int resolution_horiz; /* horizontal resolution of touchpad in units/mm */
- unsigned int resolution_vert; /* vertical resolution of touchpad in units/mm */
- int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
- + Bool has_led; /* has an embedded LED */
- + Bool led_status; /* Current status of LED (1=on) */
- + Bool led_double_tap; /* double-tap period in ms for touchpad LED control */
- int hyst_x, hyst_y; /* x and y width of hysteresis box */
- } SynapticsParameters;
- @@ -239,6 +242,14 @@ typedef struct _SynapticsPrivateRec
- Bool has_pressure; /* device reports pressure */
- Bool has_width; /* device reports finger width */
- Bool has_scrollbuttons; /* device has physical scrollbuttons */
- + Bool is_clickpad; /* is Clickpad device (one-button) */
- + struct SynapticsHwState prev_hw; /* previous h/w state (for clickpad) */
- + int prop_change_pending;
- + Bool led_touch_state;
- + Bool led_tapped;
- + int led_touch_millis;
- + int led_tap_millis;
- +
- enum TouchpadModel model; /* The detected model */
- } SynapticsPrivate;
- diff -uprN a/src/synproto.h b/src/synproto.h
- --- a/src/synproto.h 2011-03-03 21:35:56.000000000 -0500
- +++ b/src/synproto.h 2011-03-19 18:07:39.626953966 -0400
- @@ -91,6 +91,7 @@ struct SynapticsProtocolOperations {
- struct CommData *comm, struct SynapticsHwState *hwRet);
- Bool (*AutoDevProbe)(InputInfoPtr pInfo);
- void (*ReadDevDimensions)(InputInfoPtr pInfo);
- + void (*UpdateLED)(InputInfoPtr pInfo);
- };
- extern struct SynapticsProtocolOperations psaux_proto_operations;
- diff -uprN a/tools/synclient.c b/tools/synclient.c
- --- a/tools/synclient.c 2011-02-16 19:59:16.000000000 -0500
- +++ b/tools/synclient.c 2011-03-19 18:07:43.277845322 -0400
- @@ -143,6 +143,8 @@ static struct Parameter params[] = {
- {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1},
- {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2},
- {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3},
- + {"LEDStatus", PT_BOOL, 0, 1, SYNAPTICS_PROP_LED_STATUS, 8, 0},
- + {"LEDDoubleTap", PT_BOOL, 0, 1, SYNAPTICS_PROP_LED_DOUBLE_TAP, 8, 0},
- { NULL, 0, 0, 0, 0 }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement