summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile15
-rw-r--r--driver/multitouch.c8
-rw-r--r--include/abs2mt.h39
-rw-r--r--include/capabilities.h (renamed from include/mtdev-caps.h)8
-rw-r--r--include/common.h49
-rw-r--r--include/hwstate.h6
-rw-r--r--include/match.h36
-rw-r--r--include/mtbit.h14
-rw-r--r--include/mtdev-evbuf.h57
-rw-r--r--include/mtdev-iobuf.h38
-rw-r--r--include/mtdev.h57
-rw-r--r--include/mtouch.h7
-rw-r--r--match/match.c385
-rw-r--r--match/test.c135
-rw-r--r--mtdev/core.c402
-rw-r--r--mtdev/iobuf.c63
-rw-r--r--mtdev/mapgen.c69
-rw-r--r--mtdev/test.c79
-rw-r--r--src/capabilities.c (renamed from mtdev/caps.c)22
-rw-r--r--src/hwstate.c24
-rw-r--r--src/memory.c4
-rw-r--r--src/mtouch.c32
-rw-r--r--src/mtstate.c14
-rw-r--r--src/test.c4
24 files changed, 58 insertions, 1509 deletions
diff --git a/Makefile b/Makefile
index b8697a2..81eec08 100644
--- a/Makefile
+++ b/Makefile
@@ -4,20 +4,13 @@ EXTRAVERSION = beta1
4 4
5LIBRARY = multitouch.so 5LIBRARY = multitouch.so
6FDIS = 11-multitouch.fdi 6FDIS = 11-multitouch.fdi
7MODULES = match mtdev src 7MODULES = src
8XMODULES = driver 8XMODULES = driver
9 9
10o_match = match 10o_src = capabilities hwstate mtstate memory mtouch gestures
11
12o_mtdev = iobuf caps core
13
14o_src = hwstate mtstate memory mtouch gestures
15 11
16o_driver= multitouch 12o_driver= multitouch
17 13
18TARGETS += match/test
19TARGETS += mtdev/mapgen
20TARGETS += mtdev/test
21TARGETS += src/test 14TARGETS += src/test
22 15
23OBJECTS = $(addsuffix .o,\ 16OBJECTS = $(addsuffix .o,\
@@ -33,7 +26,7 @@ TOBJ = $(addprefix obj/,$(addsuffix .o,$(TARGETS)))
33TFDI = $(addprefix fdi/,$(FDIS)) 26TFDI = $(addprefix fdi/,$(FDIS))
34OBJS = $(addprefix obj/,$(OBJECTS)) 27OBJS = $(addprefix obj/,$(OBJECTS))
35XOBJS = $(addprefix obj/,$(XOBJECTS)) 28XOBJS = $(addprefix obj/,$(XOBJECTS))
36LIBS = -lm 29LIBS = -lmtdev -lm
37 30
38DLIB = usr/lib/xorg/modules/input 31DLIB = usr/lib/xorg/modules/input
39DFDI = usr/share/hal/fdi/policy/20thirdparty 32DFDI = usr/share/hal/fdi/policy/20thirdparty
@@ -52,7 +45,7 @@ bin/%: obj/%.o $(OBJS)
52 45
53$(TLIB): $(OBJS) $(XOBJS) 46$(TLIB): $(OBJS) $(XOBJS)
54 @rm -f $(TLIB) 47 @rm -f $(TLIB)
55 gcc -shared $(OBJS) $(XOBJS) -Wl,-soname -Wl,$(LIBRARY) -o $@ 48 gcc -shared $(OBJS) $(XOBJS) $(LIBS) -Wl,-soname -Wl,$(LIBRARY) -o $@
56 49
57obj/%.o: %.c 50obj/%.o: %.c
58 @mkdir -p $(@D) 51 @mkdir -p $(@D)
diff --git a/driver/multitouch.c b/driver/multitouch.c
index eef86c5..3ccc1c6 100644
--- a/driver/multitouch.c
+++ b/driver/multitouch.c
@@ -132,16 +132,16 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
132#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 132#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
133 axes_labels[0], 133 axes_labels[0],
134#endif 134#endif
135 mt->caps.abs[BIT_POSITION_X].minimum, 135 mt->caps.abs[MTDEV_POSITION_X].minimum,
136 mt->caps.abs[BIT_POSITION_X].maximum, 136 mt->caps.abs[MTDEV_POSITION_X].maximum,
137 1, 0, 1); 137 1, 0, 1);
138 xf86InitValuatorDefaults(dev, 0); 138 xf86InitValuatorDefaults(dev, 0);
139 xf86InitValuatorAxisStruct(dev, 1, 139 xf86InitValuatorAxisStruct(dev, 1,
140#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 140#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
141 axes_labels[1], 141 axes_labels[1],
142#endif 142#endif
143 mt->caps.abs[BIT_POSITION_Y].minimum, 143 mt->caps.abs[MTDEV_POSITION_Y].minimum,
144 mt->caps.abs[BIT_POSITION_Y].maximum, 144 mt->caps.abs[MTDEV_POSITION_Y].maximum,
145 1, 0, 1); 145 1, 0, 1);
146 xf86InitValuatorDefaults(dev, 1); 146 xf86InitValuatorDefaults(dev, 1);
147 147
diff --git a/include/abs2mt.h b/include/abs2mt.h
deleted file mode 100644
index 6021d8d..0000000
--- a/include/abs2mt.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/* generated by mapgen - do not edit */
2
3#ifndef ABS2MT_H
4#define ABS2MT_H
5
6#include "common.h"
7
8static const unsigned int map_abs2mt[ABS_CNT] = {
9 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
10 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
11 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
14 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
15 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
16 0x0009, 0x000a, 0x000b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
17};
18
19static const unsigned int map_mt2abs[MT_ABS_SIZE] = {
20 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
21 0x0038, 0x0039, 0x003a,
22};
23
24static inline int has_abs2mt(unsigned int code)
25{
26 return map_abs2mt[code];
27}
28
29static inline unsigned int abs2mt(unsigned int code)
30{
31 return map_abs2mt[code] - 1;
32}
33
34static inline unsigned int mt2abs(unsigned int mtcode)
35{
36 return map_mt2abs[mtcode];
37}
38
39#endif
diff --git a/include/mtdev-caps.h b/include/capabilities.h
index 727cd11..0dfc73b 100644
--- a/include/mtdev-caps.h
+++ b/include/capabilities.h
@@ -19,20 +19,18 @@
19 * 19 *
20 **************************************************************************/ 20 **************************************************************************/
21 21
22#ifndef MTDEV_CAPS_H 22#ifndef CAPABILITIES_H
23#define MTDEV_CAPS_H 23#define CAPABILITIES_H
24 24
25#include "common.h" 25#include "common.h"
26#include "button.h" 26#include "button.h"
27#include "abs2mt.h"
28#include "mtbit.h"
29 27
30struct Capabilities { 28struct Capabilities {
31 struct input_id devid; 29 struct input_id devid;
32 char devname[32]; 30 char devname[32];
33 int has_left, has_middle, has_right; 31 int has_left, has_middle, has_right;
34 int has_mtdata, has_ibt; 32 int has_mtdata, has_ibt;
35 int has_slot, nullid; 33 int has_slot;
36 int has_abs[MT_ABS_SIZE]; 34 int has_abs[MT_ABS_SIZE];
37 struct input_absinfo slot; 35 struct input_absinfo slot;
38 struct input_absinfo abs[MT_ABS_SIZE]; 36 struct input_absinfo abs[MT_ABS_SIZE];
diff --git a/include/common.h b/include/common.h
index e13088f..6d00d6e 100644
--- a/include/common.h
+++ b/include/common.h
@@ -26,59 +26,12 @@
26#include <xf86.h> 26#include <xf86.h>
27#include <xf86_OSproc.h> 27#include <xf86_OSproc.h>
28#include <xf86Xinput.h> 28#include <xf86Xinput.h>
29#include <linux/input.h>
30#include <errno.h> 29#include <errno.h>
31 30#include <mtdev-mapping.h>
32/* includes available in 2.6.30-rc5 */
33
34#ifndef BTN_TOOL_QUADTAP
35#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
36#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
37#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
38#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
39#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
40#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
41#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
42#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
43#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
44#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
45#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
46#define SYN_MT_REPORT 2
47#define MT_TOOL_FINGER 0
48#define MT_TOOL_PEN 1
49#endif
50
51/* includes available in 2.6.33 */
52#ifndef ABS_MT_PRESSURE
53#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
54#endif
55
56/* includes available in 2.6.36 */
57#ifndef ABS_MT_SLOT
58#define ABS_MT_SLOT 0x2f /* MT slot being modified */
59#define MT_SLOT_ABS_EVENTS { \
60 ABS_MT_TOUCH_MAJOR, \
61 ABS_MT_TOUCH_MINOR, \
62 ABS_MT_WIDTH_MAJOR, \
63 ABS_MT_WIDTH_MINOR, \
64 ABS_MT_ORIENTATION, \
65 ABS_MT_POSITION_X, \
66 ABS_MT_POSITION_Y, \
67 ABS_MT_TOOL_TYPE, \
68 ABS_MT_BLOB_ID, \
69 ABS_MT_TRACKING_ID, \
70 ABS_MT_PRESSURE, \
71}
72#endif
73
74#define MT_ABS_SIZE 11 /* Size of MT_SLOT_ABS_EVENTS */
75 31
76#define DIM_FINGER 32 32#define DIM_FINGER 32
77#define DIM2_FINGER (DIM_FINGER * DIM_FINGER) 33#define DIM2_FINGER (DIM_FINGER * DIM_FINGER)
78 34
79/* event buffer size (must be a power of two) */
80#define DIM_EVENTS 512
81
82/* year-proof millisecond event time */ 35/* year-proof millisecond event time */
83typedef __u64 mstime_t; 36typedef __u64 mstime_t;
84 37
diff --git a/include/hwstate.h b/include/hwstate.h
index efd291f..4c59a1e 100644
--- a/include/hwstate.h
+++ b/include/hwstate.h
@@ -22,7 +22,7 @@
22#ifndef HWSTATE_H 22#ifndef HWSTATE_H
23#define HWSTATE_H 23#define HWSTATE_H
24 24
25#include "mtdev.h" 25#include "capabilities.h"
26 26
27struct FingerState { 27struct FingerState {
28 int touch_major, touch_minor; 28 int touch_major, touch_minor;
@@ -42,8 +42,8 @@ struct HWState {
42 42
43void init_hwstate(struct HWState *s, 43void init_hwstate(struct HWState *s,
44 const struct Capabilities *caps); 44 const struct Capabilities *caps);
45int hwstate_read(struct HWState *s, const struct Capabilities *caps, 45int modify_hwstate(struct HWState *s, struct mtdev *dev, int fd,
46 const struct input_event *ev); 46 const struct Capabilities *caps);
47void output_hwstate(const struct HWState *s); 47void output_hwstate(const struct HWState *s);
48 48
49static inline int finger_dist2(const struct FingerState *a, 49static inline int finger_dist2(const struct FingerState *a,
diff --git a/include/match.h b/include/match.h
deleted file mode 100644
index 25842fc..0000000
--- a/include/match.h
+++ /dev/null
@@ -1,36 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#ifndef MATCHER_H
23#define MATCHER_H
24
25/**
26 * Special implementation of the hungarian algorithm.
27 * The maximum number of fingers matches a uint32.
28 * Bitmasks are used extensively.
29 */
30
31#include "common.h"
32
33void match_fingers(int index[DIM_FINGER], int A[DIM2_FINGER],
34 int nrow, int ncol);
35
36#endif
diff --git a/include/mtbit.h b/include/mtbit.h
deleted file mode 100644
index 2c4dacb..0000000
--- a/include/mtbit.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* generated by mapgen - do not edit */
2
3#ifndef MTBIT_H
4#define MTBIT_H
5
6#define BIT_TRACKING_ID 9
7#define BIT_POSITION_X 5
8#define BIT_POSITION_Y 6
9#define BIT_TOUCH_MAJOR 0
10#define BIT_TOUCH_MINOR 1
11#define BIT_WIDTH_MAJOR 2
12#define BIT_WIDTH_MINOR 3
13
14#endif
diff --git a/include/mtdev-evbuf.h b/include/mtdev-evbuf.h
deleted file mode 100644
index 77fec41..0000000
--- a/include/mtdev-evbuf.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#ifndef MTDEV_EVBUF_H
23#define MTDEV_EVBUF_H
24
25#include "common.h"
26
27struct EventBuffer {
28 int head;
29 int tail;
30 struct input_event buffer[DIM_EVENTS];
31};
32
33static inline void evbuf_init(struct EventBuffer *evbuf)
34{
35 memset(evbuf, 0, sizeof(*evbuf));
36}
37
38static inline int evbuf_empty(const struct EventBuffer *evbuf)
39{
40 return evbuf->head == evbuf->tail;
41}
42
43static inline void evbuf_put(struct EventBuffer *evbuf,
44 const struct input_event *ev)
45{
46 evbuf->buffer[evbuf->head++] = *ev;
47 evbuf->head &= DIM_EVENTS - 1;
48}
49
50static inline void evbuf_get(struct EventBuffer *evbuf,
51 struct input_event *ev)
52{
53 *ev = evbuf->buffer[evbuf->tail++];
54 evbuf->tail &= DIM_EVENTS - 1;
55}
56
57#endif
diff --git a/include/mtdev-iobuf.h b/include/mtdev-iobuf.h
deleted file mode 100644
index 7d4265c..0000000
--- a/include/mtdev-iobuf.h
+++ /dev/null
@@ -1,38 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#ifndef MTDEV_IOBUF_H
23#define MTDEV_IOBUF_H
24
25#include "common.h"
26
27#define EVENT_SIZE sizeof(struct input_event)
28#define DIM_BUFFER (DIM_EVENTS * EVENT_SIZE)
29
30struct IOBuffer {
31 char begin[DIM_BUFFER], *at, *top, *end;
32};
33
34void init_iobuf(struct IOBuffer *buf);
35const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd);
36int poll_iobuf(struct IOBuffer *buf, int fd, int ms);
37
38#endif
diff --git a/include/mtdev.h b/include/mtdev.h
deleted file mode 100644
index 936d597..0000000
--- a/include/mtdev.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#ifndef MTDEV_H
23#define MTDEV_H
24
25#include "mtdev-caps.h"
26#include "mtdev-evbuf.h"
27
28/**
29 * struct MTDev - represents an input MT device
30 * @inbuf: input event buffer
31 * @outbuf: output event buffer
32 * @priv: structure of private data
33 */
34struct MTDev {
35 struct EventBuffer inbuf;
36 struct EventBuffer outbuf;
37 struct MTDevState *priv;
38};
39
40int mtdev_init(struct MTDev *mtdev, const struct Capabilities *caps);
41
42static inline int mtdev_empty(struct MTDev *mtdev)
43{
44 return evbuf_empty(&mtdev->outbuf);
45}
46
47void mtdev_put(struct MTDev *dev, const struct Capabilities *caps,
48 const struct input_event *ev);
49
50static inline void mtdev_get(struct MTDev *mtdev, struct input_event* ev)
51{
52 evbuf_get(&mtdev->outbuf, ev);
53}
54
55void mtdev_destroy(struct MTDev *mtdev);
56
57#endif
diff --git a/include/mtouch.h b/include/mtouch.h
index 482d010..aedb02c 100644
--- a/include/mtouch.h
+++ b/include/mtouch.h
@@ -23,12 +23,10 @@
23#define MTOUCH_H 23#define MTOUCH_H
24 24
25#include "memory.h" 25#include "memory.h"
26#include "mtdev-iobuf.h"
27 26
28struct MTouch { 27struct MTouch {
29 struct Capabilities caps; 28 struct Capabilities caps;
30 struct MTDev dev; 29 struct mtdev dev;
31 struct IOBuffer buf;
32 struct HWState hs; 30 struct HWState hs;
33 struct MTState prev_state, state; 31 struct MTState prev_state, state;
34 struct Memory mem; 32 struct Memory mem;
@@ -36,10 +34,9 @@ struct MTouch {
36 34
37int configure_mtouch(struct MTouch *mt, int fd); 35int configure_mtouch(struct MTouch *mt, int fd);
38int open_mtouch(struct MTouch *mt, int fd); 36int open_mtouch(struct MTouch *mt, int fd);
39int get_mtouch(struct MTouch *mt, int fd, struct input_event* ev, int ev_max);
40int close_mtouch(struct MTouch *mt, int fd); 37int close_mtouch(struct MTouch *mt, int fd);
41 38
42int parse_event(struct MTouch *mt, const struct input_event *ev); 39int read_packet(struct MTouch *mt, int fd);
43 40
44int has_delayed_gestures(struct MTouch *mt, int fd); 41int has_delayed_gestures(struct MTouch *mt, int fd);
45 42
diff --git a/match/match.c b/match/match.c
deleted file mode 100644
index 4cb4495..0000000
--- a/match/match.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include "match.h"
23#include <string.h>
24#include <stdio.h>
25
26/**
27 * Bitmap implementation of the hungarian algorithm (GPL license)
28 *
29 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
30 *
31 * Based on code released by Markus Buehren (2004) (BSD license)
32 *
33 * Copyright (C) 2004, Markus Buehren. All rights reserved.
34 * See CREDITS file for full license terms.
35 *
36 */
37
38typedef unsigned col_t[1];
39typedef unsigned mat_t[DIM_FINGER];
40
41#define GET1(m, x) ((m[0] >> (x)) & 1U)
42#define SET1(m, x) (m[0] |= (1U << (x)))
43#define CLEAR1(m, x) (m[0] &= ~(1U << (x)))
44
45#define GET2(m, row, col) ((m[col] >> (row)) & 1U)
46#define SET2(m, row, col) (m[col] |= (1U << (row)))
47#define CLEAR2(m, row, col) (m[col] &= ~(1U << (row)))
48
49/********************************************************/
50
51static void buildixvector(int *ix, mat_t mstar, int nrows, int ncols)
52{
53 int row, col;
54 for (row = 0; row < nrows; row++) {
55 for (col = 0; col < ncols; col++) {
56 if (GET2(mstar, row, col)) {
57 ix[row] = col;
58 break;
59 }
60 }
61 }
62}
63
64
65/********************************************************/
66
67static void step2a(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
68 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
69 int dmin);
70static void step2b(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
71 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
72 int dmin);
73static void step3(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
74 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
75 int dmin);
76static void step4(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
77 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
78 int dmin, int row, int col);
79static void step5(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
80 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
81 int dmin);
82
83static void ixoptimal(int *ix, int *mdist, int nrows, int ncols)
84{
85 int *mdistTemp, *mdistEnd, *columnEnd, value, minValue;
86 int dmin, row, col;
87 col_t ccol, crow;
88 mat_t mstar, mprime, nmstar;
89
90 memset(ccol, 0, sizeof(col_t));
91 memset(crow, 0, sizeof(col_t));
92 memset(mstar, 0, sizeof(mat_t));
93 memset(mprime, 0, sizeof(mat_t));
94 memset(nmstar, 0, sizeof(mat_t));
95
96 /* initialization */
97 for (row = 0; row < nrows; row++)
98 ix[row] = -1;
99
100 mdistEnd = mdist + nrows * ncols;
101
102 /* preliminary steps */
103 if (nrows <= ncols) {
104 dmin = nrows;
105
106 for (row = 0; row < nrows; row++) {
107 /* find the smallest element in the row */
108 mdistTemp = mdist + row;
109 minValue = *mdistTemp;
110 mdistTemp += nrows;
111 while (mdistTemp < mdistEnd) {
112 value = *mdistTemp;
113 if (value < minValue)
114 minValue = value;
115 mdistTemp += nrows;
116 }
117
118 /* subtract the smallest element from each element
119 of the row */
120 mdistTemp = mdist + row;
121 while (mdistTemp < mdistEnd) {
122 *mdistTemp -= minValue;
123 mdistTemp += nrows;
124 }
125 }
126
127 /* Steps 1 and 2a */
128 for (row = 0; row < nrows; row++) {
129 for (col = 0; col < ncols; col++) {
130 if (mdist[row + nrows * col] != 0)
131 continue;
132 if (GET1(ccol, col))
133 continue;
134 SET2(mstar, row, col);
135 SET1(ccol, col);
136 break;
137 }
138 }
139 } else {
140 dmin = ncols;
141
142 for (col = 0; col < ncols; col++) {
143 /* find the smallest element in the column */
144 mdistTemp = mdist + nrows*col;
145 columnEnd = mdistTemp + nrows;
146
147 minValue = *mdistTemp++;
148 while (mdistTemp < columnEnd) {
149 value = *mdistTemp++;
150 if (value < minValue)
151 minValue = value;
152 }
153
154 /* subtract the smallest element from each element
155 of the column */
156 mdistTemp = mdist + nrows*col;
157 while (mdistTemp < columnEnd)
158 *mdistTemp++ -= minValue;
159 }
160
161 /* Steps 1 and 2a */
162 for (col = 0; col < ncols; col++) {
163 for (row = 0; row < nrows; row++) {
164 if (mdist[row + nrows * col] != 0)
165 continue;
166 if (GET1(crow, row))
167 continue;
168 SET2(mstar, row, col);
169 SET1(ccol, col);
170 SET1(crow, row);
171 break;
172 }
173 }
174 memset(crow, 0, sizeof(col_t));
175 }
176
177 /* move to step 2b */
178 step2b(ix, mdist, mstar, nmstar,
179 mprime, ccol, crow, nrows, ncols,
180 dmin);
181}
182
183/********************************************************/
184static void step2a(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
185 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
186 int dmin)
187{
188 int col, row;
189
190 /* cover every column containing a starred zero */
191 for (col = 0; col < ncols; col++) {
192 for (row = 0; row < nrows; row++) {
193 if (!GET2(mstar, row, col))
194 continue;
195 SET1(ccol, col);
196 break;
197 }
198 }
199
200 /* move to step 3 */
201 step2b(ix, mdist, mstar, nmstar,
202 mprime, ccol, crow, nrows, ncols,
203 dmin);
204}
205
206/********************************************************/
207static void step2b(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
208 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
209 int dmin)
210{
211 int col, ncc;
212
213 /* count covered columns */
214 ncc = 0;
215 for (col = 0; col < ncols; col++)
216 if (GET1(ccol, col))
217 ncc++;
218
219 if (ncc == dmin) {
220 /* algorithm finished */
221 buildixvector(ix, mstar, nrows, ncols);
222 } else {
223 /* move to step 3 */
224 step3(ix, mdist, mstar, nmstar,
225 mprime, ccol, crow, nrows, ncols,
226 dmin);
227 }
228
229}
230
231/********************************************************/
232static void step3(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
233 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
234 int dmin)
235{
236 int zerosFound;
237 int row, col, cstar;
238
239 zerosFound = 1;
240 while (zerosFound) {
241 zerosFound = 0;
242 for (col = 0; col < ncols; col++) {
243 if (GET1(ccol, col))
244 continue;
245 for (row = 0; row < nrows; row++) {
246 if (mdist[row + nrows * col] != 0)
247 continue;
248 if (GET1(crow, row))
249 continue;
250
251 /* prime zero */
252 SET2(mprime, row, col);
253
254 /* find starred zero in current row */
255 for (cstar = 0; cstar < ncols; cstar++)
256 if (GET2(mstar, row, cstar))
257 break;
258
259 if (cstar == ncols) { /* no starred zero */
260 /* move to step 4 */
261 step4(ix, mdist, mstar, nmstar,
262 mprime, ccol, crow, nrows, ncols,
263 dmin, row, col);
264 return;
265 } else {
266 SET1(crow, row);
267 CLEAR1(ccol, cstar);
268 zerosFound = 1;
269 break;
270 }
271 }
272 }
273 }
274
275 /* move to step 5 */
276 step5(ix, mdist, mstar, nmstar,
277 mprime, ccol, crow, nrows, ncols,
278 dmin);
279}
280
281/********************************************************/
282static void step4(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
283 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
284 int dmin, int row, int col)
285{
286 int n, rstar, cstar, primeRow, primeCol;
287
288 /* generate temporary copy of mstar */
289 memcpy(nmstar, mstar, sizeof(mat_t));
290
291 /* star current zero */
292 SET2(nmstar, row, col);
293
294 /* find starred zero in current column */
295 cstar = col;
296 for (rstar = 0; rstar < nrows; rstar++)
297 if (GET2(mstar, rstar, cstar))
298 break;
299
300 while (rstar < nrows) {
301 /* unstar the starred zero */
302 CLEAR2(nmstar, rstar, cstar);
303
304 /* find primed zero in current row */
305 primeRow = rstar;
306 for (primeCol = 0; primeCol < ncols; primeCol++)
307 if (GET2(mprime, primeRow, primeCol))
308 break;
309
310 /* star the primed zero */
311 SET2(nmstar, primeRow, primeCol);
312
313 /* find starred zero in current column */
314 cstar = primeCol;
315 for (rstar = 0; rstar < nrows; rstar++)
316 if (GET2(mstar, rstar, cstar))
317 break;
318 }
319
320 /* use temporary copy as new mstar */
321 /* delete all primes, uncover all rows */
322 memcpy(mstar, nmstar, sizeof(mat_t));
323 memset(mprime, 0, sizeof(mat_t));
324 memset(crow, 0, sizeof(col_t));
325
326 /* move to step 2a */
327 step2a(ix, mdist, mstar, nmstar,
328 mprime, ccol, crow, nrows, ncols,
329 dmin);
330}
331
332/********************************************************/
333static void step5(int *ix, int *mdist, mat_t mstar, mat_t nmstar,
334 mat_t mprime, col_t ccol, col_t crow, int nrows, int ncols,
335 int dmin)
336{
337 int h = 0, value;
338 int row, col, found = 0;
339
340 /* find smallest uncovered element h */
341 for (row = 0; row < nrows; row++) {
342 if (GET1(crow, row))
343 continue;
344 for (col = 0; col < ncols; col++) {
345 if (GET1(ccol, col))
346 continue;
347 value = mdist[row + nrows * col];
348 if (!found || value < h) {
349 h = value;
350 found = 1;
351 }
352 }
353 }
354
355 /* where to go if nothing uncovered? */
356 if (!found)
357 return;
358
359 /* add h to each covered row */
360 for (row = 0; row < nrows; row++) {
361 if (!GET1(crow, row))
362 continue;
363 for (col = 0; col < ncols; col++)
364 mdist[row + nrows * col] += h;
365 }
366
367 /* subtract h from each uncovered column */
368 for (col = 0; col < ncols; col++) {
369 if (GET1(ccol, col))
370 continue;
371 for (row = 0; row < nrows; row++)
372 mdist[row + nrows * col] -= h;
373 }
374
375 /* move to step 3 */
376 step3(ix, mdist, mstar, nmstar,
377 mprime, ccol, crow, nrows, ncols,
378 dmin);
379}
380
381void match_fingers(int ix[DIM_FINGER], int A[DIM2_FINGER], int nrow, int ncol)
382{
383 ixoptimal(ix, A, nrow, ncol);
384}
385
diff --git a/match/test.c b/match/test.c
deleted file mode 100644
index dabc083..0000000
--- a/match/test.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include <match.h>
23#include <xbypass.h>
24#include <stdio.h>
25#include <time.h>
26
27#define ITS 1000000
28
29static void test1()
30{
31 int A[] = {
32 1013,
33 3030660,
34 3559354,
35 12505925,
36 19008450,
37 6946421,
38 6118613,
39 698020,
40 3021800,
41 1017,
42 37573,
43 3242018,
44 8152794,
45 1266053,
46 942941,
47 462820,
48 };
49 int index[DIM_FINGER], i;
50 match_fingers(index, A, 4, 4);
51 for (i = 0; i < 4; i++)
52 printf("match[%d] = %d\n", i, index[i]);
53}
54
55static void test2()
56{
57 int A[] = {
58 0,
59 4534330,
60 22653552,
61 12252500,
62 685352,
63 4534330,
64 0,
65 9619317,
66 28409530,
67 6710170,
68 22653552,
69 9619317,
70 0,
71 47015292,
72 29788572,
73 2809040,
74 10428866,
75 38615920,
76 17732500,
77 719528,
78 12113945,
79 28196220,
80 46778656,
81 405,
82 14175493,
83 };
84 int index[DIM_FINGER], i;
85 match_fingers(index, A, 5, 5);
86 for (i = 0; i < 5; i++)
87 printf("match[%d] = %d\n", i, index[i]);
88}
89
90static void speed1()
91{
92 /* column-by-column matrix */
93 int A[DIM2_FINGER];
94 int x1[DIM_FINGER] = { 1, 5, 2, 3, 4, 5, 6, 7, 8 };
95 int y1[DIM_FINGER] = { 1, 5, 2, 3, 4, 6, 6, 7, 8 };
96 int x2[DIM_FINGER] = { 1.1, 3, 2, 4, 5, 6, 7, 8 };
97 int y2[DIM_FINGER] = { 1, 3, 2, 4, 5, 6, 7, 8 };
98 int index[DIM_FINGER];
99 int n1 = 4;
100 int n2 = 7;
101
102 int i, j;
103
104 for (i = 0; i < n1; i++) {
105 for (j = 0; j < n2; j++) {
106 A[i + n1 * j] =
107 (x1[i] - x2[j]) * (x1[i] - x2[j]) +
108 (y1[i] - y2[j]) * (y1[i] - y2[j]);
109 }
110 }
111
112 clock_t t1 = clock();
113 for (i = 0; i < ITS; i++)
114 match_fingers(index, A, n1, n2);
115 clock_t t2 = clock();
116
117 printf("%lf matches per second\n",
118 ITS * ((float)CLOCKS_PER_SEC / (t2 - t1)));
119
120 for (i = 0; i < n1; i++)
121 printf("match[%d] = %d\n", i, index[i]);
122
123}
124
125int main(int argc, char *argv[])
126{
127 printf("test1\n");
128 test1();
129 printf("test2\n");
130 test2();
131 printf("speed1\n");
132 speed1();
133 printf("done\n");
134 return 0;
135}
diff --git a/mtdev/core.c b/mtdev/core.c
deleted file mode 100644
index f13da13..0000000
--- a/mtdev/core.c
+++ /dev/null
@@ -1,402 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include "mtdev.h"
23#include "mtbit.h"
24
25/**
26 * struct MTSlot - represents the state of an input MT slot
27 * @abs: current values of ABS_MT axes for this slot
28 */
29struct MTSlot {
30 int abs[MT_ABS_SIZE];
31};
32
33/**
34 * struct MTDevState - MT slot parsing
35 * @data: array of scratch slot data
36 * @used: bitmask of currently used slots
37 * @slot: slot currently being modified
38 * @lastid: last used tracking id
39 */
40struct MTDevState {
41 struct MTSlot data[DIM_FINGER];
42 bitmask_t used;
43 bitmask_t slot;
44 bitmask_t lastid;
45};
46
47/**
48 * mtdev_init - init MT device
49 * @dev: device to initialize
50 * @caps: device capabilities
51 */
52int mtdev_init(struct MTDev *dev, const struct Capabilities *caps)
53{
54 memset(dev, 0, sizeof(struct MTDev));
55 if (!caps->has_mtdata)
56 return -ENODEV;
57 if (!caps->has_slot) {
58 dev->priv = calloc(1, sizeof(struct MTDevState));
59 if (!dev->priv)
60 return -ENOMEM;
61 }
62 return 0;
63}
64
65static inline int istouch(const struct MTSlot *data,
66 const struct Capabilities *caps)
67{
68 return data->abs[BIT_TOUCH_MAJOR] || !caps->has_abs[BIT_TOUCH_MAJOR];
69}
70
71/* Dmitry Torokhov's code from kernel/driver/input/input.c */
72static int defuzz(int value, int old_val, int fuzz)
73{
74 if (fuzz) {
75 if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
76 return old_val;
77
78 if (value > old_val - fuzz && value < old_val + fuzz)
79 return (old_val * 3 + value) / 4;
80
81 if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
82 return (old_val + value) / 2;
83 }
84
85 return value;
86}
87
88/*
89 * solve - solve contact matching problem
90 * @priv: parsing state
91 * @caps: device capabilities
92 * @sid: array of current tracking ids
93 * @sx: array of current position x
94 * @sy: array of current position y
95 * @sn: number of current contacts
96 * @nid: array of new or matched tracking ids, to be filled
97 * @nx: array of new position x
98 * @ny: array of new position y
99 * @nn: number of new contacts
100 * @touch: which of the new contacts to fill
101 */
102static void solve(struct MTDevState *priv, const struct Capabilities *caps,
103 const int *sid, const int *sx, const int *sy, int sn,
104 int *nid, const int *nx, const int *ny, int nn,
105 bitmask_t touch)
106{
107 int A[DIM2_FINGER], *row;
108 int n2s[DIM_FINGER];
109 int id, i, j;
110
111 /* setup distance matrix for contact matching */
112 for (j = 0; j < sn; j++) {
113 row = A + nn * j;
114 for (i = 0; i < nn; i++)
115 row[i] = dist2(nx[i] - sx[j], ny[i] - sy[j]);
116 }
117
118 match_fingers(n2s, A, nn, sn);
119
120 /* update matched contacts and create new ones */
121 foreach_bit(i, touch) {
122 j = n2s[i];
123 id = j >= 0 ? sid[j] : caps->nullid;
124 while (id == caps->nullid)
125 id = ++priv->lastid;
126 nid[i] = id;
127 }
128}
129
130/*
131 * assign_tracking_id - assign tracking ids to all contacts
132 * @priv: parsing state
133 * @caps: device capabilities
134 * @data: array of all present contacts, to be filled
135 * @prop: array of all set contacts properties
136 * @size: number of contacts in array
137 * @touch: which of the contacts are actual touches
138 */
139static void assign_tracking_id(struct MTDevState *priv,
140 const struct Capabilities *caps,
141 struct MTSlot *data, bitmask_t *prop,
142 int size, bitmask_t touch)
143{
144 int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0;
145 int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i;
146 foreach_bit(i, priv->used) {
147 sid[sn] = priv->data[i].abs[BIT_TRACKING_ID];
148 sx[sn] = priv->data[i].abs[BIT_POSITION_X];
149 sy[sn] = priv->data[i].abs[BIT_POSITION_Y];
150 sn++;
151 }
152 for (i = 0; i < size; i++) {
153 nx[i] = data[i].abs[BIT_POSITION_X];
154 ny[i] = data[i].abs[BIT_POSITION_Y];
155 }
156 solve(priv, caps, sid, sx, sy, sn, nid, nx, ny, size, touch);
157 for (i = 0; i < size; i++) {
158 data[i].abs[BIT_TRACKING_ID] =
159 GETBIT(touch, i) ? nid[i] : caps->nullid;
160 prop[i] |= BITMASK(BIT_TRACKING_ID);
161 }
162}
163
164/*
165 * process_typeA - consume MT events and update parsing state
166 * @dev: MT device
167 * @data: array of all present contacts, to be filled
168 * @prop: array of all set contacts properties, to be filled
169 *
170 * This function is called when a SYN_REPORT is seen, right before
171 * that event is pushed to the queue.
172 *
173 * Returns -1 if the packet is not MT related and should not affect
174 * the current parsing state.
175 */
176static int process_typeA(struct MTDev *dev,
177 struct MTSlot *data, bitmask_t *prop)
178{
179 struct input_event ev;
180 int consumed, mtcode;
181 int mtcnt = 0, size = 0;
182 prop[size] = 0;
183 while (!evbuf_empty(&dev->inbuf)) {
184 evbuf_get(&dev->inbuf, &ev);
185 consumed = 0;
186 switch (ev.type) {
187 case EV_SYN:
188 switch (ev.code) {
189 case SYN_MT_REPORT:
190 if (size < DIM_FINGER &&
191 GETBIT(prop[size], BIT_POSITION_X) &&
192 GETBIT(prop[size], BIT_POSITION_Y))
193 size++;
194 if (size < DIM_FINGER)
195 prop[size] = 0;
196 mtcnt++;
197 consumed = 1;
198 break;
199 }
200 break;
201 case EV_KEY:
202 switch (ev.code) {
203 case BTN_TOUCH:
204 mtcnt++;
205 break;
206 }
207 break;
208 case EV_ABS:
209 if (size < DIM_FINGER && has_abs2mt(ev.code)) {
210 mtcode = abs2mt(ev.code);
211 data[size].abs[mtcode] = ev.value;
212 prop[size] |= BITMASK(mtcode);
213 mtcnt++;
214 consumed = 1;
215 }
216 break;
217 }
218 if (!consumed)
219 evbuf_put(&dev->outbuf, &ev);
220 }
221 return mtcnt ? size : -1;
222}
223
224/*
225 * process_typeB - propagate events without parsing
226 * @dev: MT device
227 *
228 * This function is called when a SYN_REPORT is seen, right before
229 * that event is pushed to the queue.
230 */
231static void process_typeB(struct MTDev *dev)
232{
233 struct input_event ev;
234 while (!evbuf_empty(&dev->inbuf)) {
235 evbuf_get(&dev->inbuf, &ev);
236 evbuf_put(&dev->outbuf, &ev);
237 }
238}
239
240/*
241 * filter_data - apply input filtering on new incoming data
242 * @priv: parsing state
243 * @caps: device capabilities
244 * @data: the incoming data to filter
245 * @prop: the properties to filter
246 * @slot: the slot the data refers to
247 */
248static void filter_data(const struct MTDevState *priv,
249 const struct Capabilities *caps,
250 struct MTSlot *data, bitmask_t prop,
251 int slot)
252{
253 int i;
254 foreach_bit(i, prop) {
255 int fuzz = caps->abs[i].fuzz;
256 int oldval = priv->data[slot].abs[i];
257 data->abs[i] = defuzz(data->abs[i], oldval, fuzz);
258 }
259}
260
261/*
262 * push_slot_changes - propagate state changes
263 * @dev: MT device
264 * @data: the incoming data to propagate
265 * @prop: the properties to propagate
266 * @slot: the slot the data refers to
267 * @syn: reference to the SYN_REPORT event
268 */
269static void push_slot_changes(struct MTDev *dev,
270 const struct MTSlot *data, bitmask_t prop,
271 int slot, const struct input_event *syn)
272{
273 struct MTDevState *priv = dev->priv;
274 struct input_event ev;
275 int i, count = 0;
276 foreach_bit(i, prop)
277 if (priv->data[slot].abs[i] != data->abs[i])
278 count++;
279 if (!count)
280 return;
281 ev.time = syn->time;
282 ev.type = EV_ABS;
283 ev.code = ABS_MT_SLOT;
284 ev.value = slot;
285 if (priv->slot != ev.value) {
286 evbuf_put(&dev->outbuf, &ev);
287 priv->slot = ev.value;
288 }
289 foreach_bit(i, prop) {
290 ev.code = mt2abs(i);
291 ev.value = data->abs[i];
292 if (priv->data[slot].abs[i] != ev.value) {
293 evbuf_put(&dev->outbuf, &ev);
294 priv->data[slot].abs[i] = ev.value;
295 }
296 }
297}
298
299/*
300 * apply_typeA_changes - parse and propagate state changes
301 * @dev: MT device
302 * @caps: device capabilities
303 * @data: array of data to apply
304 * @prop: array of properties to apply
305 * @size: number of contacts in array
306 * @syn: reference to the SYN_REPORT event
307 */
308static void apply_typeA_changes(struct MTDev *dev,
309 const struct Capabilities *caps,
310 struct MTSlot *data, const bitmask_t *prop,
311 int size, const struct input_event *syn)
312{
313 struct MTDevState *priv = dev->priv;
314 bitmask_t unused = ~priv->used;
315 bitmask_t used = 0;
316 int i, slot, id;
317 for (i = 0; i < size; i++) {
318 id = data[i].abs[BIT_TRACKING_ID];
319 foreach_bit(slot, priv->used) {
320 if (priv->data[slot].abs[BIT_TRACKING_ID] != id)
321 continue;
322 filter_data(priv, caps, &data[i], prop[i], slot);
323 push_slot_changes(dev, &data[i], prop[i], slot, syn);
324 SETBIT(used, slot);
325 id = caps->nullid;
326 break;
327 }
328 if (id != caps->nullid) {
329 slot = firstbit(unused);
330 push_slot_changes(dev, &data[i], prop[i], slot, syn);
331 SETBIT(used, slot);
332 CLEARBIT(unused, slot);
333 }
334 }
335
336 /* clear unused slots and update slot usage */
337 foreach_bit(slot, priv->used & ~used) {
338 struct MTSlot tdata = priv->data[slot];
339 bitmask_t tprop = BITMASK(BIT_TRACKING_ID);
340 tdata.abs[BIT_TRACKING_ID] = caps->nullid;
341 push_slot_changes(dev, &tdata, tprop, slot, syn);
342 }
343 priv->used = used;
344}
345
346/*
347 * convert_A_to_B - propagate a type A packet as a type B packet
348 * @dev: MT device
349 * @caps: device capabilities
350 * @syn: reference to the SYN_REPORT event
351 */
352static void convert_A_to_B(struct MTDev *dev,
353 const struct Capabilities *caps,
354 const struct input_event *syn)
355{
356 struct MTSlot data[DIM_FINGER];
357 bitmask_t prop[DIM_FINGER];
358 int size = process_typeA(dev, data, prop);
359 if (size < 0)
360 return;
361 if (!caps->has_abs[BIT_TRACKING_ID]) {
362 bitmask_t touch = 0;
363 int i;
364 for (i = 0; i < size; i++)
365 MODBIT(touch, i, istouch(&data[i], caps));
366 assign_tracking_id(dev->priv, caps, data, prop, size, touch);
367 }
368 apply_typeA_changes(dev, caps, data, prop, size, syn);
369}
370
371/**
372 * mtdev_put - insert event into MT device
373 * @dev: MT device
374 * @caps: device capabilities
375 * @syn: reference to the SYN_REPORT event
376 */
377void mtdev_put(struct MTDev *dev,
378 const struct Capabilities *caps,
379 const struct input_event *ev)
380{
381 if (ev->type == EV_SYN && ev->code == SYN_REPORT) {
382 bitmask_t head = dev->outbuf.head;
383 if (dev->priv)
384 convert_A_to_B(dev, caps, ev);
385 else
386 process_typeB(dev);
387 if (dev->outbuf.head != head)
388 evbuf_put(&dev->outbuf, ev);
389 } else {
390 evbuf_put(&dev->inbuf, ev);
391 }
392}
393
394/**
395 * mtdev_destroy - destroy MT device
396 * @dev: MT device
397 */
398void mtdev_destroy(struct MTDev *dev)
399{
400 free(dev->priv);
401 memset(dev, 0, sizeof(struct MTDev));
402}
diff --git a/mtdev/iobuf.c b/mtdev/iobuf.c
deleted file mode 100644
index 65c33f6..0000000
--- a/mtdev/iobuf.c
+++ /dev/null
@@ -1,63 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include <mtdev-iobuf.h>
23#include <sys/poll.h>
24
25void init_iobuf(struct IOBuffer *buf)
26{
27 memset(buf, 0, sizeof(struct IOBuffer));
28 buf->at = buf->begin;
29 buf->top = buf->at;
30 buf->end = buf->begin + DIM_BUFFER;
31}
32
33const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd)
34{
35 const struct input_event *ev;
36 int n = buf->top - buf->at;
37 if (n < EVENT_SIZE) {
38 /* partial event is available: save it */
39 if (buf->at != buf->begin && n > 0)
40 memmove(buf->begin, buf->at, n);
41 /* start from the beginning */
42 buf->at = buf->begin;
43 buf->top = buf->at + n;
44 /* read more data */
45 SYSCALL(n = read(fd, buf->top, buf->end - buf->top));
46 if (n <= 0)
47 return NULL;
48 buf->top += n;
49 }
50 if (buf->top - buf->at < EVENT_SIZE)
51 return NULL;
52 ev = (const struct input_event *)buf->at;
53 buf->at += EVENT_SIZE;
54 return ev;
55}
56
57int poll_iobuf(struct IOBuffer *buf, int fd, int ms)
58{
59 struct pollfd fds = { fd, POLLIN, 0 };
60 if (buf->top != buf->at)
61 return 1;
62 return poll(&fds, 1, ms);
63}
diff --git a/mtdev/mapgen.c b/mtdev/mapgen.c
deleted file mode 100644
index efb3524..0000000
--- a/mtdev/mapgen.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include <common.h>
23#include <fcntl.h>
24#include <xbypass.h>
25
26#define BIT_DEF(name) \
27 printf("#define BIT_"#name" %d\n", \
28 cabs2mt[ABS_MT_##name] - 1)
29
30static unsigned int cabs2mt[ABS_CNT];
31static unsigned int cmt2abs[MT_ABS_SIZE];
32
33void init_caps()
34{
35 static const int init_abs_map[MT_ABS_SIZE] = MT_SLOT_ABS_EVENTS;
36 int i;
37 for (i = 0; i < MT_ABS_SIZE; i++) {
38 cabs2mt[init_abs_map[i]] = i + 1;
39 cmt2abs[i] = init_abs_map[i];
40 }
41}
42
43static inline const char *newln(int i, int n)
44{
45 return i == n - 1 || i % 8 == 7 ? "\n" : "";
46}
47
48int main(int argc, char *argv[])
49{
50 int i;
51 init_caps();
52 printf("static const unsigned int map_abs2mt[ABS_CNT] = {\n");
53 for (i = 0; i < ABS_CNT; i++)
54 printf(" 0x%04x,%s", cabs2mt[i], newln(i, ABS_CNT));
55 printf("};\n\n");
56 printf("static const unsigned int map_mt2abs[MT_ABS_SIZE] = {\n");
57 for (i = 0; i < MT_ABS_SIZE; i++)
58 printf(" 0x%04x,%s", cmt2abs[i], newln(i, MT_ABS_SIZE));
59 printf("};\n\n");
60 BIT_DEF(TRACKING_ID);
61 BIT_DEF(POSITION_X);
62 BIT_DEF(POSITION_Y);
63 BIT_DEF(TOUCH_MAJOR);
64 BIT_DEF(TOUCH_MINOR);
65 BIT_DEF(WIDTH_MAJOR);
66 BIT_DEF(WIDTH_MINOR);
67 printf("\n");
68 return 0;
69}
diff --git a/mtdev/test.c b/mtdev/test.c
deleted file mode 100644
index 9f73fcd..0000000
--- a/mtdev/test.c
+++ /dev/null
@@ -1,79 +0,0 @@
1/***************************************************************************
2 *
3 * Multitouch X driver
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 **************************************************************************/
21
22#include "mtdev-iobuf.h"
23#include "mtdev.h"
24#include <fcntl.h>
25#include <xbypass.h>
26
27static void print_event(const struct input_event *ev)
28{
29 static const mstime_t ms = 1000;
30 static int slot;
31 mstime_t evtime = ev->time.tv_usec / ms + ev->time.tv_sec * ms;
32 if (ev->type == EV_ABS && ev->code == ABS_MT_SLOT)
33 slot = ev->value;
34 fprintf(stderr, "%012llx: %04d: %04x %04x %d\n",
35 evtime, slot, ev->type, ev->code, ev->value);
36}
37
38static void loop_device(int fd)
39{
40 struct Capabilities caps;
41 struct IOBuffer iobuf;
42 struct MTDev mtdev;
43 const struct input_event *ev;
44 struct input_event event;
45 if (read_capabilities(&caps, fd)) {
46 fprintf(stderr, "error: could not read device capabilities\n");
47 return;
48 }
49 output_capabilities(&caps);
50 if (mtdev_init(&mtdev, &caps)) {
51 fprintf(stderr, "error: could not initialize device\n");
52 return;
53 }
54 init_iobuf(&iobuf);
55 while (ev = get_iobuf_event(&iobuf, fd)) {
56 mtdev_put(&mtdev, &caps, ev);
57 while (!mtdev_empty(&mtdev)) {
58 mtdev_get(&mtdev, &event);
59 print_event(&event);
60 }
61 }
62 mtdev_destroy(&mtdev);
63}
64
65int main(int argc, char *argv[])
66{
67 if (argc < 2) {
68 fprintf(stderr, "Usage: test <mtdev>\n");
69 return -1;
70 }
71 int fd = open(argv[1], O_RDONLY);
72 if (fd < 0) {
73 fprintf(stderr, "error: could not open file\n");
74 return -1;
75 }
76 loop_device(fd);
77 close(fd);
78 return 0;
79}
diff --git a/mtdev/caps.c b/src/capabilities.c
index 069816e..0d11669 100644
--- a/mtdev/caps.c
+++ b/src/capabilities.c
@@ -19,8 +19,7 @@
19 * 19 *
20 **************************************************************************/ 20 **************************************************************************/
21 21
22#include "mtdev-caps.h" 22#include "capabilities.h"
23#include "mtbit.h"
24 23
25#define SETABS(c, x, map, key, fd) \ 24#define SETABS(c, x, map, key, fd) \
26 (c->has_##x = getbit(map, key) && getabs(&c->x, key, fd)) 25 (c->has_##x = getbit(map, key) && getabs(&c->x, key, fd))
@@ -52,7 +51,7 @@ static int getabs(struct input_absinfo *abs, int key, int fd)
52 51
53static int has_mt_data(const struct Capabilities *cap) 52static int has_mt_data(const struct Capabilities *cap)
54{ 53{
55 return cap->has_abs[BIT_POSITION_X] && cap->has_abs[BIT_POSITION_Y]; 54 return cap->has_abs[MTDEV_POSITION_X] && cap->has_abs[MTDEV_POSITION_Y];
56} 55}
57 56
58static int has_integrated_button(const struct Capabilities *cap) 57static int has_integrated_button(const struct Capabilities *cap)
@@ -65,7 +64,7 @@ static int has_integrated_button(const struct Capabilities *cap)
65 64
66static void default_fuzz(struct Capabilities *cap, unsigned int code, int sn) 65static void default_fuzz(struct Capabilities *cap, unsigned int code, int sn)
67{ 66{
68 int bit = abs2mt(code); 67 int bit = mtdev_abs2mt(code);
69 if (cap->has_abs[bit] && cap->abs[bit].fuzz == 0) 68 if (cap->has_abs[bit] && cap->abs[bit].fuzz == 0)
70 cap->abs[bit].fuzz = 69 cap->abs[bit].fuzz =
71 (cap->abs[bit].maximum - cap->abs[bit].minimum) / sn; 70 (cap->abs[bit].maximum - cap->abs[bit].minimum) / sn;
@@ -102,14 +101,11 @@ int read_capabilities(struct Capabilities *cap, int fd)
102 101
103 SETABS(cap, slot, absbits, ABS_MT_SLOT, fd); 102 SETABS(cap, slot, absbits, ABS_MT_SLOT, fd);
104 for (i = 0; i < MT_ABS_SIZE; i++) 103 for (i = 0; i < MT_ABS_SIZE; i++)
105 SETABS(cap, abs[i], absbits, mt2abs(i), fd); 104 SETABS(cap, abs[i], absbits, mtdev_mt2abs(i), fd);
106 105
107 cap->has_mtdata = has_mt_data(cap); 106 cap->has_mtdata = has_mt_data(cap);
108 cap->has_ibt = has_integrated_button(cap); 107 cap->has_ibt = has_integrated_button(cap);
109 108
110 if (cap->has_abs[BIT_TRACKING_ID])
111 cap->nullid = cap->abs[BIT_TRACKING_ID].minimum - 1;
112
113 default_fuzz(cap, ABS_MT_POSITION_X, SN_COORD); 109 default_fuzz(cap, ABS_MT_POSITION_X, SN_COORD);
114 default_fuzz(cap, ABS_MT_POSITION_Y, SN_COORD); 110 default_fuzz(cap, ABS_MT_POSITION_Y, SN_COORD);
115 default_fuzz(cap, ABS_MT_TOUCH_MAJOR, SN_WIDTH); 111 default_fuzz(cap, ABS_MT_TOUCH_MAJOR, SN_WIDTH);
@@ -123,31 +119,31 @@ int read_capabilities(struct Capabilities *cap, int fd)
123 119
124int get_cap_xsize(const struct Capabilities *cap) 120int get_cap_xsize(const struct Capabilities *cap)
125{ 121{
126 const struct input_absinfo *x = &cap->abs[BIT_POSITION_X]; 122 const struct input_absinfo *x = &cap->abs[MTDEV_POSITION_X];
127 return x->maximum - x->minimum; 123 return x->maximum - x->minimum;
128} 124}
129 125
130int get_cap_ysize(const struct Capabilities *cap) 126int get_cap_ysize(const struct Capabilities *cap)
131{ 127{
132 const struct input_absinfo *y = &cap->abs[BIT_POSITION_Y]; 128 const struct input_absinfo *y = &cap->abs[MTDEV_POSITION_Y];
133 return y->maximum - y->minimum; 129 return y->maximum - y->minimum;
134} 130}
135 131
136int get_cap_wsize(const struct Capabilities *cap) 132int get_cap_wsize(const struct Capabilities *cap)
137{ 133{
138 const struct input_absinfo *w = &cap->abs[BIT_TOUCH_MAJOR]; 134 const struct input_absinfo *w = &cap->abs[MTDEV_TOUCH_MAJOR];
139 return w->maximum - w->minimum; 135 return w->maximum - w->minimum;
140} 136}
141 137
142int get_cap_xmid(const struct Capabilities *cap) 138int get_cap_xmid(const struct Capabilities *cap)
143{ 139{
144 const struct input_absinfo *x = &cap->abs[BIT_POSITION_X]; 140 const struct input_absinfo *x = &cap->abs[MTDEV_POSITION_X];
145 return (x->maximum + x->minimum) >> 1; 141 return (x->maximum + x->minimum) >> 1;
146} 142}
147 143
148int get_cap_ymid(const struct Capabilities *cap) 144int get_cap_ymid(const struct Capabilities *cap)
149{ 145{
150 const struct input_absinfo *y = &cap->abs[BIT_POSITION_Y]; 146 const struct input_absinfo *y = &cap->abs[MTDEV_POSITION_Y];
151 return (y->maximum + y->minimum) >> 1; 147 return (y->maximum + y->minimum) >> 1;
152} 148}
153 149
diff --git a/src/hwstate.c b/src/hwstate.c
index 82a3a10..076efa1 100644
--- a/src/hwstate.c
+++ b/src/hwstate.c
@@ -26,7 +26,7 @@ void init_hwstate(struct HWState *s, const struct Capabilities *caps)
26 int i; 26 int i;
27 memset(s, 0, sizeof(struct HWState)); 27 memset(s, 0, sizeof(struct HWState));
28 for (i = 0; i < DIM_FINGER; i++) 28 for (i = 0; i < DIM_FINGER; i++)
29 s->data[i].tracking_id = caps->nullid; 29 s->data[i].tracking_id = MT_ID_NULL;
30} 30}
31 31
32static void finish_packet(struct HWState *s, const struct Capabilities *caps, 32static void finish_packet(struct HWState *s, const struct Capabilities *caps,
@@ -35,16 +35,16 @@ static void finish_packet(struct HWState *s, const struct Capabilities *caps,
35 static const mstime_t ms = 1000; 35 static const mstime_t ms = 1000;
36 int i; 36 int i;
37 foreach_bit(i, s->used) { 37 foreach_bit(i, s->used) {
38 if (!caps->has_abs[BIT_TOUCH_MINOR]) 38 if (!caps->has_abs[MTDEV_TOUCH_MINOR])
39 s->data[i].touch_minor = s->data[i].touch_major; 39 s->data[i].touch_minor = s->data[i].touch_major;
40 if (!caps->has_abs[BIT_WIDTH_MINOR]) 40 if (!caps->has_abs[MTDEV_WIDTH_MINOR])
41 s->data[i].width_minor = s->data[i].width_major; 41 s->data[i].width_minor = s->data[i].width_major;
42 } 42 }
43 s->evtime = syn->time.tv_usec / ms + syn->time.tv_sec * ms; 43 s->evtime = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
44} 44}
45 45
46int hwstate_read(struct HWState *s, const struct Capabilities *caps, 46static int read_event(struct HWState *s, const struct Capabilities *caps,
47 const struct input_event *ev) 47 const struct input_event *ev)
48{ 48{
49 switch (ev->type) { 49 switch (ev->type) {
50 case EV_SYN: 50 case EV_SYN:
@@ -99,11 +99,21 @@ int hwstate_read(struct HWState *s, const struct Capabilities *caps,
99 break; 99 break;
100 case ABS_MT_TRACKING_ID: 100 case ABS_MT_TRACKING_ID:
101 s->data[s->slot].tracking_id = ev->value; 101 s->data[s->slot].tracking_id = ev->value;
102 MODBIT(s->used, s->slot, 102 MODBIT(s->used, s->slot, ev->value != MT_ID_NULL);
103 ev->value != caps->nullid);
104 break; 103 break;
105 } 104 }
106 break; 105 break;
107 } 106 }
108 return 0; 107 return 0;
109} 108}
109
110int modify_hwstate(struct HWState *s, struct mtdev *dev, int fd,
111 const struct Capabilities *caps)
112{
113 struct input_event ev;
114 int ret;
115 while ((ret = mtdev_get(dev, fd, &ev, 1)) > 0)
116 if (read_event(s, caps, &ev))
117 return 1;
118 return ret;
119}
diff --git a/src/memory.c b/src/memory.c
index 974a531..63134ca 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -119,13 +119,13 @@ static void update_pointers(struct Memory *m,
119 const struct Capabilities *caps) 119 const struct Capabilities *caps)
120{ 120{
121 const struct FingerState *f = state->finger; 121 const struct FingerState *f = state->finger;
122 int yclick = caps->abs[BIT_POSITION_Y].maximum - CLICK_AREA(caps); 122 int yclick = caps->abs[MTDEV_POSITION_Y].maximum - CLICK_AREA(caps);
123 123
124 int i; 124 int i;
125 125
126 if (state->nfinger < 2) { 126 if (state->nfinger < 2) {
127 m->pointing = m->fingers; 127 m->pointing = m->fingers;
128 m->ybar = caps->abs[BIT_POSITION_Y].maximum; 128 m->ybar = caps->abs[MTDEV_POSITION_Y].maximum;
129 return; 129 return;
130 } 130 }
131 131
diff --git a/src/mtouch.c b/src/mtouch.c
index f7a2710..e2d9572 100644
--- a/src/mtouch.c
+++ b/src/mtouch.c
@@ -34,8 +34,7 @@ int configure_mtouch(struct MTouch *mt, int fd)
34 34
35int open_mtouch(struct MTouch *mt, int fd) 35int open_mtouch(struct MTouch *mt, int fd)
36{ 36{
37 mtdev_init(&mt->dev, &mt->caps); 37 mtdev_open(&mt->dev, fd);
38 init_iobuf(&mt->buf);
39 init_hwstate(&mt->hs, &mt->caps); 38 init_hwstate(&mt->hs, &mt->caps);
40 init_mtstate(&mt->prev_state); 39 init_mtstate(&mt->prev_state);
41 init_mtstate(&mt->state); 40 init_mtstate(&mt->state);
@@ -48,40 +47,19 @@ int open_mtouch(struct MTouch *mt, int fd)
48 return 0; 47 return 0;
49} 48}
50 49
51
52int get_mtouch(struct MTouch *mt, int fd, struct input_event* ev, int ev_max)
53{
54 const struct input_event *kev;
55 int count = 0;
56 while (count < ev_max) {
57 while (mtdev_empty(&mt->dev)) {
58 kev = get_iobuf_event(&mt->buf, fd);
59 if (!kev)
60 return count;
61 mtdev_put(&mt->dev, &mt->caps, kev);
62 }
63 mtdev_get(&mt->dev, &ev[count++]);
64 }
65 return count;
66}
67
68int close_mtouch(struct MTouch *mt, int fd) 50int close_mtouch(struct MTouch *mt, int fd)
69{ 51{
70 if (use_grab) { 52 if (use_grab) {
71 int rc; 53 int rc;
72 SYSCALL(rc = ioctl(fd, EVIOCGRAB, (pointer)0)); 54 SYSCALL(rc = ioctl(fd, EVIOCGRAB, (pointer)0));
73 } 55 }
74 mtdev_destroy(&mt->dev); 56 mtdev_close(&mt->dev);
75 return 0; 57 return 0;
76} 58}
77 59
78int read_packet(struct MTouch *mt, int fd) 60int read_packet(struct MTouch *mt, int fd)
79{ 61{
80 struct input_event ev; 62 int ret = modify_hwstate(&mt->hs, &mt->dev, fd, &mt->caps);
81 int ret;
82 while ((ret = get_mtouch(mt, fd, &ev, 1)) > 0)
83 if (hwstate_read(&mt->hs, &mt->caps, &ev))
84 break;
85 if (ret <= 0) 63 if (ret <= 0)
86 return ret; 64 return ret;
87 extract_mtstate(&mt->state, &mt->hs, &mt->caps); 65 extract_mtstate(&mt->state, &mt->hs, &mt->caps);
@@ -97,7 +75,5 @@ int read_packet(struct MTouch *mt, int fd)
97 75
98int has_delayed_gestures(struct MTouch *mt, int fd) 76int has_delayed_gestures(struct MTouch *mt, int fd)
99{ 77{
100 return mt->mem.wait && 78 return mt->mem.wait && mtdev_idle(&mt->dev, fd, mt->mem.wait);
101 mtdev_empty(&mt->dev) &&
102 poll_iobuf(&mt->buf, fd, mt->mem.wait) == 0;
103} 79}
diff --git a/src/mtstate.c b/src/mtstate.c
index 7a8ef19..4c893a2 100644
--- a/src/mtstate.c
+++ b/src/mtstate.c
@@ -22,7 +22,7 @@
22#include "mtstate.h" 22#include "mtstate.h"
23 23
24#define TOUCH_WIDTH(hw) (0.05 * hw->width_major) 24#define TOUCH_WIDTH(hw) (0.05 * hw->width_major)
25#define TOUCH_SCALE(caps) (0.05 * caps->abs[BIT_TOUCH_MAJOR].maximum) 25#define TOUCH_SCALE(caps) (0.05 * caps->abs[MTDEV_TOUCH_MAJOR].maximum)
26 26
27#define THUMB_TOUCH(hw) (1.2 * hw->touch_minor) 27#define THUMB_TOUCH(hw) (1.2 * hw->touch_minor)
28#define THUMB_WIDTH_TOUCH(hw) (3 * hw->touch_major) 28#define THUMB_WIDTH_TOUCH(hw) (3 * hw->touch_major)
@@ -37,9 +37,9 @@ void init_mtstate(struct MTState *s)
37static int touching_finger(const struct FingerState *hw, 37static int touching_finger(const struct FingerState *hw,
38 const struct Capabilities *caps) 38 const struct Capabilities *caps)
39{ 39{
40 if (caps->has_abs[BIT_TOUCH_MAJOR] && caps->has_abs[BIT_WIDTH_MAJOR]) 40 if (caps->has_abs[MTDEV_TOUCH_MAJOR] && caps->has_abs[MTDEV_WIDTH_MAJOR])
41 return hw->touch_major > TOUCH_WIDTH(hw); 41 return hw->touch_major > TOUCH_WIDTH(hw);
42 if (caps->has_abs[BIT_TOUCH_MAJOR]) 42 if (caps->has_abs[MTDEV_TOUCH_MAJOR])
43 return hw->touch_major > TOUCH_SCALE(caps); 43 return hw->touch_major > TOUCH_SCALE(caps);
44 return 1; 44 return 1;
45} 45}
@@ -55,10 +55,10 @@ static int touching_finger(const struct FingerState *hw,
55static int is_thumb(const struct FingerState *hw, 55static int is_thumb(const struct FingerState *hw,
56 const struct Capabilities *caps) 56 const struct Capabilities *caps)
57{ 57{
58 if (!caps->has_abs[BIT_TOUCH_MAJOR] || 58 if (!caps->has_abs[MTDEV_TOUCH_MAJOR] ||
59 !caps->has_abs[BIT_TOUCH_MINOR] || 59 !caps->has_abs[MTDEV_TOUCH_MINOR] ||
60 !caps->has_abs[BIT_WIDTH_MAJOR] || 60 !caps->has_abs[MTDEV_WIDTH_MAJOR] ||
61 !caps->has_abs[BIT_WIDTH_MINOR]) 61 !caps->has_abs[MTDEV_WIDTH_MINOR])
62 return 0; 62 return 0;
63 return hw->touch_major > THUMB_TOUCH(hw) && 63 return hw->touch_major > THUMB_TOUCH(hw) &&
64 hw->width_major > THUMB_WIDTH_TOUCH(hw) && 64 hw->width_major > THUMB_WIDTH_TOUCH(hw) &&
diff --git a/src/test.c b/src/test.c
index e4247d2..3a23db3 100644
--- a/src/test.c
+++ b/src/test.c
@@ -35,8 +35,8 @@ static void loop_device(int fd)
35 fprintf(stderr, "error: could not open device\n"); 35 fprintf(stderr, "error: could not open device\n");
36 return; 36 return;
37 } 37 }
38 while (poll_iobuf(&mt.buf, fd, 5000)) { 38 while (mtdev_pull(&mt.dev, fd, 1) > 0) {
39 while (read_packet(&mt, fd) > 0) { 39 if (parse_event(&mt)) {
40 extract_gestures(&gs, &mt); 40 extract_gestures(&gs, &mt);
41 output_gesture(&gs); 41 output_gesture(&gs);
42 } 42 }