c1e1f08076302c3d919b0042f410a19dad133893
[profile/ivi/ecore.git] / src / lib / ecore_fb / ecore_fb_ts.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef HAVE_TSLIB
6 # include <tslib.h>
7 # include <errno.h>
8 #endif
9
10 #include "Ecore_Fb.h"
11 #include "ecore_fb_private.h"
12
13 typedef struct _Ecore_Fb_Ts_Event Ecore_Fb_Ts_Event;
14 typedef struct _Ecore_Fb_Ts_Calibrate Ecore_Fb_Ts_Calibrate;
15 typedef struct _Ecore_Fb_Ts_Backlight Ecore_Fb_Ts_Backlight;
16 typedef struct _Ecore_Fb_Ts_Contrast Ecore_Fb_Ts_Contrast;
17 typedef struct _Ecore_Fb_Ts_Led Ecore_Fb_Ts_Led;
18 typedef struct _Ecore_Fb_Ts_Flite Ecore_Fb_Ts_Flite;
19
20 struct _Ecore_Fb_Ts_Event
21 {
22    unsigned short pressure;
23    unsigned short x;
24    unsigned short y;
25    unsigned short _unused; 
26 };
27
28 struct _Ecore_Fb_Ts_Calibrate
29 {
30    int xscale;
31    int xtrans;
32    int yscale;
33    int ytrans;
34    int xyswap;
35 };
36
37 struct _Ecore_Fb_Ts_Backlight
38 {
39    int           on;
40    unsigned char brightness;
41 };
42
43 struct _Ecore_Fb_Ts_Contrast
44 {
45    unsigned char contrast;
46 };
47
48 struct _Ecore_Fb_Ts_Led
49 {
50    unsigned char on;
51    unsigned char blink_time;
52    unsigned char on_time;
53    unsigned char off_time;
54 };
55
56 struct _Ecore_Fb_Ts_Flite
57 {
58    unsigned char mode;
59    unsigned char pwr;
60    unsigned char brightness;
61 };
62
63 static Eina_Bool _ecore_fb_ts_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
64 static int _ecore_fb_ts_fd = -1;
65 static int _ecore_fb_ts_event_byte_count = 0;
66 static int _ecore_fb_ts_apply_cal = 0;
67 static Ecore_Fb_Ts_Event _ecore_fb_ts_event;
68 static Ecore_Fb_Ts_Calibrate _ecore_fb_ts_cal = {1,1,0,0,0};
69 static Ecore_Fd_Handler *_ecore_fb_ts_fd_handler_handle = NULL;
70
71 #ifdef HAVE_TSLIB
72 struct tsdev *_ecore_fb_tslib_tsdev = NULL;
73 struct ts_sample _ecore_fb_tslib_event;
74 #endif
75
76 static double _ecore_fb_double_click_time = 0.25;
77
78 EAPI int
79 ecore_fb_ts_init(void)
80 {
81 #ifdef HAVE_TSLIB
82    char *tslib_tsdevice = NULL;
83    if ( (tslib_tsdevice = getenv("TSLIB_TSDEVICE")) )
84     {
85         printf( "ECORE_FB: TSLIB_TSDEVICE = '%s'\n", tslib_tsdevice );
86         _ecore_fb_tslib_tsdev = ts_open( tslib_tsdevice, 1 ); /* 1 = nonblocking, 0 = blocking */
87
88         if ( !_ecore_fb_tslib_tsdev )
89         {
90             printf( "ECORE_FB: Can't ts_open (%s)\n", strerror( errno ) );
91             return 0;
92         }
93
94         if ( ts_config( _ecore_fb_tslib_tsdev ) )
95         {
96             printf( "ECORE_FB: Can't ts_config (%s)\n", strerror( errno ) );
97             return 0;
98         }
99         _ecore_fb_ts_fd = ts_fd( _ecore_fb_tslib_tsdev );
100         if ( _ecore_fb_ts_fd < 0 )
101         {
102             printf( "ECORE_FB: Can't open touchscreen (%s)\n", strerror( errno ) );
103             return 0;
104         }
105     }
106 #else
107    _ecore_fb_ts_fd = open("/dev/touchscreen/0", O_RDONLY);
108 #endif
109    if (_ecore_fb_ts_fd >= 0)
110      {
111         _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ts_fd, 
112                                                                    ECORE_FD_READ,
113                                                                    _ecore_fb_ts_fd_handler, NULL,
114                                                                    NULL, NULL);
115         if (!_ecore_fb_ts_fd_handler_handle)
116           {
117              close(_ecore_fb_ts_fd);
118              return 0;
119           }
120         // FIXME _ecore_fb_kbd_fd = open("/dev/touchscreen/key", O_RDONLY);
121         return 1;
122      }
123    return 0;
124 }
125
126 EAPI void
127 ecore_fb_ts_shutdown(void)
128 {
129    if (_ecore_fb_ts_fd_handler_handle)
130      ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle);
131    if (_ecore_fb_ts_fd >= 0) close(_ecore_fb_ts_fd);
132    _ecore_fb_ts_fd = -1;
133    _ecore_fb_ts_fd_handler_handle = NULL;
134 }
135
136 /**
137  * @defgroup Ecore_FB_Calibrate_Group Framebuffer Calibration Functions
138  *
139  * Functions that calibrate the screen.
140  */
141   
142   
143 /**
144  * Calibrates the touschreen using the given parameters.
145  * @param   xscale X scaling, where 256 = 1.0
146  * @param   xtrans X translation.
147  * @param   yscale Y scaling.
148  * @param   ytrans Y translation.
149  * @param   xyswap Swap X & Y flag.
150  * @ingroup Ecore_FB_Calibrate_Group
151  */
152 EAPI void
153 ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap)
154 {
155    Ecore_Fb_Ts_Calibrate cal;
156    
157    if (_ecore_fb_ts_fd < 0) return;
158    cal.xscale = xscale;
159    cal.xtrans = xtrans;
160    cal.yscale = yscale;
161    cal.ytrans = ytrans;
162    cal.xyswap = xyswap;
163    if (ioctl(_ecore_fb_ts_fd, TS_SET_CAL, (void *)&cal))
164      {
165         _ecore_fb_ts_cal = cal;
166         _ecore_fb_ts_apply_cal = 1;
167         
168      }
169 }
170
171 /**
172  * Retrieves the calibration parameters of the touchscreen.
173  * @param   xscale Pointer to an integer in which to store the X scaling.
174  *                 Note that 256 = 1.0.
175  * @param   xtrans Pointer to an integer in which to store the X translation.
176  * @param   yscale Pointer to an integer in which to store the Y scaling.
177  * @param   ytrans Pointer to an integer in which to store the Y translation.
178  * @param   xyswap Pointer to an integer in which to store the Swap X & Y flag.
179  * @ingroup Ecore_FB_Calibrate_Group
180  */
181 EAPI void
182 ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap)
183 {
184    Ecore_Fb_Ts_Calibrate cal;
185    
186    if (_ecore_fb_ts_fd < 0) return;
187    if (!_ecore_fb_ts_apply_cal)
188      {
189         if (ioctl(_ecore_fb_ts_fd, TS_GET_CAL, (void *)&cal))
190           _ecore_fb_ts_cal = cal;
191         
192      }
193    else
194      cal = _ecore_fb_ts_cal;
195    if (xscale) *xscale = cal.xscale;
196    if (xtrans) *xtrans = cal.xtrans;
197    if (yscale) *yscale = cal.yscale;
198    if (ytrans) *ytrans = cal.ytrans;
199    if (xyswap) *xyswap = cal.xyswap;
200 }
201
202 static Eina_Bool
203 _ecore_fb_ts_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
204 {
205    static int prev_x = 0, prev_y = 0, prev_pressure = 0;
206    static double last_time = 0;
207    static double last_last_time = 0;
208    int v = 0;
209    
210    do
211      {
212         int x, y, pressure;
213         int num;
214         char *ptr;
215         double t;
216         int did_triple = 0;
217
218 #ifdef HAVE_TSLIB
219         if (_ecore_fb_ts_apply_cal)
220           num = ts_read_raw(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1);
221         else
222           num = ts_read(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1);
223         if (num != 1) return 1; /* no more samples at this time */
224         x = _ecore_fb_tslib_event.x;
225         y = _ecore_fb_tslib_event.y;
226         pressure = _ecore_fb_tslib_event.pressure;
227         v = 1; /* loop, there might be more samples */
228         t = ecore_time_get();
229 #else
230         ptr = (char *)&(_ecore_fb_ts_event);
231         ptr += _ecore_fb_ts_event_byte_count;
232         num = sizeof(Ecore_Fb_Ts_Event) - _ecore_fb_ts_event_byte_count;
233         v = read(_ecore_fb_ts_fd, ptr, num);
234         if (v < 0) return 1;
235         _ecore_fb_ts_event_byte_count += v;
236         if (v < num) return 1;
237         _ecore_fb_ts_event_byte_count = 0;
238        if (_ecore_fb_ts_apply_cal)
239           {
240              x = ((_ecore_fb_ts_cal.xscale * _ecore_fb_ts_event.x) >> 8) + _ecore_fb_ts_cal.xtrans;
241              y = ((_ecore_fb_ts_cal.yscale * _ecore_fb_ts_event.y) >> 8) + _ecore_fb_ts_cal.ytrans;
242           }
243         else
244           {
245              x = _ecore_fb_ts_event.x;
246              y = _ecore_fb_ts_event.y;
247           }
248         pressure = _ecore_fb_ts_event.pressure;
249 #endif   
250         /* add event to queue */
251         /* always add a move event */
252         if ((pressure) || (prev_pressure))
253           {
254              /* MOVE: mouse is down and was */
255              Ecore_Fb_Event_Mouse_Move *e;
256              
257              e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move));
258              if (!e) goto retry;
259              e->x = x;
260              e->y = y;
261              ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, e, NULL, NULL);
262           }
263         if ((pressure) && (!prev_pressure))
264           {
265              /* DOWN: mouse is down, but was not now */
266              Ecore_Fb_Event_Mouse_Button_Down *e;
267              
268              e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
269              if (!e) goto retry;
270              e->x = x;
271              e->y = y;
272              e->button = 1;
273              if ((t - last_time) <= _ecore_fb_double_click_time)
274                e->double_click = 1;
275              if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time))
276                {
277                   did_triple = 1;
278                   e->triple_click = 1;
279                }
280              ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
281           }
282         else if ((!pressure) && (prev_pressure))
283           {
284              /* UP: mouse was down, but is not now */
285              Ecore_Fb_Event_Mouse_Button_Up *e;
286              
287              e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up));
288              if (!e) goto retry;
289              e->x = prev_x;
290              e->y = prev_y;
291              e->button = 1;
292              ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
293           }
294         if (did_triple)
295           {
296              last_time = 0;
297              last_last_time = 0;
298           }
299         else
300           {
301              last_last_time = last_time;
302              last_time = t;
303           }
304         retry:       
305         prev_x = x;
306         prev_y = y;
307         prev_pressure = pressure;
308      }
309    while (v > 0);
310    return 1;
311 }
312