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 +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 +--- + 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 +Date: Tue, 18 Mar 2014 09:45:04 +1000 +Subject: [PATCH 02/14] Include stdint from isdv4.h + +Signed-off-by: Peter Hutterer +--- + 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 ++#include ++#include ++ + #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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +Date: Mon, 17 Mar 2014 08:58:46 +1000 +Subject: [PATCH 06/14] tools: use perror instead of fprintf + +Signed-off-by: Peter Hutterer +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +Date: Tue, 18 Mar 2014 10:31:15 +1000 +Subject: [PATCH 10/14] tools: make event_loop() static + +Signed-off-by: Peter Hutterer +--- + 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 +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 +--- + 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 + #include + +-#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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@.service b/wacom-inputattach@.service index 3193d8a..40c74bb 100644 --- a/wacom-inputattach@.service +++ b/wacom-inputattach@.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@.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@.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 0.23.0-11 +- Use custom wacom inputattach tool (#1046912) + * Mon Jan 20 2014 Peter Hutterer 0.23.0-10 - Match N-Trig DuoSense (#1031343)