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