1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Shane Volpe <shanevolpe@gmail.com
8
9 Based on usb1x00_ts writen by:
10 Denis Oliver Kropp <dok@directfb.org>,
11 Andreas Hundt <andi@fischlustig.de>,
12 Sven Neumann <neo@directfb.org> and
13 Ville Syrj��<syrjala@sci.fi>.
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 2 of the License, or (at your option) any later version.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, write to the
27 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29 */
30
31 #include <config.h>
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include <tslib.h>
38
39 #include <directfb.h>
40
41 #include <core/coredefs.h>
42 #include <core/coretypes.h>
43
44 #include <core/input.h>
45
46 #include <direct/mem.h>
47 #include <direct/messages.h>
48 #include <direct/thread.h>
49
50 #include <core/input_driver.h>
51
52 #include <misc/conf.h>
53
54 DFB_INPUT_DRIVER( tslib )
55
56 typedef struct {
57 CoreInputDevice *device;
58 DirectThread *thread;
59 struct tsdev *ts;
60 } tslibData;
61
62 #define MAX_TSLIB_DEVICES 16
63
64 static int num_devices = 0;
65 static char *device_names[MAX_TSLIB_DEVICES];
66
67 static void *
tslibEventThread(DirectThread * thread,void * driver_data)68 tslibEventThread( DirectThread *thread, void *driver_data )
69 {
70 tslibData *data = (tslibData *) driver_data;
71 struct ts_sample ts_event;
72 int readlen;
73 int old_x = -1;
74 int old_y = -1;
75 unsigned int old_pressure = 0;
76
77 while ((readlen = ts_read( data->ts, &ts_event, 1 )) >= 0) {
78 DFBInputEvent evt;
79
80 direct_thread_testcancel( thread );
81
82 if (readlen < 1)
83 continue;
84
85 if (ts_event.pressure) {
86 if (ts_event.x != old_x) {
87 evt.type = DIET_AXISMOTION;
88 evt.flags = DIEF_AXISABS;
89 evt.axis = DIAI_X;
90 evt.axisabs = ts_event.x;
91
92 dfb_input_dispatch( data->device, &evt );
93
94 old_x = ts_event.x;
95 }
96
97 if (ts_event.y != old_y) {
98 evt.type = DIET_AXISMOTION;
99 evt.flags = DIEF_AXISABS;
100 evt.axis = DIAI_Y;
101 evt.axisabs = ts_event.y;
102
103 dfb_input_dispatch( data->device, &evt );
104
105 old_y = ts_event.y;
106 }
107 }
108
109 if (!ts_event.pressure != !old_pressure) {
110 evt.type = ts_event.pressure ? DIET_BUTTONPRESS : DIET_BUTTONRELEASE;
111 evt.flags = DIEF_NONE;
112 evt.button = DIBI_LEFT;
113
114 dfb_input_dispatch( data->device, &evt );
115
116 old_pressure = ts_event.pressure;
117 }
118 }
119
120 if (readlen < 0)
121 D_ERROR( "tslib Input thread died\n" );
122
123 return NULL;
124 }
125
126 static bool
check_device(const char * device)127 check_device( const char *device )
128 {
129 struct tsdev *ts;
130
131 ts = ts_open( device, 0 );
132 if (!ts)
133 return false;
134
135 if (ts_config( ts )) {
136 ts_close( ts );
137 return false;
138 }
139
140 ts_close( ts );
141
142 return true;
143 }
144
145 /* exported symbols */
146
147 static int
driver_get_available(void)148 driver_get_available(void)
149 {
150 int i;
151 char *tsdev;
152
153 /* Use the devices specified in the configuration. */
154 if (fusion_vector_has_elements( &dfb_config->tslib_devices )) {
155 const char *device;
156
157 fusion_vector_foreach (device, i, dfb_config->tslib_devices) {
158 if (num_devices >= MAX_TSLIB_DEVICES)
159 break;
160
161 if (check_device( device ))
162 device_names[num_devices++] = D_STRDUP( device );
163 }
164
165 return num_devices;
166 }
167
168 /* Check for environment variable. */
169 tsdev = getenv( "TSLIB_TSDEVICE" );
170 if (tsdev && check_device( tsdev ))
171 device_names[num_devices++] = D_STRDUP( tsdev );
172
173 /* Try to guess some (more) devices. */
174 for (i = 0; i < MAX_TSLIB_DEVICES; i++) {
175 char buf[32];
176
177 if (num_devices >= MAX_TSLIB_DEVICES)
178 break;
179
180 snprintf( buf, 32, "/dev/input/tslib%d", i );
181
182 /* Already handled above. */
183 if (tsdev && !strcmp( tsdev, buf ))
184 continue;
185
186 if (check_device( buf ))
187 device_names[num_devices++] = D_STRDUP( buf );
188 }
189
190 return num_devices;
191 }
192
193 static void
driver_get_info(InputDriverInfo * info)194 driver_get_info( InputDriverInfo *info )
195 {
196 /* fill driver info structure */
197
198 snprintf( info->name,
199 DFB_INPUT_DRIVER_INFO_NAME_LENGTH,
200 "tslib Input Driver" );
201
202 snprintf( info->vendor,
203 DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH,
204 "tslib" );
205
206 info->version.major = 0;
207 info->version.minor = 1;
208 }
209
210 static DFBResult
driver_open_device(CoreInputDevice * device,unsigned int number,InputDeviceInfo * info,void ** driver_data)211 driver_open_device( CoreInputDevice *device,
212 unsigned int number,
213 InputDeviceInfo *info,
214 void **driver_data )
215 {
216 tslibData *data;
217 struct tsdev *ts;
218
219 /* open device */
220 ts = ts_open( device_names[number], 0 );
221 if (!ts) {
222 D_ERROR( "DirectFB/tslib: Error opening `%s'!\n", device_names[number] );
223 return DFB_INIT;
224 }
225
226 /* configure device */
227 if (ts_config( ts )) {
228 D_ERROR( "DirectFB/tslib: Error configuring `%s'!\n", device_names[number] );
229 ts_close( ts );
230 return DFB_INIT;
231 }
232
233 /* fill device info structure */
234 snprintf( info->desc.name,
235 DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "tslib touchscreen %d", number );
236
237 snprintf( info->desc.vendor,
238 DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "tslib" );
239
240 info->prefered_id = DIDID_MOUSE;
241
242 info->desc.type = DIDTF_MOUSE;
243 info->desc.caps = DICAPS_AXES | DICAPS_BUTTONS;
244 info->desc.max_axis = DIAI_Y;
245 info->desc.max_button = DIBI_LEFT;
246
247 /* allocate and fill private data */
248 data = D_CALLOC( 1, sizeof(tslibData) );
249 if (!data) {
250 ts_close( ts );
251 return D_OOM();
252 }
253
254 data->ts = ts;
255 data->device = device;
256
257 /* start input thread */
258 data->thread = direct_thread_create( DTT_INPUT, tslibEventThread, data, "tslib Input" );
259
260 /* set private data pointer */
261 *driver_data = data;
262
263 return DFB_OK;
264 }
265
266 /*
267 * Fetch one entry from the device's keymap if supported.
268 */
269 static DFBResult
driver_get_keymap_entry(CoreInputDevice * device,void * driver_data,DFBInputDeviceKeymapEntry * entry)270 driver_get_keymap_entry( CoreInputDevice *device,
271 void *driver_data,
272 DFBInputDeviceKeymapEntry *entry )
273 {
274 return DFB_UNSUPPORTED;
275 }
276
277 static void
driver_close_device(void * driver_data)278 driver_close_device( void *driver_data )
279 {
280 tslibData *data = (tslibData*) driver_data;
281
282 /* stop input thread */
283 direct_thread_cancel( data->thread );
284 direct_thread_join( data->thread );
285 direct_thread_destroy( data->thread );
286
287 /* close device */
288 ts_close( data->ts );
289
290 /* free private data */
291 D_FREE( data );
292 }
293