File xf86-input-synaptics-add-led-support.diff of Package xorg-x11-driver-input
From f8d9dd1c9710f99d3c402517782ae7ba5ef208eb Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 May 2010 18:15:48 +0200
Subject: [PATCH 3/7] Add the embedded LED support
This patch adds the control of the embedded LED on the top-left corner
of new Synaptics devices. For LED control, it requires the patch to
Linux synaptics input driver,
https://patchwork.kernel.org/patch/92434/
When a sysfs file /sys/class/leds/psmouse::synaptics exists, the driver
assumes it supports the embeded LED control.
The LED can be controlled via new properties, "Synaptics LED" and
"Synaptics LED Status".
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/synaptics-properties.h | 6 ++++++
man/synaptics.man | 9 +++++++++
src/eventcomm.c | 32 +++++++++++++++++++++++++++++++-
src/properties.c | 15 +++++++++++++++
src/synapticsstr.h | 2 ++
src/synproto.h | 1 +
tools/synclient.c | 1 +
7 files changed, 65 insertions(+), 1 deletion(-)
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -155,4 +155,10 @@
/* 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"
+
#endif /* _SYNAPTICS_PROPERTIES_H_ */
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -909,6 +909,15 @@
.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.
+
.SH "NOTES"
There is an example hal policy file in
.I ${sourcecode}/fdi/11-x11-synaptics.fdi
--- a/src/eventcomm.c
+++ b/src/eventcomm.c
@@ -51,6 +51,8 @@
#define LONG(x) ((x) / LONG_BITS)
#define TEST_BIT(bit, array) (array[LONG(bit)] & (1 << OFF(bit)))
+#define SYNAPTICS_LED_SYS_FILE "/sys/class/leds/psmouse::synaptics/brightness"
+
/*****************************************************************************
* Function Definitions
****************************************************************************/
@@ -166,6 +168,32 @@
}
}
+static void
+event_query_led(LocalDevicePtr local)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *)local->private;
+
+ priv->synpara.has_led = !access(SYNAPTICS_LED_SYS_FILE, W_OK);
+}
+
+static void EventUpdateLED(LocalDevicePtr local)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *)local->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", local->name, val);
+ }
+}
+
/* Query device for axis ranges */
static void
event_query_axis_ranges(LocalDevicePtr local)
@@ -434,6 +462,7 @@
if (event_query_is_touchpad(local->fd, (need_grab) ? *need_grab : TRUE))
event_query_axis_ranges(local);
event_query_info(local);
+ event_query_led(local);
}
static Bool
@@ -503,5 +532,6 @@
EventQueryHardware,
EventReadHwState,
EventAutoDevProbe,
- EventReadDevDimensions
+ EventReadDevDimensions,
+ EventUpdateLED,
};
--- a/src/properties.c
+++ b/src/properties.c
@@ -82,6 +82,8 @@
Atom prop_capabilities = 0;
Atom prop_resolution = 0;
Atom prop_area = 0;
+Atom prop_led = 0;
+Atom prop_led_status = 0;
static Atom
InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
@@ -278,6 +280,9 @@
values[2] = para->area_top_edge;
values[3] = para->area_bottom_edge;
prop_area = InitAtom(local->dev, SYNAPTICS_PROP_AREA, 32, 4, values);
+
+ prop_led = InitAtom(local->dev, SYNAPTICS_PROP_LED, 8, 1, ¶->has_led);
+ prop_led_status = InitAtom(local->dev, SYNAPTICS_PROP_LED_STATUS, 8, 1, ¶->led_status);
}
int
@@ -649,6 +654,16 @@
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(local);
+ }
}
return Success;
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -160,6 +160,8 @@
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) */
} SynapticsParameters;
--- a/src/synproto.h
+++ b/src/synproto.h
@@ -91,6 +91,7 @@
struct CommData *comm, struct SynapticsHwState *hwRet);
Bool (*AutoDevProbe)(LocalDevicePtr local);
void (*ReadDevDimensions)(LocalDevicePtr local);
+ void (*UpdateLED)(LocalDevicePtr local);
};
extern struct SynapticsProtocolOperations psaux_proto_operations;
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -143,6 +143,7 @@
{"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},
{ NULL, 0, 0, 0, 0 }
};