[xorg-x11-drv-wacom] Use custom wacom inputattach tool (#1046912)
Peter Hutterer
whot at fedoraproject.org
Wed Mar 19 09:13:59 UTC 2014
commit cf9d3453136919dc7ea78e5d20e48227af5a3ff3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Wed Mar 19 19:02:27 2014 +1000
Use custom wacom inputattach tool (#1046912)
...oth-clients-and-drivers-need-the-protocol.patch | 34 +
0002-Include-stdint-from-isdv4.h.patch | 28 +
...-isdv4-inline-all-isdv4-parsing-functions.patch | 63 ++
0004-tools-rearrange-serial-settings.patch | 121 +++
0005-tools-open-serial-devices-with-O_NOCTTY.patch | 29 +
0006-tools-use-perror-instead-of-fprintf.patch | 26 +
0007-tools-drop-double-call-to-tcsetattr.patch | 27 +
0008-tools-drop-global-packagelen.patch | 35 +
0009-tools-drop-leftover-global-variables.patch | 91 ++
0010-tools-make-event_loop-static.patch | 26 +
...-out-the-debugger-into-the-actual-debugge.patch | 1043 ++++++++++++++++++++
0012-tools-re-enable-wait-for-tablet.patch | 41 +
0013-tools-add-colon-after-TOUCH-output.patch | 36 +
0014-tools-add-an-inputattach-like-tool.patch | 264 +++++
wacom-inputattach at .service | 3 +-
xorg-x11-drv-wacom.spec | 37 +-
16 files changed, 1899 insertions(+), 5 deletions(-)
---
diff --git a/0001-configure-both-clients-and-drivers-need-the-protocol.patch b/0001-configure-both-clients-and-drivers-need-the-protocol.patch
new file mode 100644
index 0000000..8c22463
--- /dev/null
+++ b/0001-configure-both-clients-and-drivers-need-the-protocol.patch
@@ -0,0 +1,34 @@
+From 5073552b9e20f06ccdd9620977874016fc414bdf Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 17 Mar 2014 08:52:33 +1000
+Subject: [PATCH 01/14] configure: both clients and drivers need the protocol
+ headers
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ configure.ac | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 4ba103c..be211f8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -49,11 +49,13 @@ XORG_WITH_DOXYGEN(1.6.1)
+ # Checks for libraries.
+ AC_CHECK_LIB([m], [rint])
+
++XPROTOS="xproto xext kbproto inputproto randrproto"
++
+ # Obtain compiler/linker options from server and required extensions
+-PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7.0] xproto xext kbproto inputproto randrproto)
++PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7.0] $XPROTOS)
+
+ # Obtain compiler/linker options for the xsetwacom tool
+-PKG_CHECK_MODULES(X11, x11 xi xrandr xinerama)
++PKG_CHECK_MODULES(X11, x11 xi xrandr xinerama $XPROTOS)
+
+ # Obtain compiler/linker options for libudev used by ISDV4 code
+ PKG_CHECK_MODULES(UDEV, libudev)
+--
+1.8.5.3
+
diff --git a/0002-Include-stdint-from-isdv4.h.patch b/0002-Include-stdint-from-isdv4.h.patch
new file mode 100644
index 0000000..4a4fc0c
--- /dev/null
+++ b/0002-Include-stdint-from-isdv4.h.patch
@@ -0,0 +1,28 @@
+From c5e721559b3d27b454837220ae232081cf2e0b1a Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 09:45:04 +1000
+Subject: [PATCH 02/14] Include stdint from isdv4.h
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ include/isdv4.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/include/isdv4.h b/include/isdv4.h
+index 539f609..423d564 100644
+--- a/include/isdv4.h
++++ b/include/isdv4.h
+@@ -20,6 +20,10 @@
+ #ifndef ISDV4_H
+ #define ISDV4_H
+
++#include <stdint.h>
++#include <stddef.h>
++#include <string.h>
++
+ #define ISDV4_QUERY "*" /* ISDV4 query command */
+ #define ISDV4_RESET "&" /* ISDV4 touch panel reset command */
+ #define ISDV4_TOUCH_QUERY "%" /* ISDV4 touch query command */
+--
+1.8.5.3
+
diff --git a/0003-isdv4-inline-all-isdv4-parsing-functions.patch b/0003-isdv4-inline-all-isdv4-parsing-functions.patch
new file mode 100644
index 0000000..0ac1d27
--- /dev/null
+++ b/0003-isdv4-inline-all-isdv4-parsing-functions.patch
@@ -0,0 +1,63 @@
+From c64b9218b75b9ebdf1ad94bcf9a8ecc3946c01a2 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:20:53 +1000
+Subject: [PATCH 03/14] isdv4: inline all isdv4 parsing functions
+
+Stops compiler warning if any of them aren't used.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ include/isdv4.h | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/include/isdv4.h b/include/isdv4.h
+index 423d564..a7d0d4e 100644
+--- a/include/isdv4.h
++++ b/include/isdv4.h
+@@ -103,8 +103,8 @@ typedef struct {
+ uint8_t tilt_y;
+ } ISDV4CoordinateData;
+
+-static int isdv4ParseQuery(const unsigned char *buffer, const size_t len,
+- ISDV4QueryReply *reply)
++static inline int isdv4ParseQuery(const unsigned char *buffer, const size_t len,
++ ISDV4QueryReply *reply)
+ {
+ int header, control;
+
+@@ -130,8 +130,8 @@ static int isdv4ParseQuery(const unsigned char *buffer, const size_t len,
+ return ISDV4_PKGLEN_TPCCTL;
+ }
+
+-static int isdv4ParseTouchQuery(const unsigned char *buffer, const size_t len,
+- ISDV4TouchQueryReply *reply)
++static inline int isdv4ParseTouchQuery(const unsigned char *buffer, const size_t len,
++ ISDV4TouchQueryReply *reply)
+ {
+ int header, control;
+
+@@ -157,8 +157,8 @@ static int isdv4ParseTouchQuery(const unsigned char *buffer, const size_t len,
+ }
+
+ /* pktlen defines what touch type we parse */
+-static int isdv4ParseTouchData(const unsigned char *buffer, const size_t buff_len,
+- const size_t pktlen, ISDV4TouchData *touchdata)
++static inline int isdv4ParseTouchData(const unsigned char *buffer, const size_t buff_len,
++ const size_t pktlen, ISDV4TouchData *touchdata)
+ {
+ int header, touch;
+
+@@ -191,8 +191,8 @@ static int isdv4ParseTouchData(const unsigned char *buffer, const size_t buff_le
+ return pktlen;
+ }
+
+-static int isdv4ParseCoordinateData(const unsigned char *buffer, const size_t len,
+- ISDV4CoordinateData *coord)
++static inline int isdv4ParseCoordinateData(const unsigned char *buffer, const size_t len,
++ ISDV4CoordinateData *coord)
+ {
+ int header, control;
+
+--
+1.8.5.3
+
diff --git a/0004-tools-rearrange-serial-settings.patch b/0004-tools-rearrange-serial-settings.patch
new file mode 100644
index 0000000..06d7ff1
--- /dev/null
+++ b/0004-tools-rearrange-serial-settings.patch
@@ -0,0 +1,121 @@
+From 7f188409d95bc98498d9770974b156c348da40d2 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 17 Mar 2014 09:46:21 +1000
+Subject: [PATCH 04/14] tools: rearrange serial settings
+
+If the device was't properly closed/reset after a crash, tcgetattr() will
+fail. Ignore that error and apply the settings we want nonetheless, in most
+cases the device will just come back normally.
+
+And to do so, merge setting the baud rate together with the rest so we only
+have one call. Otherwise we can't apply the baud rate settings without
+potentially submitting garbage to the driver.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 49 +++++++++++++++----------------------------
+ 1 file changed, 17 insertions(+), 32 deletions(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 8a64f43..47c6896 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -68,17 +68,16 @@ static void version(void)
+ PACKAGE_VERSION_PATCHLEVEL);
+ }
+
+-static int open_device(char *path)
++int open_device(const char *path)
+ {
+- int fd, rc;
++ int fd;
+ struct serial_struct ser;
+- struct termios t;
+
+ TRACE("Opening device '%s'.\n", path);
+ fd = open(path, O_RDWR);
+
+ if (fd < 1)
+- perror("Failed to open device file.");
++ perror("Failed to open device file");
+
+ if (ioctl(fd, TIOCGSERIAL, &ser) == -1)
+ {
+@@ -88,14 +87,16 @@ static int open_device(char *path)
+ goto out;
+ }
+
+- rc = tcgetattr(fd, &t);
+- if (rc == -1)
+- {
+- perror("Failed to get serial attributes.");
+- close(fd);
+- fd = -1;
+- goto out;
+- }
++out:
++ return fd;
++}
++
++int set_serial_attr(int fd, unsigned int baud)
++{
++ struct termios t;
++
++ if (tcgetattr(fd, &t) == -1)
++ memset(&t, 0, sizeof(t));
+
+ /* defaults from xf86OpenSerial */
+ t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+@@ -110,21 +111,9 @@ static int open_device(char *path)
+ t.c_cflag &= ~(CSIZE); /* databits 8 */
+ t.c_cflag |= (CS8); /* databits 8 */
+ t.c_cflag &= ~(PARENB); /* parity none */
+- t.c_cc[VMIN] = 1; /* vmin 1 */
++ t.c_cc[VMIN] = 1; /* vmin 1 */
+ t.c_cc[VTIME] = 10; /* vtime 10 */
+- t.c_iflag |= IXOFF; /* flow controll xoff */
+-
+-
+- tcsetattr(fd, TCSANOW, &t);
+-
+-out:
+- return fd;
+-}
+-
+-static int set_baud_rate(int fd, int baud)
+-{
+- struct termios t;
+- int rc;
++ t.c_iflag |= IXOFF; /* flow controll xoff */
+
+ TRACE("Baud rate is %d\n", baud);
+
+@@ -137,15 +126,11 @@ static int set_baud_rate(int fd, int baud)
+ return -1;
+ }
+
+- rc = tcgetattr(fd, &t);
+-
+- if (rc)
+- return rc;
+-
+ cfsetispeed(&t, baud);
+ cfsetospeed(&t, baud);
+
+ return tcsetattr(fd, TCSANOW, &t);
++
+ }
+
+ static int write_to_tablet(int fd, char *command)
+@@ -567,7 +552,7 @@ int main (int argc, char **argv)
+ if (fd < 0)
+ return 1;
+
+- rc = set_baud_rate(fd, baudrate);
++ rc = set_serial_attr(fd, baudrate);
+ if (rc < 0)
+ return 1;
+
+--
+1.8.5.3
+
diff --git a/0005-tools-open-serial-devices-with-O_NOCTTY.patch b/0005-tools-open-serial-devices-with-O_NOCTTY.patch
new file mode 100644
index 0000000..826f248
--- /dev/null
+++ b/0005-tools-open-serial-devices-with-O_NOCTTY.patch
@@ -0,0 +1,29 @@
+From 394466f19aeaa9bc8c86c110585622c766dc2d8e Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 17 Mar 2014 08:00:45 +1000
+Subject: [PATCH 05/14] tools: open serial devices with O_NOCTTY
+
+Probably doesn't make much difference, but won't hurt if we ever send the
+wrong path name.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 47c6896..72b9b4f 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -74,7 +74,7 @@ int open_device(const char *path)
+ struct serial_struct ser;
+
+ TRACE("Opening device '%s'.\n", path);
+- fd = open(path, O_RDWR);
++ fd = open(path, O_RDWR | O_NOCTTY);
+
+ if (fd < 1)
+ perror("Failed to open device file");
+--
+1.8.5.3
+
diff --git a/0006-tools-use-perror-instead-of-fprintf.patch b/0006-tools-use-perror-instead-of-fprintf.patch
new file mode 100644
index 0000000..a9deba5
--- /dev/null
+++ b/0006-tools-use-perror-instead-of-fprintf.patch
@@ -0,0 +1,26 @@
+From 787f280726afb56afab872a53a414cf0e32328dd Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 17 Mar 2014 08:58:46 +1000
+Subject: [PATCH 06/14] tools: use perror instead of fprintf
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 72b9b4f..778b500 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -81,7 +81,7 @@ int open_device(const char *path)
+
+ if (ioctl(fd, TIOCGSERIAL, &ser) == -1)
+ {
+- fprintf(stderr, "Not a serial device?");
++ perror("Not a serial device?");
+ close(fd);
+ fd = -1;
+ goto out;
+--
+1.8.5.3
+
diff --git a/0007-tools-drop-double-call-to-tcsetattr.patch b/0007-tools-drop-double-call-to-tcsetattr.patch
new file mode 100644
index 0000000..e5954e4
--- /dev/null
+++ b/0007-tools-drop-double-call-to-tcsetattr.patch
@@ -0,0 +1,27 @@
+From 9368d95b18ba8f3c13ac4c42eb4ea1d98b107231 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 17 Mar 2014 09:38:45 +1000
+Subject: [PATCH 07/14] tools: drop double-call to tcsetattr
+
+We merely modify the flags, might as well just send one call
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 778b500..e89623a 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -104,7 +104,6 @@ int set_serial_attr(int fd, unsigned int baud)
+ t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ t.c_cflag &= ~(CSIZE|PARENB);
+ t.c_cflag |= CS8|CLOCAL;
+- tcsetattr(fd, TCSANOW, &t);
+
+ /* wacom-specific */
+ t.c_cflag &= ~(CSTOPB); /* stopbits 1 */
+--
+1.8.5.3
+
diff --git a/0008-tools-drop-global-packagelen.patch b/0008-tools-drop-global-packagelen.patch
new file mode 100644
index 0000000..848d062
--- /dev/null
+++ b/0008-tools-drop-global-packagelen.patch
@@ -0,0 +1,35 @@
+From a1067ff6e67b9cb5f0ffeff1c08f9e37f755a543 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:27:53 +1000
+Subject: [PATCH 08/14] tools: drop global packagelen
+
+Not necesssary, we can have this locally in the event loop
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index e89623a..1a036ce 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -45,7 +45,6 @@
+ do { if (verbose) printf("... " __VA_ARGS__); } while(0)
+
+ static int verbose = 0;
+-static int packetlength = ISDV4_PKGLEN_TPCPEN;
+ static ISDV4QueryReply reply;
+ static ISDV4TouchQueryReply touch;
+
+@@ -423,6 +422,7 @@ int event_loop(int fd)
+ {
+ unsigned char buffer[256];
+ int dlen = 0;
++ int packetlength = ISDV4_PKGLEN_TPCPEN;
+
+ TRACE("Waiting for events\n");
+
+--
+1.8.5.3
+
diff --git a/0009-tools-drop-leftover-global-variables.patch b/0009-tools-drop-leftover-global-variables.patch
new file mode 100644
index 0000000..d0f8230
--- /dev/null
+++ b/0009-tools-drop-leftover-global-variables.patch
@@ -0,0 +1,91 @@
+From 43b57e502c34b57ee91a14b90a6b7e53023ae50f Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:30:24 +1000
+Subject: [PATCH 09/14] tools: drop leftover global variables
+
+Only one left is verbosity now.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 1a036ce..7c9700c 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -45,9 +45,6 @@
+ do { if (verbose) printf("... " __VA_ARGS__); } while(0)
+
+ static int verbose = 0;
+-static ISDV4QueryReply reply;
+-static ISDV4TouchQueryReply touch;
+-
+
+ static void usage(void)
+ {
+@@ -284,6 +281,9 @@ redo:
+
+ static int query_tablet(int fd)
+ {
++ ISDV4QueryReply reply;
++ ISDV4TouchQueryReply touch;
++
+ unsigned char buffer[ISDV4_PKGLEN_TPCCTL];
+ int len, rc;
+
+@@ -342,7 +342,7 @@ static int query_tablet(int fd)
+ printf("TOUCH sensor id: %d\n", touch.sensor_id);
+ }
+
+- return 0;
++ return touch.sensor_id;
+
+ out:
+ fprintf(stderr, "error during query.\n");
+@@ -418,7 +418,7 @@ static int parse_touch_packet(unsigned char* buffer, int packetlength)
+
+ }
+
+-int event_loop(int fd)
++int event_loop(int fd, int sensor_id)
+ {
+ unsigned char buffer[256];
+ int dlen = 0;
+@@ -450,7 +450,7 @@ int event_loop(int fd)
+ {
+ packetlength = ISDV4_PKGLEN_TPCPEN;
+ if (buffer[0] & TOUCH_CONTROL_BIT)
+- packetlength = ISDV4PacketLengths[touch.sensor_id];
++ packetlength = ISDV4PacketLengths[sensor_id];
+ } else {
+ int bytes = skip_garbage(buffer, dlen);
+ if (bytes > 0) {
+@@ -508,6 +508,7 @@ int main (int argc, char **argv)
+ int baudrate = 38400;
+ int reset = 0;
+ int rc;
++ int sensor_id;
+
+ int c, optidx = 0;
+ struct option options[] = {
+@@ -561,13 +562,13 @@ int main (int argc, char **argv)
+ return 1;
+ }
+
+- rc = query_tablet(fd);
+- if (rc < 0)
++ sensor_id = query_tablet(fd);
++ if (sensor_id < 0)
+ return 1;
+
+ start_tablet(fd);
+
+- return event_loop(fd);
++ return event_loop(fd, sensor_id);
+ }
+
+ /* vim: set noexpandtab tabstop=8 shiftwidth=8: */
+--
+1.8.5.3
+
diff --git a/0010-tools-make-event_loop-static.patch b/0010-tools-make-event_loop-static.patch
new file mode 100644
index 0000000..fea31a5
--- /dev/null
+++ b/0010-tools-make-event_loop-static.patch
@@ -0,0 +1,26 @@
+From 0822af20a0d556bc134fac396e1070373cc81568 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:31:15 +1000
+Subject: [PATCH 10/14] tools: make event_loop() static
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/isdv4-serial-debugger.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 7c9700c..65bed85 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -418,7 +418,7 @@ static int parse_touch_packet(unsigned char* buffer, int packetlength)
+
+ }
+
+-int event_loop(int fd, int sensor_id)
++static int event_loop(int fd, int sensor_id)
+ {
+ unsigned char buffer[256];
+ int dlen = 0;
+--
+1.8.5.3
+
diff --git a/0011-tools-split-out-the-debugger-into-the-actual-debugge.patch b/0011-tools-split-out-the-debugger-into-the-actual-debugge.patch
new file mode 100644
index 0000000..38d5ad1
--- /dev/null
+++ b/0011-tools-split-out-the-debugger-into-the-actual-debugge.patch
@@ -0,0 +1,1043 @@
+From 08cb75f6dfa6885e7c63a82bb8ae40bc4e7306e7 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:44:46 +1000
+Subject: [PATCH 11/14] tools: split out the debugger into the actual debugger
+ and shared code
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/Makefile.am | 4 +
+ tools/isdv4-serial-debugger.c | 450 +-------------------------------------
+ tools/tools-shared.c | 487 ++++++++++++++++++++++++++++++++++++++++++
+ tools/tools-shared.h | 41 ++++
+ 4 files changed, 534 insertions(+), 448 deletions(-)
+ create mode 100644 tools/tools-shared.c
+ create mode 100644 tools/tools-shared.h
+
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index 5cd40e2..5eba0a6 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -24,6 +24,10 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
+ AM_CFLAGS = $(XORG_CFLAGS) $(X11_CFLAGS)
+ AM_LDFLAGS = $(X11_LIBS)
+
++shared_sources = tools-shared.h tools-shared.c
++
++isdv4_serial_debugger_SOURCES = isdv4-serial-debugger.c $(shared_sources)
++
+
+ if UNITTESTS
+ check_PROGRAMS = xsetwacom-test
+diff --git a/tools/isdv4-serial-debugger.c b/tools/isdv4-serial-debugger.c
+index 65bed85..64d7a5b 100644
+--- a/tools/isdv4-serial-debugger.c
++++ b/tools/isdv4-serial-debugger.c
+@@ -39,12 +39,9 @@
+ #include <termios.h>
+ #include <unistd.h>
+
+-#include "isdv4.h"
++#include "tools-shared.h"
+
+-#define TRACE(...) \
+- do { if (verbose) printf("... " __VA_ARGS__); } while(0)
+-
+-static int verbose = 0;
++int verbose = 0;
+
+ static void usage(void)
+ {
+@@ -58,449 +55,6 @@ static void usage(void)
+ " --reset - send reset command before doing anything\n");
+ }
+
+-static void version(void)
+-{
+- printf("%d.%d.%d\n", PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
+- PACKAGE_VERSION_PATCHLEVEL);
+-}
+-
+-int open_device(const char *path)
+-{
+- int fd;
+- struct serial_struct ser;
+-
+- TRACE("Opening device '%s'.\n", path);
+- fd = open(path, O_RDWR | O_NOCTTY);
+-
+- if (fd < 1)
+- perror("Failed to open device file");
+-
+- if (ioctl(fd, TIOCGSERIAL, &ser) == -1)
+- {
+- perror("Not a serial device?");
+- close(fd);
+- fd = -1;
+- goto out;
+- }
+-
+-out:
+- return fd;
+-}
+-
+-int set_serial_attr(int fd, unsigned int baud)
+-{
+- struct termios t;
+-
+- if (tcgetattr(fd, &t) == -1)
+- memset(&t, 0, sizeof(t));
+-
+- /* defaults from xf86OpenSerial */
+- t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+- t.c_oflag &= ~OPOST;
+- t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+- t.c_cflag &= ~(CSIZE|PARENB);
+- t.c_cflag |= CS8|CLOCAL;
+-
+- /* wacom-specific */
+- t.c_cflag &= ~(CSTOPB); /* stopbits 1 */
+- t.c_cflag &= ~(CSIZE); /* databits 8 */
+- t.c_cflag |= (CS8); /* databits 8 */
+- t.c_cflag &= ~(PARENB); /* parity none */
+- t.c_cc[VMIN] = 1; /* vmin 1 */
+- t.c_cc[VTIME] = 10; /* vtime 10 */
+- t.c_iflag |= IXOFF; /* flow controll xoff */
+-
+- TRACE("Baud rate is %d\n", baud);
+-
+- switch(baud)
+- {
+- case 19200: baud = B19200; break;
+- case 38400: baud = B38400; break;
+- default:
+- fprintf(stderr, "Unsupported baud rate.\n");
+- return -1;
+- }
+-
+- cfsetispeed(&t, baud);
+- cfsetospeed(&t, baud);
+-
+- return tcsetattr(fd, TCSANOW, &t);
+-
+-}
+-
+-static int write_to_tablet(int fd, char *command)
+-{
+- int len = 0;
+-
+- do {
+- int l;
+- l = write(fd, &command[len], strlen(command) - len);
+-
+- TRACE("Written '%s'.\n", command);
+-
+- if (l == -1 && errno != EAGAIN)
+- {
+- perror("not written.\n");
+- break;
+- }
+- len += l;
+- } while (errno == EAGAIN && len < strlen(command));
+-
+- return !(len == strlen(command));
+-}
+-
+-static int stop_tablet(int fd)
+-{
+- int rc;
+- char buffer[10];
+- int fd_flags;
+-
+- TRACE("Writing STOP command.\n");
+- rc = write_to_tablet(fd, ISDV4_STOP);
+-
+- usleep(250000);
+-
+- /* flush the line */
+- fd_flags = fcntl(fd, F_GETFL);
+- if (fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK) == 0)
+- {
+- while (read(fd, buffer, sizeof(buffer)) > 0)
+- TRACE("garbage flushed\n");
+- fcntl(fd, F_SETFL, fd_flags);
+- }
+-
+- return rc;
+-}
+-
+-static int start_tablet(int fd)
+-{
+- TRACE("Writing SAMPLING command.\n");
+- return write_to_tablet(fd, ISDV4_SAMPLING);
+-}
+-
+-static int wait_for_tablet(int fd)
+-{
+-#if 0
+- struct pollfd pfd = { fd, POLLIN, 0 };
+- int rc;
+-
+- TRACE("Waiting for tablet...");
+- rc = poll(&pfd, 1, 1000);
+- if (rc < 0) {
+- perror("poll failed.");
+- return -1;
+- } else if (rc == 0) {
+- fprintf(stderr, "timeout.\n");
+- return -1;
+- } else if (pfd.revents & POLLIN)
+- TRACE("data available.\n");
+-
+-#endif
+- return 0;
+-}
+-
+-static void memdump(const unsigned char *buffer, int len)
+-{
+- int n = 0;
+- if (!len)
+- return;
+-
+- while(len-- && ++n) {
+- TRACE("%#hhx ", *buffer++);
+- if (n % 8 == 0)
+- TRACE("\n");
+- }
+-
+- TRACE("\n");
+-}
+-
+-static int skip_garbage(unsigned char *buffer, size_t len)
+-{
+- int i;
+- for (i = 0; i < len; i++)
+- if (buffer[i] & HEADER_BIT)
+- break;
+-
+- if (i != 0)
+- TRACE("skipping over %d bytes.\n", (i < len) ? i : -1);
+-
+- return (i < len) ? i : -1;
+-}
+-
+-static int read_data(int fd, unsigned char* buffer, int min_len)
+-{
+- int len = 0;
+- int attempts = 10;
+- int skip;
+-
+- TRACE("Reading %d bytes from device.\n", min_len);
+-redo:
+- do {
+- int l = read(fd, &buffer[len], min_len);
+-
+- if (l == -1) {
+- if (errno != EAGAIN) {
+- perror("Error reading data.");
+- return -1;
+- }
+- wait_for_tablet(fd);
+- attempts--;
+- continue;
+- } else {
+- TRACE("read %d bytes in one chunk.\n", l);
+- len += l;
+- }
+-
+- } while (len < min_len && attempts);
+-
+- if (!attempts) {
+- fprintf(stderr, "Only able to read %d bytes.\n", len);
+- memdump(buffer, len);
+- return -1;
+- }
+-
+- TRACE("Read %d bytes.\n", len);
+-
+- skip = skip_garbage(buffer, len);
+- if (skip > 0) {
+- TRACE("%d bytes garbage.\n", skip);
+- len -= skip;
+- memmove(buffer, &buffer[skip], len);
+- goto redo;
+- }
+-
+- if (len > min_len)
+- {
+- TRACE("%d bytes unexpected data.\n", (len - min_len));
+- memdump(&buffer[min_len], len - min_len);
+- }
+-
+-
+- return len;
+-}
+-
+-static int query_tablet(int fd)
+-{
+- ISDV4QueryReply reply;
+- ISDV4TouchQueryReply touch;
+-
+- unsigned char buffer[ISDV4_PKGLEN_TPCCTL];
+- int len, rc;
+-
+- TRACE("Querying tablet.\n");
+-
+- if (stop_tablet(fd)) goto out;
+- if (write_to_tablet(fd, ISDV4_QUERY)) goto out;
+- if (wait_for_tablet(fd)) goto out;
+-
+- len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
+- if (len < 1)
+- goto out;
+-
+- if (!(buffer[0] & CONTROL_BIT))
+- {
+- TRACE("+++ out of cheese error +++ redo from start +++\n");
+- /* X driver claims that the first read may fail ??? */
+- len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
+- }
+-
+- TRACE("Parsing query reply.\n");
+- rc = isdv4ParseQuery(buffer, len, &reply);
+- if (rc < 0)
+- {
+- fprintf(stderr, "parsing error code %d\n", rc);
+- goto out;
+- }
+-
+- printf("TABLET: version: %d\n", reply.version);
+- printf("TABLET: x max: %d y max %d\n", reply.x_max, reply.y_max);
+- printf("TABLET: tilt_x max: %d tilt_y max %d\n", reply.tilt_x_max, reply.tilt_y_max);
+- printf("TABLET: pressure max: %d\n", reply.pressure_max);
+-
+- /* check for touch capabilities */
+- TRACE("Trying touch query\n");
+- if (stop_tablet(fd)) goto out;
+- if (write_to_tablet(fd, ISDV4_TOUCH_QUERY)) goto out;
+- if (wait_for_tablet(fd)) goto out;
+-
+- memset(buffer, 0, sizeof(buffer));
+- len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
+- if (len < 1 && errno != EAGAIN)
+- goto out;
+-
+- TRACE("Parsing touch query reply.\n");
+- rc = isdv4ParseTouchQuery(buffer, len, &touch);
+- if (rc < 0)
+- {
+- fprintf(stderr, "touch parsing error code %d\n", rc);
+- /* failure to parse touch query is not fatal */
+- } else {
+- printf("TOUCH version: %d\n", touch.version);
+- printf("TOUCH x max: %d y max %d\n", touch.x_max, touch.y_max);
+- printf("TOUCH panel resolution: %d\n", touch.panel_resolution);
+- printf("TOUCH capacity resolution: %d\n", touch.capacity_resolution);
+- printf("TOUCH sensor id: %d\n", touch.sensor_id);
+- }
+-
+- return touch.sensor_id;
+-
+-out:
+- fprintf(stderr, "error during query.\n");
+- return -1;
+-}
+-
+-static int reset_tablet(int fd)
+-{
+- char buffer[10];
+- TRACE("Reset requested, resetting tablet\n");
+-
+- if (stop_tablet(fd)) goto out;
+- if (write_to_tablet(fd, ISDV4_RESET)) goto out;
+- if (wait_for_tablet(fd)) goto out;
+-
+- memset(buffer, 0, sizeof(buffer));
+- if (read(fd, buffer, sizeof(buffer)) < 1 && errno != EAGAIN)
+- goto out;
+-
+- if (buffer[0] == '&')
+- return 0;
+-
+-out:
+- fprintf(stderr, "failed to reset tablet.\n");
+- return 1;
+-}
+-
+-static int parse_pen_packet(unsigned char* buffer)
+-{
+- int rc;
+- ISDV4CoordinateData coord;
+-
+- TRACE("Parsing coordinate data.\n");
+- rc = isdv4ParseCoordinateData(buffer, ISDV4_PKGLEN_TPCPEN, &coord);
+- if (rc == -1) {
+- fprintf(stderr, "failed to parse coordinate data.\n");
+- return -1;
+- }
+-
+- printf("PEN ");
+- printf("%ld:", time(NULL));
+- printf("%5d/%5d | pressure: %3d | ", coord.x, coord.y, coord.pressure);
+- printf(" %3d/%3d |", coord.tilt_x, coord.tilt_y);
+- printf("%1s %1s %1s %1s |\n", coord.proximity ? "p" : "",
+- coord.tip ? "t" : "",
+- coord.side ? "s" : "",
+- coord.eraser ? "e" : "");
+- return 0;
+-}
+-
+-static int parse_touch_packet(unsigned char* buffer, int packetlength)
+-{
+- ISDV4TouchData touchdata;
+- int rc;
+-
+- rc = isdv4ParseTouchData(buffer, packetlength, packetlength, &touchdata);
+- if (rc == -1) {
+- fprintf(stderr, "failed to parse touch data.\n");
+- return -1;
+- }
+-
+- printf("TOUCH ");
+- printf("%ld:", time(NULL));
+- printf("%5d/%5d | capacity: %3d | ", touchdata.x, touchdata.y, touchdata.capacity);
+- printf("%d | ", touchdata.status);
+-
+- if (packetlength == ISDV4_PKGLEN_TOUCH2FG)
+- printf("%d | %d/%d |", touchdata.finger2.status, touchdata.finger2.x, touchdata.finger2.y);
+-
+- printf("\n");
+-
+- return 0;
+-
+-}
+-
+-static int event_loop(int fd, int sensor_id)
+-{
+- unsigned char buffer[256];
+- int dlen = 0;
+- int packetlength = ISDV4_PKGLEN_TPCPEN;
+-
+- TRACE("Waiting for events\n");
+-
+- if (fcntl(fd, F_SETFD, O_NONBLOCK) == -1)
+- perror("Nonblock failed.");
+-
+- memset(buffer, 0, sizeof(buffer));
+-
+- while (1) {
+- int r, garbage = 0;
+- r = read(fd, &buffer[dlen], sizeof(buffer) - dlen);
+-
+- if (r == -1) {
+- if (errno == EAGAIN)
+- continue;
+- else {
+- perror("Error during read.");
+- goto out;
+- }
+- }
+-
+- dlen += r;
+-
+- if (buffer[0] & HEADER_BIT)
+- {
+- packetlength = ISDV4_PKGLEN_TPCPEN;
+- if (buffer[0] & TOUCH_CONTROL_BIT)
+- packetlength = ISDV4PacketLengths[sensor_id];
+- } else {
+- int bytes = skip_garbage(buffer, dlen);
+- if (bytes > 0) {
+- dlen -= bytes;
+- memmove(buffer, &buffer[bytes], sizeof(buffer) - bytes);
+- }
+- continue;
+- }
+-
+-
+- if (dlen < packetlength)
+- continue;
+- TRACE("Expecting packet sized %d\n", packetlength);
+-
+- if (buffer[0] & CONTROL_BIT) {
+- dlen -= packetlength;
+- continue;
+- }
+-
+- switch(packetlength)
+- {
+- case ISDV4_PKGLEN_TPCPEN:
+- if (parse_pen_packet(buffer))
+- garbage = 1;
+- break;
+- default: /* all others */
+- if (parse_touch_packet(buffer, packetlength))
+- garbage = 1;
+- }
+-
+- if (garbage) {
+- int bytes;
+- bytes = skip_garbage(buffer, packetlength);
+- if (bytes > 0) {
+- dlen -= bytes;
+- memmove(buffer, &buffer[bytes], sizeof(buffer) - bytes);
+- }
+- garbage = 0;
+- } else {
+- memmove(buffer, &buffer[packetlength], sizeof(buffer) - packetlength);
+- dlen -= packetlength;
+- }
+- }
+-
+-
+- return 0;
+-out:
+- return 1;
+-}
+-
+ int main (int argc, char **argv)
+ {
+ int fd;
+diff --git a/tools/tools-shared.c b/tools/tools-shared.c
+new file mode 100644
+index 0000000..4d22cdf
+--- /dev/null
++++ b/tools/tools-shared.c
+@@ -0,0 +1,487 @@
++/*
++ * Copyright 2014 by Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifdef HAVE_CONFIG_H
++#define WACOM_TOOLS
++#include "config.h"
++#endif
++
++#include <errno.h>
++#include <fcntl.h>
++#include <linux/serial.h>
++#include <getopt.h>
++#include <poll.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <time.h>
++#include <termios.h>
++#include <unistd.h>
++
++#include "isdv4.h"
++#include "tools-shared.h"
++
++extern int verbose;
++
++void version(void)
++{
++ printf("%d.%d.%d\n", PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
++ PACKAGE_VERSION_PATCHLEVEL);
++}
++
++int open_device(const char *path)
++{
++ int fd;
++ struct serial_struct ser;
++
++ TRACE("Opening device '%s'.\n", path);
++ fd = open(path, O_RDWR | O_NOCTTY);
++
++ if (fd < 1)
++ perror("Failed to open device file");
++
++ if (ioctl(fd, TIOCGSERIAL, &ser) == -1)
++ {
++ perror("Not a serial device?");
++ close(fd);
++ fd = -1;
++ goto out;
++ }
++
++out:
++ return fd;
++}
++
++int set_serial_attr(int fd, unsigned int baud)
++{
++ struct termios t;
++
++ if (tcgetattr(fd, &t) == -1)
++ memset(&t, 0, sizeof(t));
++
++ /* defaults from xf86OpenSerial */
++ t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
++ t.c_oflag &= ~OPOST;
++ t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
++ t.c_cflag &= ~(CSIZE|PARENB);
++ t.c_cflag |= CS8|CLOCAL;
++
++ /* wacom-specific */
++ t.c_cflag &= ~(CSTOPB); /* stopbits 1 */
++ t.c_cflag &= ~(CSIZE); /* databits 8 */
++ t.c_cflag |= (CS8); /* databits 8 */
++ t.c_cflag &= ~(PARENB); /* parity none */
++ t.c_cc[VMIN] = 1; /* vmin 1 */
++ t.c_cc[VTIME] = 10; /* vtime 10 */
++ t.c_iflag |= IXOFF; /* flow controll xoff */
++
++ TRACE("Baud rate is %d\n", baud);
++
++ switch(baud)
++ {
++ case 19200: baud = B19200; break;
++ case 38400: baud = B38400; break;
++ default:
++ fprintf(stderr, "Unsupported baud rate.\n");
++ return -1;
++ }
++
++ cfsetispeed(&t, baud);
++ cfsetospeed(&t, baud);
++
++ return tcsetattr(fd, TCSANOW, &t);
++
++}
++
++int write_to_tablet(int fd, char *command)
++{
++ int len = 0;
++
++ do {
++ int l;
++ l = write(fd, &command[len], strlen(command) - len);
++
++ TRACE("Written '%s'.\n", command);
++
++ if (l == -1 && errno != EAGAIN)
++ {
++ perror("not written.\n");
++ break;
++ }
++ len += l;
++ } while (errno == EAGAIN && len < strlen(command));
++
++ return !(len == strlen(command));
++}
++
++int stop_tablet(int fd)
++{
++ int rc;
++ char buffer[10];
++ int fd_flags;
++
++ TRACE("Writing STOP command.\n");
++ rc = write_to_tablet(fd, ISDV4_STOP);
++
++ usleep(250000);
++
++ /* flush the line */
++ fd_flags = fcntl(fd, F_GETFL);
++ if (fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK) == 0)
++ {
++ while (read(fd, buffer, sizeof(buffer)) > 0)
++ TRACE("garbage flushed\n");
++ fcntl(fd, F_SETFL, fd_flags);
++ }
++
++ return rc;
++}
++
++int start_tablet(int fd)
++{
++ TRACE("Writing SAMPLING command.\n");
++ return write_to_tablet(fd, ISDV4_SAMPLING);
++}
++
++int wait_for_tablet(int fd)
++{
++#if 0
++ struct pollfd pfd = { fd, POLLIN, 0 };
++ int rc;
++
++ TRACE("Waiting for tablet...");
++ rc = poll(&pfd, 1, 1000);
++ if (rc < 0) {
++ perror("poll failed.");
++ return -1;
++ } else if (rc == 0) {
++ fprintf(stderr, "timeout.\n");
++ return -1;
++ } else if (pfd.revents & POLLIN)
++ TRACE("data available.\n");
++
++#endif
++ return 0;
++}
++
++void memdump(const unsigned char *buffer, int len)
++{
++ int n = 0;
++ if (!len)
++ return;
++
++ while(len-- && ++n) {
++ TRACE("%#hhx ", *buffer++);
++ if (n % 8 == 0)
++ TRACE("\n");
++ }
++
++ TRACE("\n");
++}
++
++int skip_garbage(unsigned char *buffer, size_t len)
++{
++ int i;
++ for (i = 0; i < len; i++)
++ if (buffer[i] & HEADER_BIT)
++ break;
++
++ if (i != 0)
++ TRACE("skipping over %d bytes.\n", (i < len) ? i : -1);
++
++ return (i < len) ? i : -1;
++}
++
++int read_data(int fd, unsigned char* buffer, int min_len)
++{
++ int len = 0;
++ int attempts = 10;
++ int skip;
++
++ TRACE("Reading %d bytes from device.\n", min_len);
++redo:
++ do {
++ int l = read(fd, &buffer[len], min_len);
++
++ if (l == -1) {
++ if (errno != EAGAIN) {
++ perror("Error reading data.");
++ return -1;
++ }
++ wait_for_tablet(fd);
++ attempts--;
++ continue;
++ } else {
++ TRACE("read %d bytes in one chunk.\n", l);
++ len += l;
++ }
++
++ } while (len < min_len && attempts);
++
++ if (!attempts) {
++ fprintf(stderr, "Only able to read %d bytes.\n", len);
++ memdump(buffer, len);
++ return -1;
++ }
++
++ TRACE("Read %d bytes.\n", len);
++
++ skip = skip_garbage(buffer, len);
++ if (skip > 0) {
++ TRACE("%d bytes garbage.\n", skip);
++ len -= skip;
++ memmove(buffer, &buffer[skip], len);
++ goto redo;
++ }
++
++ if (len > min_len)
++ {
++ TRACE("%d bytes unexpected data.\n", (len - min_len));
++ memdump(&buffer[min_len], len - min_len);
++ }
++
++
++ return len;
++}
++
++int query_tablet(int fd)
++{
++ ISDV4QueryReply reply;
++ ISDV4TouchQueryReply touch;
++
++ unsigned char buffer[ISDV4_PKGLEN_TPCCTL];
++ int len, rc;
++
++ TRACE("Querying tablet.\n");
++
++ if (stop_tablet(fd)) goto out;
++ if (write_to_tablet(fd, ISDV4_QUERY)) goto out;
++ if (wait_for_tablet(fd)) goto out;
++
++ len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
++ if (len < 1)
++ goto out;
++
++ if (!(buffer[0] & CONTROL_BIT))
++ {
++ TRACE("+++ out of cheese error +++ redo from start +++\n");
++ /* X driver claims that the first read may fail ??? */
++ len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
++ }
++
++ TRACE("Parsing query reply.\n");
++ rc = isdv4ParseQuery(buffer, len, &reply);
++ if (rc < 0)
++ {
++ fprintf(stderr, "parsing error code %d\n", rc);
++ goto out;
++ }
++
++ printf("TABLET: version: %d\n", reply.version);
++ printf("TABLET: x max: %d y max %d\n", reply.x_max, reply.y_max);
++ printf("TABLET: tilt_x max: %d tilt_y max %d\n", reply.tilt_x_max, reply.tilt_y_max);
++ printf("TABLET: pressure max: %d\n", reply.pressure_max);
++
++ /* check for touch capabilities */
++ TRACE("Trying touch query\n");
++ if (stop_tablet(fd)) goto out;
++ if (write_to_tablet(fd, ISDV4_TOUCH_QUERY)) goto out;
++ if (wait_for_tablet(fd)) goto out;
++
++ memset(buffer, 0, sizeof(buffer));
++ len = read_data(fd, buffer, ISDV4_PKGLEN_TPCCTL);
++ if (len < 1 && errno != EAGAIN)
++ goto out;
++
++ TRACE("Parsing touch query reply.\n");
++ rc = isdv4ParseTouchQuery(buffer, len, &touch);
++ if (rc < 0)
++ {
++ fprintf(stderr, "touch parsing error code %d\n", rc);
++ /* failure to parse touch query is not fatal */
++ } else {
++ printf("TOUCH version: %d\n", touch.version);
++ printf("TOUCH x max: %d y max %d\n", touch.x_max, touch.y_max);
++ printf("TOUCH panel resolution: %d\n", touch.panel_resolution);
++ printf("TOUCH capacity resolution: %d\n", touch.capacity_resolution);
++ printf("TOUCH sensor id: %d\n", touch.sensor_id);
++ }
++
++ return touch.sensor_id;
++
++out:
++ fprintf(stderr, "error during query.\n");
++ return -1;
++}
++
++int reset_tablet(int fd)
++{
++ char buffer[10];
++ TRACE("Reset requested, resetting tablet\n");
++
++ if (stop_tablet(fd)) goto out;
++ if (write_to_tablet(fd, ISDV4_RESET)) goto out;
++ if (wait_for_tablet(fd)) goto out;
++
++ memset(buffer, 0, sizeof(buffer));
++ if (read(fd, buffer, sizeof(buffer)) < 1 && errno != EAGAIN)
++ goto out;
++
++ if (buffer[0] == '&')
++ return 0;
++
++out:
++ fprintf(stderr, "failed to reset tablet.\n");
++ return 1;
++}
++
++int parse_pen_packet(unsigned char* buffer)
++{
++ int rc;
++ ISDV4CoordinateData coord;
++
++ TRACE("Parsing coordinate data.\n");
++ rc = isdv4ParseCoordinateData(buffer, ISDV4_PKGLEN_TPCPEN, &coord);
++ if (rc == -1) {
++ fprintf(stderr, "failed to parse coordinate data.\n");
++ return -1;
++ }
++
++ printf("PEN ");
++ printf("%ld:", time(NULL));
++ printf("%5d/%5d | pressure: %3d | ", coord.x, coord.y, coord.pressure);
++ printf(" %3d/%3d |", coord.tilt_x, coord.tilt_y);
++ printf("%1s %1s %1s %1s |\n", coord.proximity ? "p" : "",
++ coord.tip ? "t" : "",
++ coord.side ? "s" : "",
++ coord.eraser ? "e" : "");
++ return 0;
++}
++
++int parse_touch_packet(unsigned char* buffer, int packetlength)
++{
++ ISDV4TouchData touchdata;
++ int rc;
++
++ rc = isdv4ParseTouchData(buffer, packetlength, packetlength, &touchdata);
++ if (rc == -1) {
++ fprintf(stderr, "failed to parse touch data.\n");
++ return -1;
++ }
++
++ printf("TOUCH ");
++ printf("%ld:", time(NULL));
++ printf("%5d/%5d | capacity: %3d | ", touchdata.x, touchdata.y, touchdata.capacity);
++ printf("%d | ", touchdata.status);
++
++ if (packetlength == ISDV4_PKGLEN_TOUCH2FG)
++ printf("%d | %d/%d |", touchdata.finger2.status, touchdata.finger2.x, touchdata.finger2.y);
++
++ printf("\n");
++
++ return 0;
++
++}
++
++int event_loop(int fd, int sensor_id)
++{
++ unsigned char buffer[256];
++ int dlen = 0;
++ int packetlength = ISDV4_PKGLEN_TPCPEN;
++
++ TRACE("Waiting for events\n");
++
++ if (fcntl(fd, F_SETFD, O_NONBLOCK) == -1)
++ perror("Nonblock failed.");
++
++ memset(buffer, 0, sizeof(buffer));
++
++ while (1) {
++ int r, garbage = 0;
++ r = read(fd, &buffer[dlen], sizeof(buffer) - dlen);
++
++ if (r == -1) {
++ if (errno == EAGAIN)
++ continue;
++ else {
++ perror("Error during read.");
++ goto out;
++ }
++ }
++
++ dlen += r;
++
++ if (buffer[0] & HEADER_BIT)
++ {
++ packetlength = ISDV4_PKGLEN_TPCPEN;
++ if (buffer[0] & TOUCH_CONTROL_BIT)
++ packetlength = ISDV4PacketLengths[sensor_id];
++ } else {
++ int bytes = skip_garbage(buffer, dlen);
++ if (bytes > 0) {
++ dlen -= bytes;
++ memmove(buffer, &buffer[bytes], sizeof(buffer) - bytes);
++ }
++ continue;
++ }
++
++
++ if (dlen < packetlength)
++ continue;
++ TRACE("Expecting packet sized %d\n", packetlength);
++
++ if (buffer[0] & CONTROL_BIT) {
++ dlen -= packetlength;
++ continue;
++ }
++
++ switch(packetlength)
++ {
++ case ISDV4_PKGLEN_TPCPEN:
++ if (parse_pen_packet(buffer))
++ garbage = 1;
++ break;
++ default: /* all others */
++ if (parse_touch_packet(buffer, packetlength))
++ garbage = 1;
++ }
++
++ if (garbage) {
++ int bytes;
++ bytes = skip_garbage(buffer, packetlength);
++ if (bytes > 0) {
++ dlen -= bytes;
++ memmove(buffer, &buffer[bytes], sizeof(buffer) - bytes);
++ }
++ garbage = 0;
++ } else {
++ memmove(buffer, &buffer[packetlength], sizeof(buffer) - packetlength);
++ dlen -= packetlength;
++ }
++ }
++
++
++ return 0;
++out:
++ return 1;
++}
++
+diff --git a/tools/tools-shared.h b/tools/tools-shared.h
+new file mode 100644
+index 0000000..0a1e41f
+--- /dev/null
++++ b/tools/tools-shared.h
+@@ -0,0 +1,41 @@
++/*
++ * Copyright 2014 by Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef TOOLS_SHARED_H_
++#define TOOLS_SHARED_H_
++
++void version(void);
++int open_device(const char *path);
++int set_serial_attr(int fd, unsigned int baud);
++int write_to_tablet(int fd, char *command);
++int stop_tablet(int fd);
++int start_tablet(int fd);
++int wait_for_tablet(int fd);
++void memdump(const unsigned char *buffer, int len);
++int skip_garbage(unsigned char *buffer, size_t len);
++int read_data(int fd, unsigned char* buffer, int min_len);
++int query_tablet(int fd);
++int reset_tablet(int fd);
++int parse_pen_packet(unsigned char* buffer);
++int parse_touch_packet(unsigned char* buffer, int packetlength);
++int event_loop(int fd, int sensor_id);
++
++#define TRACE(...) \
++ do { if (verbose) printf("... " __VA_ARGS__); } while(0)
++
++#endif /* TOOLS_SHARED_H_ */
+--
+1.8.5.3
+
diff --git a/0012-tools-re-enable-wait-for-tablet.patch b/0012-tools-re-enable-wait-for-tablet.patch
new file mode 100644
index 0000000..b397317
--- /dev/null
+++ b/0012-tools-re-enable-wait-for-tablet.patch
@@ -0,0 +1,41 @@
+From 76ec64178f6cc8d6d737408ee23f36f5a0ed6c43 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:56:57 +1000
+Subject: [PATCH 12/14] tools: re-enable wait-for-tablet
+
+We need this to actually time out, otherwise we can't tell whether we have the
+wrong baud rate set. That's fine for a debugger where a human will terminate,
+but not for the upcoming inputattach clone.fine for a debugger where a human
+will terminate, but not for the upcoming inputattach clone.fine for a debugger
+where a human will terminate, but not for the upcoming inputattach clone.fine
+for a debugger where a human will terminate, but not for the upcoming
+inputattach clone.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/tools-shared.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/tools/tools-shared.c b/tools/tools-shared.c
+index 4d22cdf..2537211 100644
+--- a/tools/tools-shared.c
++++ b/tools/tools-shared.c
+@@ -164,7 +164,6 @@ int start_tablet(int fd)
+
+ int wait_for_tablet(int fd)
+ {
+-#if 0
+ struct pollfd pfd = { fd, POLLIN, 0 };
+ int rc;
+
+@@ -179,7 +178,6 @@ int wait_for_tablet(int fd)
+ } else if (pfd.revents & POLLIN)
+ TRACE("data available.\n");
+
+-#endif
+ return 0;
+ }
+
+--
+1.8.5.3
+
diff --git a/0013-tools-add-colon-after-TOUCH-output.patch b/0013-tools-add-colon-after-TOUCH-output.patch
new file mode 100644
index 0000000..35a416a
--- /dev/null
+++ b/0013-tools-add-colon-after-TOUCH-output.patch
@@ -0,0 +1,36 @@
+From 4600725950913539cccb0732ecb8d67faa26bf31 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:58:20 +1000
+Subject: [PATCH 13/14] tools: add colon after TOUCH output
+
+For consistency with the TABLET output.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/tools-shared.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/tools/tools-shared.c b/tools/tools-shared.c
+index 2537211..10d7008 100644
+--- a/tools/tools-shared.c
++++ b/tools/tools-shared.c
+@@ -317,11 +317,11 @@ int query_tablet(int fd)
+ fprintf(stderr, "touch parsing error code %d\n", rc);
+ /* failure to parse touch query is not fatal */
+ } else {
+- printf("TOUCH version: %d\n", touch.version);
+- printf("TOUCH x max: %d y max %d\n", touch.x_max, touch.y_max);
+- printf("TOUCH panel resolution: %d\n", touch.panel_resolution);
+- printf("TOUCH capacity resolution: %d\n", touch.capacity_resolution);
+- printf("TOUCH sensor id: %d\n", touch.sensor_id);
++ printf("TOUCH: version: %d\n", touch.version);
++ printf("TOUCH: x max: %d y max %d\n", touch.x_max, touch.y_max);
++ printf("TOUCH: panel resolution: %d\n", touch.panel_resolution);
++ printf("TOUCH: capacity resolution: %d\n", touch.capacity_resolution);
++ printf("TOUCH: sensor id: %d\n", touch.sensor_id);
+ }
+
+ return touch.sensor_id;
+--
+1.8.5.3
+
diff --git a/0014-tools-add-an-inputattach-like-tool.patch b/0014-tools-add-an-inputattach-like-tool.patch
new file mode 100644
index 0000000..a28418f
--- /dev/null
+++ b/0014-tools-add-an-inputattach-like-tool.patch
@@ -0,0 +1,264 @@
+From d54ad59f636ddfffba251d3756a41ebe1ce9224c Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Tue, 18 Mar 2014 10:49:22 +1000
+Subject: [PATCH 14/14] tools: add an inputattach-like tool
+
+Does more or less the same thing as inputattach, but tries to be a bit smarter
+about the baud rate depending on the tablet model. And re-tries if the baud
+rate is wrong.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+---
+ tools/Makefile.am | 5 +-
+ tools/isdv4-serial-inputattach.c | 216 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 220 insertions(+), 1 deletion(-)
+ create mode 100644 tools/isdv4-serial-inputattach.c
+
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index 5eba0a6..a49380b 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -18,7 +18,7 @@
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-bin_PROGRAMS = xsetwacom isdv4-serial-debugger
++bin_PROGRAMS = xsetwacom isdv4-serial-debugger isdv4-serial-inputattach
+
+ AM_CPPFLAGS = -I$(top_srcdir)/include
+ AM_CFLAGS = $(XORG_CFLAGS) $(X11_CFLAGS)
+@@ -27,6 +27,9 @@ AM_LDFLAGS = $(X11_LIBS)
+ shared_sources = tools-shared.h tools-shared.c
+
+ isdv4_serial_debugger_SOURCES = isdv4-serial-debugger.c $(shared_sources)
++isdv4_serial_inputattach_SOURCES = isdv4-serial-inputattach.c $(shared_sources)
++isdv4_serial_inputattach_CFLAGS = $(UDEV_CFLAGS)
++isdv4_serial_inputattach_LDADD = $(UDEV_LIBS)
+
+
+ if UNITTESTS
+diff --git a/tools/isdv4-serial-inputattach.c b/tools/isdv4-serial-inputattach.c
+new file mode 100644
+index 0000000..7ce1b44
+--- /dev/null
++++ b/tools/isdv4-serial-inputattach.c
+@@ -0,0 +1,216 @@
++/*
++ * Copyright 2014 by Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/* inputattach clone for ISDV4 serial devices */
++
++#ifdef HAVE_CONFIG_H
++#define WACOM_TOOLS
++#include "config.h"
++#endif
++
++#include <linux/serio.h>
++#include <libudev.h>
++
++#include <getopt.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <errno.h>
++#include <poll.h>
++#include <sys/ioctl.h>
++#include <signal.h>
++
++#include "tools-shared.h"
++
++int verbose;
++
++static void usage(void)
++{
++ printf(
++ "Usage: %s [options] device\n"
++ "Options: \n"
++ "-h, --help - usage\n"
++ "--verbose - verbose output\n"
++ "--version - version info\n"
++ "--baudrate <19200|38400> - set baudrate\n",
++ program_invocation_short_name
++ );
++}
++
++static int set_line_discipline(int fd, int ldisc)
++{
++ int rc;
++
++ rc = ioctl(fd, TIOCSETD, &ldisc);
++ if (rc < 0)
++ perror("can't set line discipline");
++
++ return rc;
++}
++
++static int bind_kernel_driver(int fd)
++{
++ unsigned long devt;
++ unsigned int id = 0, extra = 0;
++
++ devt = SERIO_W8001 | (id << 8) | (extra << 16);
++ if (ioctl(fd, SPIOCSTYPE, &devt)) {
++ perror("Failed to set device type");
++ return -1;
++ }
++
++ return 0;
++}
++
++int get_baud_rate(int fd)
++{
++ struct stat st;
++ int baudrate = 19200;
++ int id;
++ struct udev *udev;
++ struct udev_device *device, *parent;
++ const char *attr_id;
++
++ fstat(fd, &st);
++
++ udev = udev_new();
++ device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
++ parent = device;
++
++ while (parent) {
++ attr_id = udev_device_get_sysattr_value(parent, "id");
++ if (attr_id &&
++ (strncmp(attr_id, "WACf", 4) == 0 || strncmp(attr_id, "FUJ", 3) == 0))
++ break;
++
++ parent = udev_device_get_parent(parent);
++ }
++
++ /* Devices up to WACf007 are 19200, newer devices are 38400. FUJ
++ devices are all 19200 */
++ if (attr_id && sscanf(attr_id, "WACf%x", &id) == 1 && id >= 0x8)
++ baudrate = 38400;
++
++ if (device)
++ udev_device_unref(device);
++ udev_unref(udev);
++
++ return baudrate;
++}
++
++void sighandler(int signum)
++{
++ /* We don't need to do anything here, triggering the signal is
++ * enough to trigger EINTR in read() and then reset the line
++ * discipline in main */
++}
++
++int main(int argc, char **argv)
++{
++ int sensor_id;
++ char *filename;
++ int fd, rc = 1;
++ int baudrate = -1;
++
++ int c, optidx = 0;
++ struct option options[] = {
++ {"help", 0, NULL, 'h'},
++ {"verbose", 0, NULL, 'v'},
++ {"version", 0, NULL, 'V'},
++ {"baudrate", 1, NULL, 'b'},
++ {NULL, 0, NULL, 0}
++ };
++
++ while ((c = getopt_long(argc, argv, "h", options, &optidx)) != -1) {
++ switch(c) {
++ case 'v':
++ verbose = 1;
++ break;
++ case 'V':
++ version();
++ return 0;
++ case 'b':
++ baudrate = atoi(optarg);
++ if (baudrate == 0) {
++ usage();
++ return 1;
++ }
++ break;
++ case 'h':
++ default:
++ usage();
++ return 0;
++ }
++ }
++
++ if (optind == argc) {
++ usage();
++ return 1;
++ }
++
++ filename = argv[optind];
++
++ fd = open_device(filename);
++ if (fd < 0)
++ goto out;
++
++ /* only guess if we didn't get a baud rate */
++ if (baudrate == -1 && (baudrate = get_baud_rate(fd)) < 0)
++ goto out;
++
++ set_serial_attr(fd, baudrate);
++
++ sensor_id = query_tablet(fd);
++ if (sensor_id < 0) {
++ /* query failed, maybe the wrong baud rate? */
++ baudrate = (baudrate == 19200) ? 38400 : 19200;
++
++ printf("Initial tablet query failed. Trying with baud rate %d.\n", baudrate);
++
++ set_serial_attr(fd, baudrate);
++ sensor_id = query_tablet(fd);
++ }
++
++ if (sensor_id < 0) {
++ fprintf(stderr, "Tablet query failed, cannot initialize.\n");
++ return 1;
++ }
++
++ /* some of the 19200 tablets can't set the line discipline */
++ set_line_discipline(fd, N_MOUSE);
++
++ if (bind_kernel_driver(fd) < 0) {
++ fprintf(stderr, "Failed to bind the kernel driver.\n");
++ goto out;
++ }
++
++ signal(SIGINT, sighandler);
++ signal(SIGHUP, sighandler);
++ read(fd, NULL, 0);
++
++ set_line_discipline(fd, 0);
++
++ rc = 0;
++out:
++ if (fd >= 0)
++ close(fd);
++ return rc;
++}
++
++/* vim: set noexpandtab tabstop=8 shiftwidth=8: */
+--
+1.8.5.3
+
diff --git a/wacom-inputattach at .service b/wacom-inputattach at .service
index 3193d8a..40c74bb 100644
--- a/wacom-inputattach at .service
+++ b/wacom-inputattach at .service
@@ -3,6 +3,5 @@ Description=inputattach for Wacom ISDv4-compatible serial devices
[Service]
Type=simple
-ExecStart=/usr/bin/inputattach -w8001 /dev/%I
+ExecStart=/usr/bin/isdv4-serial-inputattach /dev/%I
Restart=on-success
-
diff --git a/xorg-x11-drv-wacom.spec b/xorg-x11-drv-wacom.spec
index e6516da..1e034a4 100644
--- a/xorg-x11-drv-wacom.spec
+++ b/xorg-x11-drv-wacom.spec
@@ -9,7 +9,7 @@
Summary: Xorg X11 wacom input driver
Name: xorg-x11-drv-wacom
Version: 0.23.0
-Release: 10%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
+Release: 11%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
URL: http://www.x.org
License: GPLv2+
Group: User Interface/X Hardware Support
@@ -24,7 +24,21 @@ Source0: http://prdownloads.sourceforge.net/linuxwacom/xf86-input-wacom-%{versio
Source3: 70-wacom.rules
Source4: wacom-inputattach at .service
-Patch01: 0001-conf-add-N-Trig-DuoSense-to-our-matched-devices.patch
+Patch00: 0001-conf-add-N-Trig-DuoSense-to-our-matched-devices.patch
+Patch01: 0001-configure-both-clients-and-drivers-need-the-protocol.patch
+Patch02: 0002-Include-stdint-from-isdv4.h.patch
+Patch03: 0003-isdv4-inline-all-isdv4-parsing-functions.patch
+Patch04: 0004-tools-rearrange-serial-settings.patch
+Patch05: 0005-tools-open-serial-devices-with-O_NOCTTY.patch
+Patch06: 0006-tools-use-perror-instead-of-fprintf.patch
+Patch07: 0007-tools-drop-double-call-to-tcsetattr.patch
+Patch08: 0008-tools-drop-global-packagelen.patch
+Patch09: 0009-tools-drop-leftover-global-variables.patch
+Patch10: 0010-tools-make-event_loop-static.patch
+Patch11: 0011-tools-split-out-the-debugger-into-the-actual-debugge.patch
+Patch12: 0012-tools-re-enable-wait-for-tablet.patch
+Patch13: 0013-tools-add-colon-after-TOUCH-output.patch
+Patch14: 0014-tools-add-an-inputattach-like-tool.patch
ExcludeArch: s390 s390x
@@ -36,7 +50,6 @@ BuildRequires: systemd systemd-devel
Requires: Xorg %(xserver-sdk-abi-requires ansic)
Requires: Xorg %(xserver-sdk-abi-requires xinput)
-Requires: linuxconsoletools
Provides: linuxwacom = %{version}-%{release}
Obsoletes: linuxwacom <= 0.8.4.3
@@ -46,7 +59,21 @@ X.Org X11 wacom input driver for Wacom tablets.
%prep
%setup -q -n %{tarball}-%{?gitdate:%{gitdate}}%{!?gitdate:%{version}}
+%patch00 -p1
%patch01 -p1
+%patch02 -p1
+%patch03 -p1
+%patch04 -p1
+%patch05 -p1
+%patch06 -p1
+%patch07 -p1
+%patch08 -p1
+%patch09 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
%build
autoreconf --force -v --install || exit 1
@@ -83,6 +110,7 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/X11/xorg.conf.d/50-wacom.conf
%{_bindir}/xsetwacom
%{_prefix}/lib/udev/rules.d/70-wacom.rules
+%{_bindir}/isdv4-serial-inputattach
%{_unitdir}/wacom-inputattach at .service
%package devel
@@ -106,6 +134,9 @@ X.Org X11 wacom input driver development files.
%{_bindir}/isdv4-serial-debugger
%changelog
+* Wed Mar 19 2014 Peter Hutterer <peter.hutterer at redhat.com> 0.23.0-11
+- Use custom wacom inputattach tool (#1046912)
+
* Mon Jan 20 2014 Peter Hutterer <peter.hutterer at redhat.com> 0.23.0-10
- Match N-Trig DuoSense (#1031343)
More information about the scm-commits
mailing list