Instead of having the protocol parsing code directly in the matching functions, move it to a separate function and return a struct with the interesting data already set. This eases code readability and improves debugging between protocol parsing errors and general driver bugs.
Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- src/Makefile.am | 2 +- src/wcmISDV4.c | 120 ++++++++++++++++++++++++++++++++++++++++++--------- src/wcmISDV4.h | 50 +++++++++++++++++++++ src/xf86WacomDefs.h | 2 + 4 files changed, 152 insertions(+), 22 deletions(-) create mode 100644 src/wcmISDV4.h diff --git a/src/Makefile.am b/src/Makefile.am index c5de655..e332ca8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,7 +34,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) INCLUDES=-I$(top_srcdir)/include/ @driver_n...@_drv_la_sources = xf86Wacom.c xf86Wacom.h \ - wcmCommon.c wcmConfig.c wcmISDV4.c \ + wcmCommon.c wcmConfig.c wcmISDV4.c wcmISDV4.h \ wcmFilter.c wcmFilter.h xf86WacomDefs.h \ wcmUSB.c wcmXCommand.c wcmValidateDevice.c \ wcmTouchFilter.c diff --git a/src/wcmISDV4.c b/src/wcmISDV4.c index 8d96216..f60686b 100644 --- a/src/wcmISDV4.c +++ b/src/wcmISDV4.c @@ -25,6 +25,7 @@ #include <xf86_OSproc.h> #include "wcmFilter.h" #include <linux/serial.h> +#include "wcmISDV4.h" #define ISDV4_QUERY "*" /* ISDV4 query command */ #define ISDV4_TOUCH_QUERY "%" /* ISDV4 touch query command */ @@ -44,6 +45,11 @@ static int wcmSerialValidate(LocalDevicePtr local, const unsigned char* data); static int wcmWaitForTablet(LocalDevicePtr local, char * data, int size); static int wcmWriteWait(LocalDevicePtr local, const char* request); +static inline int isdv4ParseQuery(const char *buffer, const size_t len, + ISDV4QueryReply *reply); +static inline int isdv4ParseTouchQuery(const char *buffer, const size_t len, + ISDV4TouchQueryReply *reply); + WacomDeviceClass gWacomISDV4Device = { @@ -260,20 +266,28 @@ static int isdv4GetRanges(LocalDevicePtr local) ret = isdv4Query(local, ISDV4_QUERY, data); if (ret == Success) { + ISDV4QueryReply reply; + int rc; + + rc = isdv4ParseQuery(data, sizeof(data), &reply); + if (rc <= 0) + { + xf86Msg(X_ERROR, "Error while parsing ISDV4 query.\n"); + return BadAlloc; + } + /* transducer data */ - common->wcmMaxZ = ( data[5] | ((data[6] & 0x07) << 7) ); - common->wcmMaxX = ( (data[1] << 9) | - (data[2] << 2) | ( (data[6] & 0x60) >> 5) ); - common->wcmMaxY = ( (data[3] << 9) | (data[4] << 2 ) - | ( (data[6] & 0x18) >> 3) ); - if (data[7] && data[8]) + common->wcmMaxZ = reply.pressure_max; + common->wcmMaxX = reply.x_max; + common->wcmMaxY = reply.y_max; + if (reply.tilt_x_max && reply.tilt_y_max) { - common->wcmMaxtiltX = data[7] + 1; - common->wcmMaxtiltY = data[8] + 1; + common->wcmMaxtiltX = reply.tilt_x_max; + common->wcmMaxtiltY = reply.tilt_y_max; common->wcmFlags |= TILT_ENABLED_FLAG; } - - common->wcmVersion = ( data[10] | (data[9] << 7) ); + + common->wcmVersion = reply.version; /* default to no pen 2FGT if size is undefined */ if (!common->wcmMaxX || !common->wcmMaxY) @@ -289,7 +303,17 @@ static int isdv4GetRanges(LocalDevicePtr local) common->wcmISDV4Speed = 38400; if (isdv4Query(local, ISDV4_TOUCH_QUERY, data) == Success) { - switch (data[2] & 0x07) + ISDV4TouchQueryReply reply; + int rc; + + rc = isdv4ParseTouchQuery(data, sizeof(data), &reply); + if (rc <= 0) + { + xf86Msg(X_ERROR, "Error while parsing ISDV4 touch query.\n"); + return BadAlloc; + } + + switch (reply.sensor_id) { case 0x00: /* resistive touch & pen */ common->wcmPktLength = ISDV4_PKGLEN_TOUCH93; @@ -319,7 +343,7 @@ static int isdv4GetRanges(LocalDevicePtr local) break; } - switch(data[0] & 0x3f) + switch(reply.data_id) { /* single finger touch */ case 0x01: @@ -348,21 +372,19 @@ static int isdv4GetRanges(LocalDevicePtr local) } /* don't overwrite the default */ - if (((data[2]& 0x78) | data[3] | data[4] | data[5] | data[6])) + if (reply.x_max | reply.y_max) { - common->wcmMaxTouchX = ((data[3] << 9) | - (data[4] << 2) | ((data[2] & 0x60) >> 5)); - common->wcmMaxTouchY = ((data[5] << 9) | - (data[6] << 2) | ((data[2] & 0x18) >> 3)); + common->wcmMaxTouchX = reply.x_max; + common->wcmMaxTouchY = reply.y_max; } - else if (data[1]) + else if (reply.panel_resolution) common->wcmMaxTouchX = common->wcmMaxTouchY = - (int)(1 << data[1]); + (1 << reply.panel_resolution); - if (data[1]) + if (reply.panel_resolution) common->wcmTouchResolX = common->wcmTouchResolY = 10; - common->wcmVersion = ( data[10] | (data[9] << 7) ); + common->wcmVersion = reply.version; ret = Success; DBG(2, priv, "touch speed=%d " @@ -703,4 +725,60 @@ int isdv4ProbeKeys(LocalDevicePtr local, unsigned long *keys) return tablet_id; } +/* Convert buffer data of buffer sized len into a query reply. + * Returns the number of bytes read from buffer or 0 if the buffer was on + * insufficient length. Returns -1 on parsing or internal errors. + */ +static inline int isdv4ParseQuery(const char *buffer, const size_t len, + ISDV4QueryReply *reply) +{ + int header, control; + + if (!reply || len < ISDV4_PKGLEN_TPCCTL) + return 0; + + header = !!(buffer[0] & HEADER_BIT); + control = !!(buffer[0] & CONTROL_BIT); + + if (!header || !control) + return -1; + + reply->data_id = buffer[0] & DATA_ID_MASK; + + /* FIXME: big endian? */ + reply->x_max = (buffer[1] << 9) | (buffer[2] << 2) | ((buffer[6] >> 5) & 0x3); + reply->y_max = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[6] >> 3) & 0x3); + reply->pressure_max = buffer[5] | (buffer[6] & 0x7); + reply->tilt_y_max = buffer[7]; + reply->tilt_x_max = buffer[8]; + reply->version = buffer[9] << 7 | buffer[10]; + + return ISDV4_PKGLEN_TPCCTL; +} + +static inline int isdv4ParseTouchQuery(const char *buffer, const size_t len, + ISDV4TouchQueryReply *reply) +{ + int header, control; + + if (!reply || len < ISDV4_PKGLEN_TPCCTL) + return 0; + + header = !!(buffer[0] & HEADER_BIT); + control = !!(buffer[0] & CONTROL_BIT); + + if (!header || !control) + return -1; + + reply->data_id = buffer[0] & DATA_ID_MASK; + reply->sensor_id = buffer[2] & 0x7; + reply->panel_resolution = buffer[1]; + /* FIXME: big endian? */ + reply->x_max = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[2] >> 5) & 0x3); + reply->y_max = (buffer[5] << 9) | (buffer[6] << 2) | ((buffer[2] >> 3) & 0x3); + reply->capacity_resolution = buffer[7]; + reply->version = buffer[9] << 7 | buffer[10]; + + return ISDV4_PKGLEN_TPCCTL; +} /* vim: set noexpandtab shiftwidth=8: */ diff --git a/src/wcmISDV4.h b/src/wcmISDV4.h new file mode 100644 index 0000000..93c5e19 --- /dev/null +++ b/src/wcmISDV4.h @@ -0,0 +1,50 @@ +/* + * Copyright 2010 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 WCMISDV4_H +#define WCMISDV4_H + +/* ISDV4 protocol parsing structs. */ + +/* Query reply data */ +typedef struct { + unsigned char data_id; /* always 00H */ + uint16_t x_max; + uint16_t y_max; + uint16_t pressure_max; + uint8_t tilt_x_max; + uint8_t tilt_y_max; + uint16_t version; +} ISDV4QueryReply; + + +/* Touch Query reply data */ +typedef struct { + uint8_t data_id; /* always 01H */ + uint8_t panel_resolution; + uint8_t sensor_id; + uint16_t x_max; + uint16_t y_max; + uint8_t capacity_resolution; + uint16_t version; +} ISDV4TouchQueryReply; + +#endif /* WCMISDV4_H */ + +/* vim: set noexpandtab shiftwidth=8: */ diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h index 3a9a89a..d4e18f8 100644 --- a/src/xf86WacomDefs.h +++ b/src/xf86WacomDefs.h @@ -40,6 +40,8 @@ #define PROXOUT_GRAPHIRE_DISTANCE 42 #define HEADER_BIT 0x80 +#define CONTROL_BIT 0x40 +#define DATA_ID_MASK 0x3F #ifndef BTN_TOOL_DOUBLETAP #define BTN_TOOL_DOUBLETAP 0x14d -- 1.6.6.1 ------------------------------------------------------------------------------ Download Intel® Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel