summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mtdev-mapping.h4
-rw-r--r--include/mtdev-plumbing.h37
-rw-r--r--include/mtdev.h117
-rw-r--r--src/Makefile.am2
-rw-r--r--src/caps.c163
-rw-r--r--src/common.h59
-rw-r--r--src/core.c126
-rw-r--r--src/state.h27
-rw-r--r--test/mtdev-mapgen.c32
9 files changed, 425 insertions, 142 deletions
diff --git a/include/mtdev-mapping.h b/include/mtdev-mapping.h
index 0e47970..0cdb39d 100644
--- a/include/mtdev-mapping.h
+++ b/include/mtdev-mapping.h
@@ -37,6 +37,8 @@ extern "C" {
37 37
38#include <mtdev.h> 38#include <mtdev.h>
39 39
40#ifndef MTDEV_NO_LEGACY_API
41
40#define MTDEV_TOUCH_MAJOR 0 42#define MTDEV_TOUCH_MAJOR 0
41#define MTDEV_TOUCH_MINOR 1 43#define MTDEV_TOUCH_MINOR 1
42#define MTDEV_WIDTH_MAJOR 2 44#define MTDEV_WIDTH_MAJOR 2
@@ -80,6 +82,8 @@ static inline unsigned int mtdev_mt2abs(unsigned int mtcode)
80 return mtdev_map_mt2abs[mtcode]; 82 return mtdev_map_mt2abs[mtcode];
81} 83}
82 84
85#endif
86
83#ifdef __cplusplus 87#ifdef __cplusplus
84} 88}
85#endif 89#endif
diff --git a/include/mtdev-plumbing.h b/include/mtdev-plumbing.h
index cadc1f7..21ca708 100644
--- a/include/mtdev-plumbing.h
+++ b/include/mtdev-plumbing.h
@@ -36,6 +36,15 @@ extern "C" {
36#include <mtdev.h> 36#include <mtdev.h>
37 37
38/** 38/**
39 * mtdev_new - allocate a new mtdev
40 *
41 * Allocate a new mtdev.
42 *
43 * Returns zero in case of memory allocation failure.
44 */
45struct mtdev *mtdev_new(void);
46
47/**
39 * mtdev_init - initialize mtdev converter 48 * mtdev_init - initialize mtdev converter
40 * @dev: the mtdev to initialize 49 * @dev: the mtdev to initialize
41 * 50 *
@@ -46,6 +55,26 @@ extern "C" {
46int mtdev_init(struct mtdev *dev); 55int mtdev_init(struct mtdev *dev);
47 56
48/** 57/**
58 * mtdev_set_mt_event - set event type
59 * @dev: the mtdev in use
60 * @code: the ABS_MT code to set
61 * @value: boolean value
62 *
63 * Returns true if the given event code is present.
64 */
65void mtdev_set_mt_event(struct mtdev *dev, int code, int value);
66
67/**
68 * mtdev_set_abs_<property> - set abs event property
69 * @dev: the mtdev in use
70 * @code: the ABS_MT code to set
71 */
72void mtdev_set_abs_minimum(struct mtdev *dev, int code, int value);
73void mtdev_set_abs_maximum(struct mtdev *dev, int code, int value);
74void mtdev_set_abs_fuzz(struct mtdev *dev, int code, int value);
75void mtdev_set_abs_resolution(struct mtdev *dev, int code, int value);
76
77/**
49 * mtdev_configure - configure the mtdev converter 78 * mtdev_configure - configure the mtdev converter
50 * @dev: the mtdev to configure 79 * @dev: the mtdev to configure
51 * @fd: file descriptor of the kernel device 80 * @fd: file descriptor of the kernel device
@@ -106,6 +135,14 @@ int mtdev_empty(struct mtdev *dev);
106 */ 135 */
107void mtdev_get_event(struct mtdev *dev, struct input_event* ev); 136void mtdev_get_event(struct mtdev *dev, struct input_event* ev);
108 137
138/**
139 * mtdev_delete - free a previously allocated mtdev
140 *
141 * Frees the memory associated with the mtdev and invalidates the
142 * mtdev pointer.
143 */
144void mtdev_delete(struct mtdev *dev);
145
109#ifdef __cplusplus 146#ifdef __cplusplus
110} 147}
111#endif 148#endif
diff --git a/include/mtdev.h b/include/mtdev.h
index 15bc53b..df74e95 100644
--- a/include/mtdev.h
+++ b/include/mtdev.h
@@ -62,59 +62,23 @@ extern "C" {
62#ifndef ABS_MT_SLOT 62#ifndef ABS_MT_SLOT
63#define ABS_MT_SLOT 0x2f /* MT slot being modified */ 63#define ABS_MT_SLOT 0x2f /* MT slot being modified */
64#endif 64#endif
65#ifndef MT_SLOT_ABS_EVENTS
66#define MT_SLOT_ABS_EVENTS { \
67 ABS_MT_TOUCH_MAJOR, \
68 ABS_MT_TOUCH_MINOR, \
69 ABS_MT_WIDTH_MAJOR, \
70 ABS_MT_WIDTH_MINOR, \
71 ABS_MT_ORIENTATION, \
72 ABS_MT_POSITION_X, \
73 ABS_MT_POSITION_Y, \
74 ABS_MT_TOOL_TYPE, \
75 ABS_MT_BLOB_ID, \
76 ABS_MT_TRACKING_ID, \
77 ABS_MT_PRESSURE, \
78}
79#endif
80
81#define MT_ABS_SIZE 11
82 65
83#define MT_ID_NULL (-1) 66#define MT_ID_NULL (-1)
84#define MT_ID_MIN 0 67#define MT_ID_MIN 0
85#define MT_ID_MAX 65535 68#define MT_ID_MAX 65535
86 69
87/** 70/**
88 * struct mt_caps - protocol capabilities of kernel device 71 * mtdev_new_open - create and open a new mtdev
89 * @has_mtdata: true if the device has MT capabilities 72 * @fd: file descriptor of the kernel device
90 * @has_slot: true if the device sends MT slots 73 *
91 * @slot: slot event properties 74 * Create a new mtdev and open the conversion.
92 * @abs: ABS_MT event properties
93 */
94struct mtdev_caps {
95 int has_mtdata;
96 int has_slot;
97 int has_abs[MT_ABS_SIZE];
98 struct input_absinfo slot;
99 struct input_absinfo abs[MT_ABS_SIZE];
100};
101
102/**
103 * struct mtdev - represents an input MT device
104 * @caps: the kernel device protocol capabilities
105 * @state: internal mtdev parsing state
106 * 75 *
107 * The mtdev structure represents a kernel MT device type B, emitting 76 * Returns zero in case of failure.
108 * MT slot events. The events put into mtdev may be from any MT
109 * device, specifically type A without contact tracking, type A with
110 * contact tracking, or type B with contact tracking. See the kernel
111 * documentation for further details.
112 * 77 *
78 * This call combines the plumbing functions mtdev_new() and
79 * mtdev_open().
113 */ 80 */
114struct mtdev { 81struct mtdev *mtdev_new_open(int fd);
115 struct mtdev_caps caps;
116 struct mtdev_state *state;
117};
118 82
119/** 83/**
120 * mtdev_open - open an mtdev converter 84 * mtdev_open - open an mtdev converter
@@ -132,6 +96,27 @@ struct mtdev {
132int mtdev_open(struct mtdev *dev, int fd); 96int mtdev_open(struct mtdev *dev, int fd);
133 97
134/** 98/**
99 * mtdev_has_mt_event - check for event type
100 * @dev: the mtdev in use
101 * @code: the ABS_MT code to look for
102 *
103 * Returns true if the given event code is present.
104 */
105int mtdev_has_mt_event(const struct mtdev *dev, int code);
106
107/**
108 * mtdev_get_abs_<property> - get abs event property
109 * @dev: the mtdev in use
110 * @code: the ABS_MT code to look for
111 *
112 * Returns NULL if code is not a valid ABS_MT code.
113 */
114int mtdev_get_abs_minimum(const struct mtdev *dev, int code);
115int mtdev_get_abs_maximum(const struct mtdev *dev, int code);
116int mtdev_get_abs_fuzz(const struct mtdev *dev, int code);
117int mtdev_get_abs_resolution(const struct mtdev *dev, int code);
118
119/**
135 * mtdev_idle - check state of kernel device 120 * mtdev_idle - check state of kernel device
136 * @dev: the mtdev in use 121 * @dev: the mtdev in use
137 * @fd: file descriptor of the kernel device 122 * @fd: file descriptor of the kernel device
@@ -173,6 +158,50 @@ int mtdev_get(struct mtdev *dev, int fd, struct input_event* ev, int ev_max);
173 */ 158 */
174void mtdev_close(struct mtdev *dev); 159void mtdev_close(struct mtdev *dev);
175 160
161/**
162 * mtdev_close_delete - close conversion and delete mtdev
163 * @dev: the mtdev in use
164 *
165 * Flush pending buffers and deallocate all memory associated with
166 * mtdev. The device pointer is invalidated. This call combines the
167 * plumbing functions mtdev_close() and mtdev_delete().
168 */
169void mtdev_close_delete(struct mtdev *dev);
170
171#ifndef MTDEV_NO_LEGACY_API
172
173#define MT_ABS_SIZE 11
174#ifndef MT_SLOT_ABS_EVENTS
175#define MT_SLOT_ABS_EVENTS { \
176 ABS_MT_TOUCH_MAJOR, \
177 ABS_MT_TOUCH_MINOR, \
178 ABS_MT_WIDTH_MAJOR, \
179 ABS_MT_WIDTH_MINOR, \
180 ABS_MT_ORIENTATION, \
181 ABS_MT_POSITION_X, \
182 ABS_MT_POSITION_Y, \
183 ABS_MT_TOOL_TYPE, \
184 ABS_MT_BLOB_ID, \
185 ABS_MT_TRACKING_ID, \
186 ABS_MT_PRESSURE, \
187}
188#endif
189
190struct mtdev_caps {
191 int has_mtdata;
192 int has_slot;
193 int has_abs[MT_ABS_SIZE];
194 struct input_absinfo slot;
195 struct input_absinfo abs[MT_ABS_SIZE];
196};
197
198struct mtdev {
199 struct mtdev_caps caps;
200 struct mtdev_state *state;
201};
202
203#endif
204
176#ifdef __cplusplus 205#ifdef __cplusplus
177} 206}
178#endif 207#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 1c22c33..16d388c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,7 +16,7 @@ libmtdev_la_SOURCES = \
16 match.c \ 16 match.c \
17 match_four.c 17 match_four.c
18 18
19AM_CFLAGS = $(CWARNFLAGS) 19AM_CFLAGS = $(CWARNFLAGS) #-DMTDEV_NO_LEGACY_ABI
20 20
21INCLUDES = -I$(top_srcdir)/include/ 21INCLUDES = -I$(top_srcdir)/include/
22 22
diff --git a/src/caps.c b/src/caps.c
index bf578fa..23f16fc 100644
--- a/src/caps.c
+++ b/src/caps.c
@@ -26,10 +26,7 @@
26 * 26 *
27 ****************************************************************************/ 27 ****************************************************************************/
28 28
29#include "common.h" 29#include "state.h"
30
31#define SETABS(c, x, map, key, fd) \
32 (c->has_##x = getbit(map, key) && getabs(&c->x, key, fd))
33 30
34static const int SN_COORD = 250; /* coordinate signal-to-noise ratio */ 31static const int SN_COORD = 250; /* coordinate signal-to-noise ratio */
35static const int SN_WIDTH = 100; /* width signal-to-noise ratio */ 32static const int SN_WIDTH = 100; /* width signal-to-noise ratio */
@@ -54,59 +51,157 @@ static int getabs(struct input_absinfo *abs, int key, int fd)
54 return rc >= 0; 51 return rc >= 0;
55} 52}
56 53
57static int has_mt_data(const struct mtdev_caps *cap) 54static struct input_absinfo *get_info(struct mtdev *dev, int code)
58{ 55{
59 return cap->has_abs[MTDEV_POSITION_X] && cap->has_abs[MTDEV_POSITION_Y]; 56 int ix;
57
58 if (code == ABS_MT_SLOT)
59 return &dev->slot;
60 if (!mtdev_is_absmt(code))
61 return NULL;
62
63 ix = mtdev_abs2mt(code);
64 if (ix < 11)
65 return &dev->abs[ix];
66 else
67 return &dev->state->ext_abs[ix - 11];
60} 68}
61 69
62static void default_fuzz(struct mtdev_caps *cap, int bit, int sn) 70static void set_info(struct mtdev *dev, int code,
71 const unsigned long *bits, int fd)
63{ 72{
64 if (cap->has_abs[bit] && cap->abs[bit].fuzz == 0) 73 int has = getbit(bits, code) && getabs(get_info(dev, code), code, fd);
65 cap->abs[bit].fuzz = 74 mtdev_set_mt_event(dev, code, has);
66 (cap->abs[bit].maximum - cap->abs[bit].minimum) / sn;
67} 75}
68 76
69static int read_caps(struct mtdev_caps *cap, int fd) 77static void default_fuzz(struct mtdev *dev, int code, int sn)
78{
79 struct input_absinfo *abs = get_info(dev, code);
80 if (!mtdev_has_mt_event(dev, code) || abs->fuzz)
81 return;
82 abs->fuzz = (abs->maximum - abs->minimum) / sn;
83}
84
85int mtdev_configure(struct mtdev *dev, int fd)
70{ 86{
71 unsigned long absbits[nlongs(ABS_MAX)]; 87 unsigned long absbits[nlongs(ABS_MAX)];
72 int rc, i; 88 int rc, i;
73 89
74 memset(cap, 0, sizeof(struct mtdev_caps));
75
76 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits)); 90 SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
77 if (rc < 0) 91 if (rc < 0)
78 return rc; 92 return rc;
79 93
80 SETABS(cap, slot, absbits, ABS_MT_SLOT, fd); 94 set_info(dev, ABS_MT_SLOT, absbits, fd);
81 for (i = 0; i < MT_ABS_SIZE; i++) 95 for (i = 0; i < MT_ABS_SIZE; i++)
82 SETABS(cap, abs[i], absbits, mtdev_mt2abs(i), fd); 96 set_info(dev, mtdev_mt2abs(i), absbits, fd);
83 97
84 cap->has_mtdata = has_mt_data(cap); 98 dev->has_mtdata = mtdev_has_mt_event(dev, ABS_MT_POSITION_X) &&
99 mtdev_has_mt_event(dev, ABS_MT_POSITION_Y);
85 100
86 if (!cap->has_abs[MTDEV_POSITION_X]) 101 if (!mtdev_has_mt_event(dev, ABS_MT_POSITION_X))
87 getabs(&cap->abs[MTDEV_POSITION_X], ABS_X, fd); 102 getabs(get_info(dev, ABS_MT_POSITION_X), ABS_X, fd);
88 if (!cap->has_abs[MTDEV_POSITION_Y]) 103 if (!mtdev_has_mt_event(dev, ABS_MT_POSITION_Y))
89 getabs(&cap->abs[MTDEV_POSITION_Y], ABS_Y, fd); 104 getabs(get_info(dev, ABS_MT_POSITION_Y), ABS_Y, fd);
90 if (!cap->has_abs[MTDEV_PRESSURE]) 105 if (!mtdev_has_mt_event(dev, ABS_MT_PRESSURE))
91 getabs(&cap->abs[MTDEV_PRESSURE], ABS_PRESSURE, fd); 106 getabs(get_info(dev, ABS_MT_PRESSURE), ABS_PRESSURE, fd);
92 107
93 if (!cap->has_abs[MTDEV_TRACKING_ID]) { 108 if (!mtdev_has_mt_event(dev, ABS_MT_TRACKING_ID)) {
94 cap->abs[MTDEV_TRACKING_ID].minimum = MT_ID_MIN; 109 mtdev_set_abs_minimum(dev, ABS_MT_TRACKING_ID, MT_ID_MIN);
95 cap->abs[MTDEV_TRACKING_ID].maximum = MT_ID_MAX; 110 mtdev_set_abs_maximum(dev, ABS_MT_TRACKING_ID, MT_ID_MAX);
96 } 111 }
97 112
98 default_fuzz(cap, MTDEV_POSITION_X, SN_COORD); 113 default_fuzz(dev, ABS_MT_POSITION_X, SN_COORD);
99 default_fuzz(cap, MTDEV_POSITION_Y, SN_COORD); 114 default_fuzz(dev, ABS_MT_POSITION_Y, SN_COORD);
100 default_fuzz(cap, MTDEV_TOUCH_MAJOR, SN_WIDTH); 115 default_fuzz(dev, ABS_MT_TOUCH_MAJOR, SN_WIDTH);
101 default_fuzz(cap, MTDEV_TOUCH_MINOR, SN_WIDTH); 116 default_fuzz(dev, ABS_MT_TOUCH_MINOR, SN_WIDTH);
102 default_fuzz(cap, MTDEV_WIDTH_MAJOR, SN_WIDTH); 117 default_fuzz(dev, ABS_MT_WIDTH_MAJOR, SN_WIDTH);
103 default_fuzz(cap, MTDEV_WIDTH_MINOR, SN_WIDTH); 118 default_fuzz(dev, ABS_MT_WIDTH_MINOR, SN_WIDTH);
104 default_fuzz(cap, MTDEV_ORIENTATION, SN_ORIENT); 119 default_fuzz(dev, ABS_MT_ORIENTATION, SN_ORIENT);
105 120
106 return 0; 121 return 0;
107} 122}
108 123
109int mtdev_configure(struct mtdev *dev, int fd) 124int mtdev_has_mt_event(const struct mtdev *dev, int code)
125{
126 int ix;
127
128 if (code == ABS_MT_SLOT)
129 return dev->has_slot;
130 if (!mtdev_is_absmt(code))
131 return 0;
132
133 ix = mtdev_abs2mt(code);
134 if (ix < 11)
135 return dev->has_abs[ix];
136 else
137 return dev->state->has_ext_abs[ix - 11];
138}
139
140int mtdev_get_abs_minimum(const struct mtdev *dev, int code)
110{ 141{
111 return read_caps(&dev->caps, fd); 142 const struct input_absinfo *abs = get_info((struct mtdev *)dev, code);
143 return abs ? abs->minimum : 0;
112} 144}
145
146int mtdev_get_abs_maximum(const struct mtdev *dev, int code)
147{
148 const struct input_absinfo *abs = get_info((struct mtdev *)dev, code);
149 return abs ? abs->maximum : 0;
150}
151
152int mtdev_get_abs_fuzz(const struct mtdev *dev, int code)
153{
154 const struct input_absinfo *abs = get_info((struct mtdev *)dev, code);
155 return abs ? abs->fuzz : 0;
156}
157
158int mtdev_get_abs_resolution(const struct mtdev *dev, int code)
159{
160 const struct input_absinfo *abs = get_info((struct mtdev *)dev, code);
161 return abs ? abs->resolution : 0;
162}
163
164void mtdev_set_abs_minimum(struct mtdev *dev, int code, int value)
165{
166 struct input_absinfo *abs = get_info(dev, code);
167 if (abs)
168 abs->minimum = value;
169}
170
171void mtdev_set_mt_event(struct mtdev *dev, int code, int value)
172{
173 int ix;
174
175 if (code == ABS_MT_SLOT)
176 dev->has_slot = value;
177 if (!mtdev_is_absmt(code))
178 return;
179
180 ix = mtdev_abs2mt(code);
181 if (ix < 11)
182 dev->has_abs[ix] = value;
183 else
184 dev->state->has_ext_abs[ix - 11] = value;
185}
186
187void mtdev_set_abs_maximum(struct mtdev *dev, int code, int value)
188{
189 struct input_absinfo *abs = get_info(dev, code);
190 if (abs)
191 abs->maximum = value;
192}
193
194void mtdev_set_abs_fuzz(struct mtdev *dev, int code, int value)
195{
196 struct input_absinfo *abs = get_info(dev, code);
197 if (abs)
198 abs->fuzz = value;
199}
200
201void mtdev_set_abs_resolution(struct mtdev *dev, int code, int value)
202{
203 struct input_absinfo *abs = get_info(dev, code);
204 if (abs)
205 abs->resolution = value;
206}
207
diff --git a/src/common.h b/src/common.h
index e06f7f7..43b5688 100644
--- a/src/common.h
+++ b/src/common.h
@@ -29,6 +29,8 @@
29#ifndef COMMON_H 29#ifndef COMMON_H
30#define COMMON_H 30#define COMMON_H
31 31
32#define MTDEV_NO_LEGACY_API
33
32#include <mtdev-mapping.h> 34#include <mtdev-mapping.h>
33#include <mtdev-plumbing.h> 35#include <mtdev-plumbing.h>
34#include <malloc.h> 36#include <malloc.h>
@@ -85,4 +87,61 @@ static inline int bitcount(unsigned v)
85/* robust system ioctl calls */ 87/* robust system ioctl calls */
86#define SYSCALL(call) while (((call) == -1) && (errno == EINTR)) 88#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
87 89
90/**
91 * struct mtdev - represents an input MT device
92 * @has_mtdata: true if the device has MT capabilities
93 * @has_slot: true if the device sends MT slots
94 * @slot: slot event properties
95 * @abs: ABS_MT event properties
96 * @state: internal mtdev parsing state
97 *
98 * The mtdev structure represents a kernel MT device type B, emitting
99 * MT slot events. The events put into mtdev may be from any MT
100 * device, specifically type A without contact tracking, type A with
101 * contact tracking, or type B with contact tracking. See the kernel
102 * documentation for further details.
103 *
104 */
105struct mtdev {
106 int has_mtdata;
107 int has_slot;
108 int has_abs[11];
109 struct input_absinfo slot;
110 struct input_absinfo abs[11];
111 struct mtdev_state *state;
112};
113
114#define MT_ABS_SIZE 11
115
116static const unsigned int mtdev_map_abs2mt[ABS_CNT] = {
117 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
118 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
119 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
120 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
121 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
122 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
123 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
124 0x0009, 0x000a, 0x000b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
125};
126
127static const unsigned int mtdev_map_mt2abs[MT_ABS_SIZE] = {
128 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
129 0x0038, 0x0039, 0x003a,
130};
131
132static inline int mtdev_is_absmt(unsigned int code)
133{
134 return mtdev_map_abs2mt[code];
135}
136
137static inline unsigned int mtdev_abs2mt(unsigned int code)
138{
139 return mtdev_map_abs2mt[code] - 1;
140}
141
142static inline unsigned int mtdev_mt2abs(unsigned int mtcode)
143{
144 return mtdev_map_mt2abs[mtcode];
145}
146
88#endif 147#endif
diff --git a/src/core.c b/src/core.c
index a6798b0..1f7c1fe 100644
--- a/src/core.c
+++ b/src/core.c
@@ -32,10 +32,16 @@
32#include "match.h" 32#include "match.h"
33 33
34static inline int istouch(const struct mtdev_slot *data, 34static inline int istouch(const struct mtdev_slot *data,
35 const struct mtdev_caps *caps) 35 const struct mtdev *dev)
36{ 36{
37 return data->abs[MTDEV_TOUCH_MAJOR] || 37 return data->touch_major ||
38 !caps->has_abs[MTDEV_TOUCH_MAJOR]; 38 !mtdev_has_mt_event(dev, ABS_MT_TOUCH_MAJOR);
39}
40
41static inline int isfilled(unsigned int mask)
42{
43 return GETBIT(mask, mtdev_abs2mt(ABS_MT_POSITION_X)) &&
44 GETBIT(mask, mtdev_abs2mt(ABS_MT_POSITION_Y));
39} 45}
40 46
41/* Response-augmented EWMA filter, courtesy of Vojtech Pavlik */ 47/* Response-augmented EWMA filter, courtesy of Vojtech Pavlik */
@@ -58,7 +64,7 @@ static int defuzz(int value, int old_val, int fuzz)
58/* 64/*
59 * solve - solve contact matching problem 65 * solve - solve contact matching problem
60 * @state: mtdev state 66 * @state: mtdev state
61 * @caps: device capabilities 67 * @dev: device capabilities
62 * @sid: array of current tracking ids 68 * @sid: array of current tracking ids
63 * @sx: array of current position x 69 * @sx: array of current position x
64 * @sy: array of current position y 70 * @sy: array of current position y
@@ -69,7 +75,7 @@ static int defuzz(int value, int old_val, int fuzz)
69 * @nn: number of new contacts 75 * @nn: number of new contacts
70 * @touch: which of the new contacts to fill 76 * @touch: which of the new contacts to fill
71 */ 77 */
72static void solve(struct mtdev_state *state, const struct mtdev_caps *caps, 78static void solve(struct mtdev_state *state, const struct mtdev *dev,
73 const int *sid, const int *sx, const int *sy, int sn, 79 const int *sid, const int *sx, const int *sy, int sn,
74 int *nid, const int *nx, const int *ny, int nn, 80 int *nid, const int *nx, const int *ny, int nn,
75 bitmask_t touch) 81 bitmask_t touch)
@@ -100,34 +106,33 @@ static void solve(struct mtdev_state *state, const struct mtdev_caps *caps,
100/* 106/*
101 * assign_tracking_id - assign tracking ids to all contacts 107 * assign_tracking_id - assign tracking ids to all contacts
102 * @state: mtdev state 108 * @state: mtdev state
103 * @caps: device capabilities 109 * @dev: device capabilities
104 * @data: array of all present contacts, to be filled 110 * @data: array of all present contacts, to be filled
105 * @prop: array of all set contacts properties 111 * @prop: array of all set contacts properties
106 * @size: number of contacts in array 112 * @size: number of contacts in array
107 * @touch: which of the contacts are actual touches 113 * @touch: which of the contacts are actual touches
108 */ 114 */
109static void assign_tracking_id(struct mtdev_state *state, 115static void assign_tracking_id(struct mtdev_state *state,
110 const struct mtdev_caps *caps, 116 const struct mtdev *dev,
111 struct mtdev_slot *data, bitmask_t *prop, 117 struct mtdev_slot *data, bitmask_t *prop,
112 int size, bitmask_t touch) 118 int size, bitmask_t touch)
113{ 119{
114 int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0; 120 int sid[DIM_FINGER], sx[DIM_FINGER], sy[DIM_FINGER], sn = 0;
115 int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i; 121 int nid[DIM_FINGER], nx[DIM_FINGER], ny[DIM_FINGER], i;
116 foreach_bit(i, state->used) { 122 foreach_bit(i, state->used) {
117 sid[sn] = state->data[i].abs[MTDEV_TRACKING_ID]; 123 sid[sn] = state->data[i].tracking_id;
118 sx[sn] = state->data[i].abs[MTDEV_POSITION_X]; 124 sx[sn] = state->data[i].position_x;
119 sy[sn] = state->data[i].abs[MTDEV_POSITION_Y]; 125 sy[sn] = state->data[i].position_y;
120 sn++; 126 sn++;
121 } 127 }
122 for (i = 0; i < size; i++) { 128 for (i = 0; i < size; i++) {
123 nx[i] = data[i].abs[MTDEV_POSITION_X]; 129 nx[i] = data[i].position_x;
124 ny[i] = data[i].abs[MTDEV_POSITION_Y]; 130 ny[i] = data[i].position_y;
125 } 131 }
126 solve(state, caps, sid, sx, sy, sn, nid, nx, ny, size, touch); 132 solve(state, dev, sid, sx, sy, sn, nid, nx, ny, size, touch);
127 for (i = 0; i < size; i++) { 133 for (i = 0; i < size; i++) {
128 data[i].abs[MTDEV_TRACKING_ID] = 134 data[i].tracking_id = GETBIT(touch, i) ? nid[i] : MT_ID_NULL;
129 GETBIT(touch, i) ? nid[i] : MT_ID_NULL; 135 SETBIT(prop[i], mtdev_abs2mt(ABS_MT_TRACKING_ID));
130 prop[i] |= BITMASK(MTDEV_TRACKING_ID);
131 } 136 }
132} 137}
133 138
@@ -157,9 +162,7 @@ static int process_typeA(struct mtdev_state *state,
157 case EV_SYN: 162 case EV_SYN:
158 switch (ev.code) { 163 switch (ev.code) {
159 case SYN_MT_REPORT: 164 case SYN_MT_REPORT:
160 if (size < DIM_FINGER && 165 if (size < DIM_FINGER && isfilled(prop[size]))
161 GETBIT(prop[size], MTDEV_POSITION_X) &&
162 GETBIT(prop[size], MTDEV_POSITION_Y))
163 size++; 166 size++;
164 if (size < DIM_FINGER) 167 if (size < DIM_FINGER)
165 prop[size] = 0; 168 prop[size] = 0;
@@ -178,8 +181,8 @@ static int process_typeA(struct mtdev_state *state,
178 case EV_ABS: 181 case EV_ABS:
179 if (size < DIM_FINGER && mtdev_is_absmt(ev.code)) { 182 if (size < DIM_FINGER && mtdev_is_absmt(ev.code)) {
180 mtcode = mtdev_abs2mt(ev.code); 183 mtcode = mtdev_abs2mt(ev.code);
181 data[size].abs[mtcode] = ev.value; 184 set_sval(&data[size], mtcode, ev.value);
182 prop[size] |= BITMASK(mtcode); 185 SETBIT(prop[size], mtcode);
183 mtcnt++; 186 mtcnt++;
184 consumed = 1; 187 consumed = 1;
185 } 188 }
@@ -210,21 +213,22 @@ static void process_typeB(struct mtdev_state *state)
210/* 213/*
211 * filter_data - apply input filtering on new incoming data 214 * filter_data - apply input filtering on new incoming data
212 * @state: mtdev state 215 * @state: mtdev state
213 * @caps: device capabilities 216 * @dev: device capabilities
214 * @data: the incoming data to filter 217 * @data: the incoming data to filter
215 * @prop: the properties to filter 218 * @prop: the properties to filter
216 * @slot: the slot the data refers to 219 * @slot: the slot the data refers to
217 */ 220 */
218static void filter_data(const struct mtdev_state *state, 221static void filter_data(const struct mtdev_state *state,
219 const struct mtdev_caps *caps, 222 const struct mtdev *dev,
220 struct mtdev_slot *data, bitmask_t prop, 223 struct mtdev_slot *data, bitmask_t prop,
221 int slot) 224 int slot)
222{ 225{
223 int i; 226 int i;
224 foreach_bit(i, prop) { 227 foreach_bit(i, prop) {
225 int fuzz = caps->abs[i].fuzz; 228 int fuzz = mtdev_get_abs_fuzz(dev, mtdev_mt2abs(i));
226 int oldval = state->data[slot].abs[i]; 229 int oldval = get_sval(&state->data[slot], i);
227 data->abs[i] = defuzz(data->abs[i], oldval, fuzz); 230 int value = get_sval(data, i);
231 set_sval(data, i, defuzz(value, oldval, fuzz));
228 } 232 }
229} 233}
230 234
@@ -243,7 +247,7 @@ static void push_slot_changes(struct mtdev_state *state,
243 struct input_event ev; 247 struct input_event ev;
244 int i, count = 0; 248 int i, count = 0;
245 foreach_bit(i, prop) 249 foreach_bit(i, prop)
246 if (state->data[slot].abs[i] != data->abs[i]) 250 if (get_sval(&state->data[slot], i) != get_sval(data, i))
247 count++; 251 count++;
248 if (!count) 252 if (!count)
249 return; 253 return;
@@ -257,10 +261,10 @@ static void push_slot_changes(struct mtdev_state *state,
257 } 261 }
258 foreach_bit(i, prop) { 262 foreach_bit(i, prop) {
259 ev.code = mtdev_mt2abs(i); 263 ev.code = mtdev_mt2abs(i);
260 ev.value = data->abs[i]; 264 ev.value = get_sval(data, i);
261 if (state->data[slot].abs[i] != ev.value) { 265 if (get_sval(&state->data[slot], i) != ev.value) {
262 evbuf_put(&state->outbuf, &ev); 266 evbuf_put(&state->outbuf, &ev);
263 state->data[slot].abs[i] = ev.value; 267 set_sval(&state->data[slot], i, ev.value);
264 } 268 }
265 } 269 }
266} 270}
@@ -268,14 +272,14 @@ static void push_slot_changes(struct mtdev_state *state,
268/* 272/*
269 * apply_typeA_changes - parse and propagate state changes 273 * apply_typeA_changes - parse and propagate state changes
270 * @state: mtdev state 274 * @state: mtdev state
271 * @caps: device capabilities 275 * @dev: device capabilities
272 * @data: array of data to apply 276 * @data: array of data to apply
273 * @prop: array of properties to apply 277 * @prop: array of properties to apply
274 * @size: number of contacts in array 278 * @size: number of contacts in array
275 * @syn: reference to the SYN_REPORT event 279 * @syn: reference to the SYN_REPORT event
276 */ 280 */
277static void apply_typeA_changes(struct mtdev_state *state, 281static void apply_typeA_changes(struct mtdev_state *state,
278 const struct mtdev_caps *caps, 282 const struct mtdev *dev,
279 struct mtdev_slot *data, const bitmask_t *prop, 283 struct mtdev_slot *data, const bitmask_t *prop,
280 int size, const struct input_event *syn) 284 int size, const struct input_event *syn)
281{ 285{
@@ -283,11 +287,11 @@ static void apply_typeA_changes(struct mtdev_state *state,
283 bitmask_t used = 0; 287 bitmask_t used = 0;
284 int i, slot, id; 288 int i, slot, id;
285 for (i = 0; i < size; i++) { 289 for (i = 0; i < size; i++) {
286 id = data[i].abs[MTDEV_TRACKING_ID]; 290 id = data[i].tracking_id;
287 foreach_bit(slot, state->used) { 291 foreach_bit(slot, state->used) {
288 if (state->data[slot].abs[MTDEV_TRACKING_ID] != id) 292 if (state->data[slot].tracking_id != id)
289 continue; 293 continue;
290 filter_data(state, caps, &data[i], prop[i], slot); 294 filter_data(state, dev, &data[i], prop[i], slot);
291 push_slot_changes(state, &data[i], prop[i], slot, syn); 295 push_slot_changes(state, &data[i], prop[i], slot, syn);
292 SETBIT(used, slot); 296 SETBIT(used, slot);
293 id = MT_ID_NULL; 297 id = MT_ID_NULL;
@@ -304,8 +308,8 @@ static void apply_typeA_changes(struct mtdev_state *state,
304 /* clear unused slots and update slot usage */ 308 /* clear unused slots and update slot usage */
305 foreach_bit(slot, state->used & ~used) { 309 foreach_bit(slot, state->used & ~used) {
306 struct mtdev_slot tdata = state->data[slot]; 310 struct mtdev_slot tdata = state->data[slot];
307 bitmask_t tprop = BITMASK(MTDEV_TRACKING_ID); 311 bitmask_t tprop = BITMASK(mtdev_abs2mt(ABS_MT_TRACKING_ID));
308 tdata.abs[MTDEV_TRACKING_ID] = MT_ID_NULL; 312 tdata.tracking_id = MT_ID_NULL;
309 push_slot_changes(state, &tdata, tprop, slot, syn); 313 push_slot_changes(state, &tdata, tprop, slot, syn);
310 } 314 }
311 state->used = used; 315 state->used = used;
@@ -314,11 +318,11 @@ static void apply_typeA_changes(struct mtdev_state *state,
314/* 318/*
315 * convert_A_to_B - propagate a type A packet as a type B packet 319 * convert_A_to_B - propagate a type A packet as a type B packet
316 * @state: mtdev state 320 * @state: mtdev state
317 * @caps: device capabilities 321 * @dev: device capabilities
318 * @syn: reference to the SYN_REPORT event 322 * @syn: reference to the SYN_REPORT event
319 */ 323 */
320static void convert_A_to_B(struct mtdev_state *state, 324static void convert_A_to_B(struct mtdev_state *state,
321 const struct mtdev_caps *caps, 325 const struct mtdev *dev,
322 const struct input_event *syn) 326 const struct input_event *syn)
323{ 327{
324 struct mtdev_slot data[DIM_FINGER]; 328 struct mtdev_slot data[DIM_FINGER];
@@ -326,14 +330,19 @@ static void convert_A_to_B(struct mtdev_state *state,
326 int size = process_typeA(state, data, prop); 330 int size = process_typeA(state, data, prop);
327 if (size < 0) 331 if (size < 0)
328 return; 332 return;
329 if (!caps->has_abs[MTDEV_TRACKING_ID]) { 333 if (!mtdev_has_mt_event(dev, ABS_MT_TRACKING_ID)) {
330 bitmask_t touch = 0; 334 bitmask_t touch = 0;
331 int i; 335 int i;
332 for (i = 0; i < size; i++) 336 for (i = 0; i < size; i++)
333 MODBIT(touch, i, istouch(&data[i], caps)); 337 MODBIT(touch, i, istouch(&data[i], dev));
334 assign_tracking_id(state, caps, data, prop, size, touch); 338 assign_tracking_id(state, dev, data, prop, size, touch);
335 } 339 }
336 apply_typeA_changes(state, caps, data, prop, size, syn); 340 apply_typeA_changes(state, dev, data, prop, size, syn);
341}
342
343struct mtdev *mtdev_new(void)
344{
345 return calloc(1, sizeof(struct mtdev));
337} 346}
338 347
339int mtdev_init(struct mtdev *dev) 348int mtdev_init(struct mtdev *dev)
@@ -344,7 +353,7 @@ int mtdev_init(struct mtdev *dev)
344 if (!dev->state) 353 if (!dev->state)
345 return -ENOMEM; 354 return -ENOMEM;
346 for (i = 0; i < DIM_FINGER; i++) 355 for (i = 0; i < DIM_FINGER; i++)
347 dev->state->data[i].abs[MTDEV_TRACKING_ID] = MT_ID_NULL; 356 dev->state->data[i].tracking_id = MT_ID_NULL;
348 return 0; 357 return 0;
349} 358}
350 359
@@ -364,15 +373,29 @@ int mtdev_open(struct mtdev *dev, int fd)
364 return ret; 373 return ret;
365} 374}
366 375
376struct mtdev *mtdev_new_open(int fd)
377{
378 struct mtdev *dev;
379
380 dev = mtdev_new();
381 if (!dev)
382 return NULL;
383 if (!mtdev_open(dev, fd))
384 return dev;
385
386 mtdev_delete(dev);
387 return NULL;
388}
389
367void mtdev_put_event(struct mtdev *dev, const struct input_event *ev) 390void mtdev_put_event(struct mtdev *dev, const struct input_event *ev)
368{ 391{
369 struct mtdev_state *state = dev->state; 392 struct mtdev_state *state = dev->state;
370 if (ev->type == EV_SYN && ev->code == SYN_REPORT) { 393 if (ev->type == EV_SYN && ev->code == SYN_REPORT) {
371 bitmask_t head = state->outbuf.head; 394 bitmask_t head = state->outbuf.head;
372 if (dev->caps.has_slot) 395 if (mtdev_has_mt_event(dev, ABS_MT_SLOT))
373 process_typeB(state); 396 process_typeB(state);
374 else 397 else
375 convert_A_to_B(state, &dev->caps, ev); 398 convert_A_to_B(state, dev, ev);
376 if (state->outbuf.head != head) 399 if (state->outbuf.head != head)
377 evbuf_put(&state->outbuf, ev); 400 evbuf_put(&state->outbuf, ev);
378 } else { 401 } else {
@@ -380,8 +403,19 @@ void mtdev_put_event(struct mtdev *dev, const struct input_event *ev)
380 } 403 }
381} 404}
382 405
406void mtdev_close_delete(struct mtdev *dev)
407{
408 mtdev_close(dev);
409 mtdev_delete(dev);
410}
411
383void mtdev_close(struct mtdev *dev) 412void mtdev_close(struct mtdev *dev)
384{ 413{
385 free(dev->state); 414 free(dev->state);
386 memset(dev, 0, sizeof(struct mtdev)); 415 memset(dev, 0, sizeof(struct mtdev));
387} 416}
417
418void mtdev_delete(struct mtdev *dev)
419{
420 free(dev);
421}
diff --git a/src/state.h b/src/state.h
index df12139..4e98a08 100644
--- a/src/state.h
+++ b/src/state.h
@@ -37,9 +37,29 @@
37 * @abs: current values of ABS_MT axes for this slot 37 * @abs: current values of ABS_MT axes for this slot
38 */ 38 */
39struct mtdev_slot { 39struct mtdev_slot {
40 int abs[MT_ABS_SIZE]; 40 int touch_major;
41 int touch_minor;
42 int width_major;
43 int width_minor;
44 int orientation;
45 int position_x;
46 int position_y;
47 int tool_type;
48 int blob_id;
49 int tracking_id;
50 int pressure;
41}; 51};
42 52
53static inline int get_sval(const struct mtdev_slot *slot, int ix)
54{
55 return (&slot->touch_major)[ix];
56}
57
58static inline void set_sval(struct mtdev_slot *slot, int ix, int value)
59{
60 (&slot->touch_major)[ix] = value;
61}
62
43/* 63/*
44 * struct mtdev_state - MT slot parsing 64 * struct mtdev_state - MT slot parsing
45 * @inbuf: input event buffer 65 * @inbuf: input event buffer
@@ -50,10 +70,15 @@ struct mtdev_slot {
50 * @lastid: last used tracking id 70 * @lastid: last used tracking id
51 */ 71 */
52struct mtdev_state { 72struct mtdev_state {
73
74 int has_ext_abs[MT_ABS_SIZE - 11];
75 struct input_absinfo ext_abs[MT_ABS_SIZE - 11];
76
53 struct mtdev_iobuf iobuf; 77 struct mtdev_iobuf iobuf;
54 struct mtdev_evbuf inbuf; 78 struct mtdev_evbuf inbuf;
55 struct mtdev_evbuf outbuf; 79 struct mtdev_evbuf outbuf;
56 struct mtdev_slot data[DIM_FINGER]; 80 struct mtdev_slot data[DIM_FINGER];
81
57 bitmask_t used; 82 bitmask_t used;
58 bitmask_t slot; 83 bitmask_t slot;
59 bitmask_t lastid; 84 bitmask_t lastid;
diff --git a/test/mtdev-mapgen.c b/test/mtdev-mapgen.c
index 8f70998..dc1ba91 100644
--- a/test/mtdev-mapgen.c
+++ b/test/mtdev-mapgen.c
@@ -26,12 +26,24 @@
26 * 26 *
27 ****************************************************************************/ 27 ****************************************************************************/
28 28
29#include <mtdev-mapping.h> 29#define MTDEV_NO_LEGACY_API
30#include <mtdev.h>
30#include <stdio.h> 31#include <stdio.h>
31 32
32#define BIT_DEF(name) \ 33#define MT_ABS_SIZE 11
33 printf("#define MTDEV_"#name"\t%d\n", \ 34#define MT_SLOT_ABS_EVENTS { \
34 cabs2mt[ABS_MT_##name] - 1) 35 ABS_MT_TOUCH_MAJOR, \
36 ABS_MT_TOUCH_MINOR, \
37 ABS_MT_WIDTH_MAJOR, \
38 ABS_MT_WIDTH_MINOR, \
39 ABS_MT_ORIENTATION, \
40 ABS_MT_POSITION_X, \
41 ABS_MT_POSITION_Y, \
42 ABS_MT_TOOL_TYPE, \
43 ABS_MT_BLOB_ID, \
44 ABS_MT_TRACKING_ID, \
45 ABS_MT_PRESSURE, \
46}
35 47
36static unsigned int cabs2mt[ABS_CNT]; 48static unsigned int cabs2mt[ABS_CNT];
37static unsigned int cmt2abs[MT_ABS_SIZE]; 49static unsigned int cmt2abs[MT_ABS_SIZE];
@@ -63,17 +75,5 @@ int main(int argc, char *argv[])
63 for (i = 0; i < MT_ABS_SIZE; i++) 75 for (i = 0; i < MT_ABS_SIZE; i++)
64 printf(" 0x%04x,%s", cmt2abs[i], newln(i, MT_ABS_SIZE)); 76 printf(" 0x%04x,%s", cmt2abs[i], newln(i, MT_ABS_SIZE));
65 printf("};\n\n"); 77 printf("};\n\n");
66 BIT_DEF(TOUCH_MAJOR);
67 BIT_DEF(TOUCH_MINOR);
68 BIT_DEF(WIDTH_MAJOR);
69 BIT_DEF(WIDTH_MINOR);
70 BIT_DEF(ORIENTATION);
71 BIT_DEF(POSITION_X);
72 BIT_DEF(POSITION_Y);
73 BIT_DEF(TOOL_TYPE);
74 BIT_DEF(BLOB_ID);
75 BIT_DEF(TRACKING_ID);
76 BIT_DEF(PRESSURE);
77 printf("\n");
78 return 0; 78 return 0;
79} 79}