Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/wcmISDV4.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++--------
 src/wcmISDV4.h |   29 ++++++++++++-
 2 files changed, 135 insertions(+), 20 deletions(-)

diff --git a/src/wcmISDV4.c b/src/wcmISDV4.c
index f60686b..2c70d00 100644
--- a/src/wcmISDV4.c
+++ b/src/wcmISDV4.c
@@ -50,6 +50,11 @@ static inline int isdv4ParseQuery(const char *buffer, const 
size_t len,
 static inline int isdv4ParseTouchQuery(const char *buffer, const size_t len,
                                        ISDV4TouchQueryReply *reply);
 
+static inline int isdv4ParseTouchData(const unsigned char *buffer, const 
size_t len,
+                                     const size_t pktlen, ISDV4TouchData 
*touchdata);
+
+static inline int isdv4ParseCoordinateData(const unsigned char *buffer, const 
size_t len,
+                                          ISDV4CoordinateData *coord);
 
        WacomDeviceClass gWacomISDV4Device =
        {
@@ -450,7 +455,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned 
char* data, int len)
                return 0;
 
        /* determine the type of message (touch or stylus) */
-       if (data[0] & 0x10) /* a touch data */
+       if (data[0] & TOUCH_CONTROL_BIT) /* a touch data */
        {
                if ((last->device_id != TOUCH_DEVICE_ID && last->device_id &&
                                 last->proximity ) || !common->wcmTouch)
@@ -472,7 +477,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned 
char* data, int len)
        }
 
        /* Coordinate data bit check */
-       if (data[0] & 0x40) /* control data */
+       if (data[0] & CONTROL_BIT) /* control data */
                return common->wcmPktLength;
        else if ((n = wcmSerialValidate(local,data)) > 0)
                return n;
@@ -483,20 +488,29 @@ static int isdv4Parse(LocalDevicePtr local, const 
unsigned char* data, int len)
 
        if (common->wcmPktLength != ISDV4_PKGLEN_TPCPEN) /* a touch */
        {
-               ds->x = (((int)data[1]) << 7) | ((int)data[2]);
-               ds->y = (((int)data[3]) << 7) | ((int)data[4]);
-               if (common->wcmPktLength == ISDV4_PKGLEN_TOUCH9A)
+               ISDV4TouchData touchdata;
+               int rc;
+
+               rc = isdv4ParseTouchData(data, len, common->wcmPktLength, 
&touchdata);
+               if (rc == -1)
                {
-                       ds->capacity = (((int)data[5]) << 7) | ((int)data[6]);
+                       xf86Msg(X_ERROR, "%s: failed to parse touch data.\n",
+                               local->name);
+                       return 0;
                }
-               ds->buttons = ds->proximity = data[0] & 0x01;
+
+
+               ds->x = touchdata.x;
+               ds->y = touchdata.y;
+               ds->capacity = touchdata.capacity;
+               ds->buttons = ds->proximity = touchdata.status;
                ds->device_type = TOUCH_ID;
                ds->device_id = TOUCH_DEVICE_ID;
 
                if (common->wcmPktLength == ISDV4_PKGLEN_TOUCH2FG)
                {
-                       if ((data[0] & 0x02) || (!(data[0] & 0x02) &&
-                                        lastTemp->proximity))
+                       if (touchdata.finger2.status ||
+                           (!touchdata.finger2.status && lastTemp->proximity))
                        {
                                /* Got 2FGT. Send the first one if received */
                                if (ds->proximity || (!ds->proximity &&
@@ -512,11 +526,11 @@ static int isdv4Parse(LocalDevicePtr local, const 
unsigned char* data, int len)
                                channel = 1;
                                ds = &common->wcmChannel[channel].work;
                                RESET_RELATIVE(*ds);
-                               ds->x = (((int)data[7]) << 7) | ((int)data[8]);
-                               ds->y = (((int)data[9]) << 7) | ((int)data[10]);
+                               ds->x = touchdata.finger2.x;
+                               ds->y = touchdata.finger2.y;
                                ds->device_type = TOUCH_ID;
                                ds->device_id = TOUCH_DEVICE_ID;
-                               ds->proximity = data[0] & 0x02;
+                               ds->proximity = touchdata.finger2.status;
                                /* time stamp for 2FGT gesture events */
                                if ((ds->proximity && !lastTemp->proximity) ||
                                            (!ds->proximity && 
lastTemp->proximity))
@@ -529,19 +543,28 @@ static int isdv4Parse(LocalDevicePtr local, const 
unsigned char* data, int len)
        }
        else
        {
-               ds->proximity = (data[0] & 0x20);
+               int rc;
+               ISDV4CoordinateData coord;
+
+               rc = isdv4ParseCoordinateData(data, ISDV4_PKGLEN_TPCPEN, 
&coord);
+
+               if (rc == -1)
+               {
+                       xf86Msg(X_ERROR, "%s: failed to parse coordinate 
data.\n", local->name);
+                       return 0;
+               }
+
+               ds->proximity = coord.proximity;
 
                /* x and y in "normal" orientetion (wide length is X) */
-               ds->x = (((int)data[6] & 0x60) >> 5) | ((int)data[2] << 2) |
-                       ((int)data[1] << 9);
-               ds->y = (((int)data[6] & 0x18) >> 3) | ((int)data[4] << 2) |
-                       ((int)data[3] << 9);
+               ds->x = coord.x;
+               ds->y = coord.y;
 
                /* pressure */
-               ds->pressure = (((data[6] & 0x07) << 7) | data[5] );
+               ds->pressure = coord.pressure;
 
                /* buttons */
-               ds->buttons = (data[0] & 0x07);
+               ds->buttons = coord.tip | (coord.side << 1) | (coord.eraser << 
2);
 
                /* check which device we have */
                cur_type = (ds->buttons & 4) ? ERASER_ID : STYLUS_ID;
@@ -781,4 +804,69 @@ static inline int isdv4ParseTouchQuery(const char *buffer, 
const size_t len,
 
        return ISDV4_PKGLEN_TPCCTL;
 }
+
+/* pktlen defines what touch type we parse */
+static inline int isdv4ParseTouchData(const unsigned char *buffer, const 
size_t buff_len,
+                                     const size_t pktlen, ISDV4TouchData 
*touchdata)
+{
+       int header, touch;
+
+       if (!touchdata || buff_len < pktlen)
+               return 0;
+
+       header = !!(buffer[0] & HEADER_BIT);
+       touch = !!(buffer[0] & TOUCH_CONTROL_BIT);
+
+       if (header != 1 || touch != 1)
+               return -1;
+
+       memset(touchdata, 0, sizeof(*touchdata));
+
+       touchdata->status = buffer[0] & 0x1;
+       /* FIXME: big endian */
+       touchdata->x = buffer[1] << 7 | buffer[2];
+       touchdata->y = buffer[3] << 7 | buffer[4];
+       if (pktlen == ISDV4_PKGLEN_TOUCH9A)
+               touchdata->capacity = buffer[5] << 7 | buffer[6];
+
+       if (pktlen == ISDV4_PKGLEN_TOUCH2FG)
+       {
+               touchdata->finger2.x = buffer[7] << 7 | buffer[8];
+               touchdata->finger2.y = buffer[9] << 7 | buffer[10];
+               touchdata->finger2.status = !!(buffer[0] & 0x2);
+               /* FIXME: is there a fg2 capacity? */
+       }
+
+       return pktlen;
+}
+
+static inline int isdv4ParseCoordinateData(const unsigned char *buffer, const 
size_t len,
+                                          ISDV4CoordinateData *coord)
+{
+       int header, control;
+
+       if (!coord || len < ISDV4_PKGLEN_TPCPEN)
+               return 0;
+
+       header = !!(buffer[0] & HEADER_BIT);
+       control = !!(buffer[0] & TOUCH_CONTROL_BIT);
+
+       if (header != 1 || control != 0)
+               return -1;
+
+       coord->proximity = (buffer[0] >> 5) & 0x1;
+       coord->tip = buffer[0] & 0x1;
+       coord->side = (buffer[0] >> 1) & 0x1;
+       coord->eraser = (buffer[0] >> 2) & 0x1;
+       /* FIXME: big endian */
+       coord->x = (buffer[1] << 9) | (buffer[2] << 2) | ((buffer[6] >> 5) & 
0x3);
+       coord->y = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[6] >> 3) & 
0x3);
+
+       coord->pressure = ((buffer[6] & 0x7) << 7) | buffer[5];
+       coord->tilt_x = buffer[7];
+       coord->tilt_y = buffer[8];
+
+       return ISDV4_PKGLEN_TPCPEN;
+}
+
 /* vim: set noexpandtab shiftwidth=8: */
diff --git a/src/wcmISDV4.h b/src/wcmISDV4.h
index cd57d5e..cb1ad1b 100644
--- a/src/wcmISDV4.h
+++ b/src/wcmISDV4.h
@@ -30,6 +30,7 @@
 #define HEADER_BIT      0x80
 #define CONTROL_BIT     0x40
 #define DATA_ID_MASK    0x3F
+#define TOUCH_CONTROL_BIT 0x10
 
 /* ISDV4 protocol parsing structs. */
 
@@ -44,7 +45,6 @@ typedef struct {
        uint16_t version;
 } ISDV4QueryReply;
 
-
 /* Touch Query reply data */
 typedef struct {
        uint8_t data_id;        /* always 01H */
@@ -56,6 +56,33 @@ typedef struct {
        uint16_t version;
 } ISDV4TouchQueryReply;
 
+/* Touch Data format. Note that capacity and finger2 are only set for some
+ * devices (0 on all others) */
+typedef struct {
+       uint8_t status;         /* touch down/up */
+       uint16_t x;
+       uint16_t y;
+       uint16_t capacity;
+       struct {
+               uint8_t status;         /* touch down/up */
+               uint16_t x;
+               uint16_t y;
+       } finger2;
+} ISDV4TouchData;
+
+/* Coordinate data format */
+typedef struct {
+       uint8_t proximity;      /* in proximity? */
+       uint8_t tip;            /* tip/eraser pressed? */
+       uint8_t side;           /* side switch pressed? */
+       uint8_t eraser;         /* eraser pressed? */
+       uint16_t x;
+       uint16_t y;
+       uint16_t pressure;
+       uint8_t tilt_x;
+       uint8_t tilt_y;
+} ISDV4CoordinateData;
+
 #endif /* WCMISDV4_H */
 
 /* vim: set noexpandtab shiftwidth=8: */
-- 
1.6.6.1


------------------------------------------------------------------------------
Download Intel&#174; 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

Reply via email to