1
/*****************************************************************************
3
* grail - Gesture Recognition And Instantiation Library
5
* Copyright (C) 2010 Canonical Ltd.
7
* This program is free software: you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the
9
* Free Software Foundation, either version 3 of the License, or (at your
10
* option) any later version.
12
* This program is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public License along
18
* with this program. If not, see <http://www.gnu.org/licenses/>.
21
* Henrik Rydberg <rydberg@bitmath.org>
23
****************************************************************************/
25
#include <touch-dev.h>
32
struct touch_dev_impl {
36
touch_prop_mask_t mask[1];
37
touch_prop_t prop[DIM_TOUCH_PROP];
41
static inline int has_any_prop(const touch_prop_mask_t *mask)
46
static inline void set_prop(struct touch_dev_impl *x, int code, int value)
48
x->mask[code >> 5] |= 1U << (code & 31);
49
x->prop[code] = value;
52
static void finish_touch(struct touch_dev *dev,
53
struct touch_dev_impl *x)
55
if (x->status < 0 && dev->destroy)
56
dev->destroy(dev, x->slot);
57
if (x->status > 0 && dev->create)
58
dev->create(dev, x->slot, x->mask, x->prop);
59
if (x->status == 0 && has_any_prop(x->mask) && dev->modify)
60
dev->modify(dev, x->slot, x->mask, x->prop);
62
memset(x->mask, 0, sizeof(x->mask));
65
static void finish_packet(struct touch_dev *dev,
66
const struct input_event *syn)
68
static const touch_time_t ms = 1000;
69
touch_time_t time = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
70
finish_touch(dev, dev->impl);
75
static int handle_abs_event(struct touch_dev *dev,
76
const struct input_event *ev)
78
struct touch_dev_impl *x = dev->impl;
81
if (ev->value >= 0 && ev->value < DIM_TOUCH) {
82
if (x->slot != ev->value)
87
case ABS_MT_POSITION_X:
88
set_prop(x, TP_POS_X, ev->value);
90
case ABS_MT_POSITION_Y:
91
set_prop(x, TP_POS_Y, ev->value);
93
case ABS_MT_TOUCH_MAJOR:
94
set_prop(x, TP_TOUCH_MAJOR, ev->value);
96
case ABS_MT_TOUCH_MINOR:
97
set_prop(x, TP_TOUCH_MINOR, ev->value);
99
case ABS_MT_WIDTH_MAJOR:
100
set_prop(x, TP_WIDTH_MAJOR, ev->value);
102
case ABS_MT_WIDTH_MINOR:
103
set_prop(x, TP_WIDTH_MINOR, ev->value);
105
case ABS_MT_ORIENTATION:
106
set_prop(x, TP_ORIENTATION, ev->value);
108
case ABS_MT_PRESSURE:
109
set_prop(x, TP_PRESSURE, ev->value);
111
case ABS_MT_TRACKING_ID:
112
if (x->id[x->slot] != ev->value) {
113
if (x->id[x->slot] != MT_ID_NULL) {
115
finish_touch(dev, x);
117
if (ev->value != MT_ID_NULL)
120
x->id[x->slot] = ev->value;
127
int touch_dev_open(struct touch_dev *dev, int fd)
129
struct touch_dev_impl *x;
131
memset(dev, 0, sizeof(*dev));
132
x = calloc(1, sizeof(*x));
135
ret = mtdev_open(&x->mtdev, fd);
138
for (i = 0; i < DIM_TOUCH; i++)
139
x->id[i] = MT_ID_NULL;
147
int touch_dev_idle(struct touch_dev *dev, int fd, int ms)
149
return mtdev_idle(&dev->impl->mtdev, fd, ms);
152
int touch_dev_pull(struct touch_dev *dev, int fd)
154
struct touch_dev_impl *x = dev->impl;
155
struct input_event ev;
156
int ret, count = 0, consumed;
157
while ((ret = mtdev_get(&x->mtdev, fd, &ev, 1)) > 0) {
159
if (ev.type == EV_SYN) {
160
if (ev.code == SYN_REPORT)
161
finish_packet(dev, &ev);
163
} else if (ev.type == EV_ABS) {
164
consumed += handle_abs_event(dev, &ev);
166
if (!consumed && dev->event)
167
dev->event(dev, &ev);
170
return count > 0 ? count : ret;
173
void touch_dev_close(struct touch_dev *dev, int fd)
175
struct touch_dev_impl *x = dev->impl;
176
mtdev_close(&x->mtdev);
178
memset(dev, 0, sizeof(*dev));