1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
23 #include <sys/types.h>
28 #include <linux/input.h>
30 #include "core/GP_Debug.h"
32 #include "input/GP_EventQueue.h"
33 #include "input/GP_InputDriverLinux.h"
35 static int get_version(int fd
)
39 if (ioctl(fd
, EVIOCGVERSION
, &ver
))
42 GP_DEBUG(2, "Input version %u.%u.%u",
43 ver
>>16, (ver
>>8)&0xff, ver
&0xff);
49 * Returns size on success just as read()
51 static int get_name(int fd
, char *buf
, size_t buf_len
)
55 if ((ret
= ioctl(fd
, EVIOCGNAME(buf_len
), buf
)) <= 0)
61 static void print_name(int fd
)
65 if (GP_GetDebugLevel() < 2)
68 if (get_name(fd
, name
, sizeof(name
)) > 0)
69 GP_DEBUG(2, "Input device name '%s'", name
);
72 static void try_load_callibration(struct GP_InputDriverLinux
*self
)
77 ioctl(self
->fd
, EVIOCGBIT(EV_ABS
, EV_ABS
), &bit
);
80 GP_DEBUG(3, "Not an absolute input device");
84 if (!ioctl(self
->fd
, EVIOCGABS(ABS_X
), abs
)) {
85 GP_DEBUG(3, "ABS X = <%i,%i> Fuzz %i Flat %i",
86 abs
[1], abs
[2], abs
[3], abs
[4]);
87 self
->abs_x_max
= abs
[2];
90 if (!ioctl(self
->fd
, EVIOCGABS(ABS_Y
), abs
)) {
91 GP_DEBUG(3, "ABS Y = <%i,%i> Fuzz %i Flat %i",
92 abs
[1], abs
[2], abs
[3], abs
[4]);
93 self
->abs_y_max
= abs
[2];
96 if (!ioctl(self
->fd
, EVIOCGABS(ABS_PRESSURE
), abs
)) {
97 GP_DEBUG(3, "ABS P = <%i,%i> Fuzz %i Flat %i",
98 abs
[1], abs
[2], abs
[3], abs
[4]);
99 self
->abs_press_max
= abs
[2];
103 struct GP_InputDriverLinux
*GP_InputDriverLinuxOpen(const char *path
)
106 struct GP_InputDriverLinux
*ret
;
108 GP_DEBUG(2, "Opening '%s'", path
);
110 fd
= open(path
, O_RDONLY
| O_NONBLOCK
);
113 GP_DEBUG(1, "Failed to open '%s': %s", path
, strerror(errno
));
117 if (get_version(fd
)) {
118 GP_DEBUG(1, "Failed ioctl(), not a input device?");
124 ret
= malloc(sizeof(struct GP_InputDriverLinux
));
127 GP_DEBUG(1, "Malloc failed :(");
143 ret
->abs_pen_flag
= 1;
145 try_load_callibration(ret
);
150 void GP_InputDriverLinuxClose(struct GP_InputDriverLinux
*self
)
152 GP_DEBUG(1, "Closing input device");
153 print_name(self
->fd
);
159 static void input_rel(struct GP_InputDriverLinux
*self
, struct input_event
*ev
)
161 GP_DEBUG(4, "Relative event");
165 self
->rel_x
= ev
->value
;
169 self
->rel_y
= ev
->value
;
173 GP_DEBUG(3, "Unhandled code %i", ev
->code
);
177 static void input_abs(struct GP_InputDriverLinux
*self
, struct input_event
*ev
)
179 GP_DEBUG(4, "Absolute event");
183 self
->abs_x
= ev
->value
;
184 self
->abs_flag_x
= 1;
185 GP_DEBUG(4, "ABS X %i", ev
->value
);
188 self
->abs_y
= ev
->value
;
189 self
->abs_flag_y
= 1;
190 GP_DEBUG(4, "ABS Y %i", ev
->value
);
193 self
->abs_press
= ev
->value
;
196 GP_DEBUG(3, "Unhandled code %i", ev
->code
);
200 static void input_key(struct GP_InputDriverLinux
*self
,
201 struct GP_EventQueue
*event_queue
,
202 struct input_event
*ev
)
204 GP_DEBUG(4, "Key event");
207 * We need to postpone btn touch down until
208 * we read new coordinates for cursor.
210 if (ev
->code
== BTN_TOUCH
) {
212 self
->abs_pen_flag
= 1;
217 GP_EventQueuePushKey(event_queue
, ev
->code
, ev
->value
, NULL
);
220 static void do_sync(struct GP_InputDriverLinux
*self
,
221 struct GP_EventQueue
*event_queue
)
223 if (self
->rel_flag
) {
225 GP_EventQueuePushRel(event_queue
, self
->rel_x
,
231 if (self
->abs_flag_x
|| self
->abs_flag_y
) {
232 uint32_t x
= 0, y
= 0, x_max
= 0, y_max
= 0;
234 if (self
->abs_flag_x
) {
236 if (self
->abs_x
> self
->abs_x_max
)
237 self
->abs_x
= self
->abs_x_max
;
243 x_max
= self
->abs_x_max
;
245 self
->abs_flag_x
= 0;
248 if (self
->abs_flag_y
) {
250 if (self
->abs_y
> self
->abs_y_max
)
251 self
->abs_y
= self
->abs_y_max
;
257 y_max
= self
->abs_y_max
;
259 self
->abs_flag_y
= 0;
262 GP_EventQueuePushAbs(event_queue
, x
, y
, self
->abs_press
,
263 x_max
, y_max
, self
->abs_press_max
, NULL
);
267 if (self
->abs_pen_flag
) {
268 GP_EventQueuePushKey(event_queue
, BTN_TOUCH
, 1, NULL
);
269 self
->abs_pen_flag
= 0;
274 static void input_syn(struct GP_InputDriverLinux
*self
,
275 struct GP_EventQueue
*event_queue
,
276 struct input_event
*ev
)
278 GP_DEBUG(4, "Sync event");
282 do_sync(self
, event_queue
);
285 GP_DEBUG(3, "Unhandled code %i", ev
->code
);
289 int GP_InputDriverLinuxRead(struct GP_InputDriverLinux
*self
,
290 struct GP_EventQueue
*event_queue
)
292 struct input_event ev
;
295 ret
= read(self
->fd
, &ev
, sizeof(ev
));
297 if (ret
== -1 && errno
== EAGAIN
)
305 input_rel(self
, &ev
);
308 input_abs(self
, &ev
);
311 input_key(self
, event_queue
, &ev
);
314 input_syn(self
, event_queue
, &ev
);
317 GP_DEBUG(3, "Unhandled type %i", ev
.type
);