diff options
Diffstat (limited to 'led_support.patch')
-rw-r--r-- | led_support.patch | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/led_support.patch b/led_support.patch new file mode 100644 index 000000000000..19b12903315a --- /dev/null +++ b/led_support.patch @@ -0,0 +1,442 @@ +diff -ur xf86-input-synaptics-1.7.6/include/synaptics-properties.h xf86-input-synaptics-1.7.6_new/include/synaptics-properties.h +--- xf86-input-synaptics-1.7.6/include/synaptics-properties.h 2014-05-01 08:18:12.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/include/synaptics-properties.h 2015-10-29 11:37:06.960956364 +0300 +@@ -158,4 +158,13 @@ + /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */ + #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation" + ++/* 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" ++ + #endif /* _SYNAPTICS_PROPERTIES_H_ */ +diff -ur xf86-input-synaptics-1.7.6/man/synaptics.man xf86-input-synaptics-1.7.6_new/man/synaptics.man +--- xf86-input-synaptics-1.7.6/man/synaptics.man 2014-05-01 08:18:12.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/man/synaptics.man 2015-10-29 11:38:20.123434539 +0300 +@@ -573,6 +573,19 @@ + 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. +@@ -919,6 +932,19 @@ + .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" + Configuration through + .I InputClass +diff -ur xf86-input-synaptics-1.7.6/src/eventcomm.c xf86-input-synaptics-1.7.6_new/src/eventcomm.c +--- xf86-input-synaptics-1.7.6/src/eventcomm.c 2014-05-13 05:33:21.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/src/eventcomm.c 2015-10-29 11:48:24.683944284 +0300 +@@ -62,6 +62,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" ++ + /** + * Protocol-specific data. + */ +@@ -392,6 +394,37 @@ + return 0; + } + ++static void ++event_query_led(InputInfoPtr pInfo) ++{ ++ SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; ++ ++ xf86IDrvMsg(pInfo, X_INFO, "led: checking for access to %s\n", SYNAPTICS_LED_SYS_FILE); ++ priv->synpara.has_led = !access(SYNAPTICS_LED_SYS_FILE, W_OK); ++ if (priv->synpara.has_led) ++ xf86IDrvMsg(pInfo, X_INFO, "led: access ok\n"); ++ else ++ xf86IDrvMsg(pInfo, X_INFO, "led: no access\n"); ++} ++ ++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) ++ xf86IDrvMsg(pInfo, X_WARNING, "can't write LED value %s\n", val); ++ } ++} ++ + /* Query device for axis ranges */ + static void + event_query_axis_ranges(InputInfoPtr pInfo) +@@ -928,6 +961,9 @@ + event_query_model(pInfo->fd, &priv->model, &priv->id_vendor, + &priv->id_product); + ++ event_query_led(pInfo); ++ event_query_model(pInfo->fd, &priv->model, &priv->id_vendor, &priv->id_product); ++ + xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n", + priv->id_vendor, priv->id_product); + } +@@ -1007,5 +1043,6 @@ + EventQueryHardware, + EventReadHwState, + EventAutoDevProbe, +- EventReadDevDimensions ++ EventReadDevDimensions, ++ EventUpdateLED, + }; +diff -ur xf86-input-synaptics-1.7.6/src/properties.c xf86-input-synaptics-1.7.6_new/src/properties.c +--- xf86-input-synaptics-1.7.6/src/properties.c 2014-05-01 08:18:12.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/src/properties.c 2015-10-29 11:40:12.047245599 +0300 +@@ -95,6 +95,9 @@ + Atom prop_noise_cancellation = 0; + Atom prop_product_id = 0; + Atom prop_device_node = 0; ++Atom prop_led = 0; ++Atom prop_led_status = 0; ++Atom prop_led_double_tap = 0; + + static Atom + InitTypedAtom(DeviceIntPtr dev, char *name, Atom type, int format, int nvalues, +@@ -381,6 +384,11 @@ + SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 2, + 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); ++ + /* only init product_id property if we actually know them */ + if (priv->id_vendor || priv->id_product) { + values[0] = priv->id_vendor; +@@ -814,6 +822,22 @@ + para->hyst_x = hyst[0]; + para->hyst_y = hyst[1]; + } ++ 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_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_product_id || property == prop_device_node) + return BadValue; /* read-only */ + else { /* unknown property */ +@@ -829,3 +853,14 @@ + + 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 -ur xf86-input-synaptics-1.7.6/src/synaptics.c xf86-input-synaptics-1.7.6_new/src/synaptics.c +--- xf86-input-synaptics-1.7.6/src/synaptics.c 2014-05-13 05:33:21.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/src/synaptics.c 2015-10-29 11:46:05.609365594 +0300 +@@ -143,6 +143,7 @@ + void InitDeviceProperties(InputInfoPtr pInfo); + int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, + BOOL checkonly); ++void SynapticsToggleOffProperty(DeviceIntPtr dev, Bool off); + + const static struct { + const char *name; +@@ -745,6 +746,8 @@ + 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) { +@@ -1004,6 +1007,10 @@ + xf86AddEnabledDevice(pInfo); + dev->public.on = TRUE; + ++ /* update LED */ ++ if (priv->proto_ops && priv->proto_ops->UpdateLED) ++ priv->proto_ops->UpdateLED(pInfo); ++ + return Success; + } + +@@ -1346,14 +1353,83 @@ + return !Success; + } + ++#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) { ++ para->led_status = para->touchpad_off; ++ 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 */ ++} ++ ++ + /* + * Convert from absolute X/Y coordinates to a coordinate system where + * -1 corresponds to the left/upper edge and +1 corresponds to the + * right/lower edge. + */ + static void +-relative_coords(SynapticsPrivate * priv, int x, int y, +- double *relX, double *relY) ++relative_coords(SynapticsPrivate *priv, int x, int y, ++ double *relX, double *relY) + { + int minX = priv->synpara.left_edge; + int maxX = priv->synpara.right_edge; +@@ -1363,12 +1439,11 @@ + double yCenter = (minY + maxY) / 2.0; + + if ((maxX - xCenter > 0) && (maxY - yCenter > 0)) { +- *relX = (x - xCenter) / (maxX - xCenter); +- *relY = (y - yCenter) / (maxY - yCenter); +- } +- else { +- *relX = 0; +- *relY = 0; ++ *relX = (x - xCenter) / (maxX - xCenter); ++ *relY = (y - yCenter) / (maxY - yCenter); ++ } else { ++ *relX = 0; ++ *relY = 0; + } + } + +@@ -1581,6 +1656,7 @@ + { + InputInfoPtr pInfo = arg; + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); ++ SynapticsParameters *para = &priv->synpara; + struct SynapticsHwState *hw = priv->local_hw_state; + int delay; + int sigstate; +@@ -1591,6 +1667,13 @@ + SynapticsCopyHwState(hw, priv->hwState); + SynapticsResetTouchHwState(hw, FALSE); + delay = HandleState(pInfo, hw, hw->millis, TRUE); ++ if (priv->prop_change_pending) ++ delay = MIN(10, delay); ++ ++ if (priv->prop_change_pending) { ++ SynapticsToggleOffProperty(pInfo->dev, para->touchpad_off); ++ priv->prop_change_pending = 0; ++ } + + priv->timer_time = now; + priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo); +@@ -2773,7 +2856,7 @@ + + /* If this is a clickpad and the user clicks in a soft button area, press + * the soft button instead. */ +- if (para->clickpad) { ++ if (para->touchpad_off != 1 && para->clickpad) { + /* hw->left is down, but no other buttons were already down */ + if (!(priv->lastButtons & 7) && hw->left && !hw->right && !hw->middle) { + /* If the finger down event is delayed, the x and y +@@ -3072,6 +3155,12 @@ + Bool using_cumulative_coords = FALSE; + Bool ignore_motion; + ++ /* If touchpad is switched off, we skip the whole thing and return delay */ ++ if (para->touchpad_off == TOUCHPAD_OFF && !(para->has_led && para->led_double_tap)) { ++ UpdateTouchState(pInfo, hw); ++ return delay; ++ } ++ + /* We need both and x/y, the driver can't handle just one of the two + * yet. But since it's possible to hit a phys button on non-clickpads + * without ever getting motion data first, we must continue with 0/0 for +@@ -3143,6 +3232,15 @@ + finger = priv->finger_state; + } + ++ 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, now, finger, inside_active_area); +diff -ur xf86-input-synaptics-1.7.6/src/synapticsstr.h xf86-input-synaptics-1.7.6_new/src/synapticsstr.h +--- xf86-input-synaptics-1.7.6/src/synapticsstr.h 2014-05-01 08:18:12.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/src/synapticsstr.h 2015-10-29 11:47:04.671303525 +0300 +@@ -226,6 +226,9 @@ + int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */ + int softbutton_areas[4][4]; /* soft button area coordinates, 0 => right, 1 => middle , 2 => secondary right, 3 => secondary middle button */ + int hyst_x, hyst_y; /* x and y width of hysteresis box */ ++ 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 */ + } SynapticsParameters; + + struct _SynapticsPrivateRec { +@@ -308,6 +311,11 @@ + Bool has_width; /* device reports finger width */ + Bool has_scrollbuttons; /* device has physical scrollbuttons */ + Bool has_semi_mt; /* device is only semi-multitouch capable */ ++ 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 */ + unsigned short id_vendor; /* vendor id */ +diff -ur xf86-input-synaptics-1.7.6/src/synproto.h xf86-input-synaptics-1.7.6_new/src/synproto.h +--- xf86-input-synaptics-1.7.6/src/synproto.h 2014-05-13 05:33:21.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/src/synproto.h 2015-10-29 11:34:03.864805494 +0300 +@@ -31,6 +31,7 @@ + #include "config.h" + #endif + ++#include <xorg-server.h> + #include <unistd.h> + #include <sys/ioctl.h> + #include <xf86Xinput.h> +@@ -103,6 +104,7 @@ + struct SynapticsHwState * hwRet); + Bool (*AutoDevProbe) (InputInfoPtr pInfo, const char *device); + void (*ReadDevDimensions) (InputInfoPtr pInfo); ++ void (*UpdateLED)(InputInfoPtr pInfo); + }; + + #ifdef BUILD_PS2COMM +diff -ur xf86-input-synaptics-1.7.6/tools/synclient.c xf86-input-synaptics-1.7.6_new/tools/synclient.c +--- xf86-input-synaptics-1.7.6/tools/synclient.c 2014-03-20 03:18:02.000000000 +0400 ++++ xf86-input-synaptics-1.7.6_new/tools/synclient.c 2015-10-29 11:47:25.371985080 +0300 +@@ -148,6 +148,8 @@ + {"MiddleButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 5}, + {"MiddleButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 6}, + {"MiddleButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 7}, ++ {"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 } + }; + |