Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / linux / tslib.c
CommitLineData
a09e091a
JB
1/*
2 * TSLIB based touchscreen driver for KDrive
3 * Porting to new input API and event queueing by Daniel Stone.
4 * Derived from ts.c by Keith Packard
5 * Derived from ps2.c by Jim Gettys
6 *
7 * Copyright © 1999 Keith Packard
8 * Copyright © 2000 Compaq Computer Corporation
9 * Copyright © 2002 MontaVista Software Inc.
10 * Copyright © 2005 OpenedHand Ltd.
11 * Copyright © 2006 Nokia Corporation
12 *
13 * Permission to use, copy, modify, distribute, and sell this software and its
14 * documentation for any purpose is hereby granted without fee, provided that
15 * the above copyright notice appear in all copies and that both that
16 * copyright notice and this permission notice appear in supporting
17 * documentation, and that the name of the authors and/or copyright holders
18 * not be used in advertising or publicity pertaining to distribution of the
19 * software without specific, written prior permission. The authors and/or
20 * copyright holders make no representations about the suitability of this
21 * software for any purpose. It is provided "as is" without express or
22 * implied warranty.
23 *
24 * THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
25 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
26 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
27 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
29 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 */
32
33#ifdef HAVE_KDRIVE_CONFIG_H
34#include <kdrive-config.h>
35#endif
36
37#include <X11/X.h>
38#include <X11/Xproto.h>
39#include <X11/Xpoll.h>
40#include "inputstr.h"
41#include "scrnintstr.h"
42#include "kdrive.h"
43#include <sys/ioctl.h>
44#include <tslib.h>
45#include <dirent.h>
46#include <linux/input.h>
47
48struct TslibPrivate {
49 int fd;
50 int lastx, lasty;
51 struct tsdev *tsDev;
52 void (*raw_event_hook) (int x, int y, int pressure, void *closure);
53 void *raw_event_closure;
54 int phys_screen;
55};
56
57static void
58TsRead(int fd, void *closure)
59{
60 KdPointerInfo *pi = closure;
61 struct TslibPrivate *private = pi->driverPrivate;
62 struct ts_sample event;
63 long x = 0, y = 0;
64 unsigned long flags;
65
66 if (private->raw_event_hook) {
67 while (ts_read_raw(private->tsDev, &event, 1) == 1)
68 private->raw_event_hook(event.x, event.y, event.pressure,
69 private->raw_event_closure);
70 return;
71 }
72
73 while (ts_read(private->tsDev, &event, 1) == 1) {
74 if (event.pressure) {
75 flags = KD_BUTTON_1;
76
77 /*
78 * Here we test for the touch screen driver actually being on the
79 * touch screen, if it is we send absolute coordinates. If not,
80 * then we send delta's so that we can track the entire vga screen.
81 */
82 if (KdCurScreen == private->phys_screen) {
83 x = event.x;
84 y = event.y;
85 }
86 else {
87 flags |= KD_MOUSE_DELTA;
88 if ((private->lastx == 0) || (private->lasty == 0)) {
89 x = event.x;
90 y = event.y;
91 }
92 else {
93 x = event.x - private->lastx;
94 y = event.y - private->lasty;
95 }
96 }
97 private->lastx = event.x;
98 private->lasty = event.y;
99 }
100 else {
101 flags = 0;
102 x = private->lastx;
103 y = private->lasty;
104 }
105
106 KdEnqueuePointerEvent(pi, flags, x, y, event.pressure);
107 }
108}
109
110static Status
111TslibEnable(KdPointerInfo * pi)
112{
113 struct TslibPrivate *private = pi->driverPrivate;
114
115 private->raw_event_hook = NULL;
116 private->raw_event_closure = NULL;
117 if (!pi->path) {
118 pi->path = strdup("/dev/input/touchscreen0");
119 ErrorF("[tslib/TslibEnable] no device path given, trying %s\n",
120 pi->path);
121 }
122
123 private->tsDev = ts_open(pi->path, 0);
124 if (!private->tsDev) {
125 ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path);
126 return BadAlloc;
127 }
128
129 if (ts_config(private->tsDev)) {
130 ErrorF("[tslib/TslibEnable] failed to load configuration\n");
131 ts_close(private->tsDev);
132 private->tsDev = NULL;
133 return BadValue;
134 }
135
136 private->fd = ts_fd(private->tsDev);
137
138 KdRegisterFd(private->fd, TsRead, pi);
139
140 return Success;
141}
142
143static void
144TslibDisable(KdPointerInfo * pi)
145{
146 struct TslibPrivate *private = pi->driverPrivate;
147
148 if (private->fd)
149 KdUnregisterFd(pi, private->fd, TRUE);
150
151 if (private->tsDev)
152 ts_close(private->tsDev);
153
154 private->fd = 0;
155 private->tsDev = NULL;
156}
157
158static Status
159TslibInit(KdPointerInfo * pi)
160{
161 struct TslibPrivate *private = NULL;
162
163 if (!pi || !pi->dixdev)
164 return !Success;
165
166 pi->driverPrivate = (struct TslibPrivate *)
167 calloc(sizeof(struct TslibPrivate), 1);
168 if (!pi->driverPrivate)
169 return !Success;
170
171 private = pi->driverPrivate;
172 /* hacktastic */
173 private->phys_screen = 0;
174 pi->nAxes = 3;
175 pi->name = strdup("Touchscreen");
176 pi->inputClass = KD_TOUCHSCREEN;
177
178 return Success;
179}
180
181static void
182TslibFini(KdPointerInfo * pi)
183{
184 free(pi->driverPrivate);
185 pi->driverPrivate = NULL;
186}
187
188KdPointerDriver TsDriver = {
189 "tslib",
190 TslibInit,
191 TslibEnable,
192 TslibDisable,
193 TslibFini,
194 NULL,
195};