]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/touch/arm/ipaq/v2_0/src/ipaq_ts.c
Initial revision
[karo-tx-redboot.git] / packages / devs / touch / arm / ipaq / v2_0 / src / ipaq_ts.c
1 //==========================================================================
2 //
3 //      ipaq_ts.c
4 //
5 //      Touchscreen driver for the Compaq iPAQ
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    gthomas
44 // Contributors: gthomas
45 // Date:         2001-03-05
46 // Purpose:      
47 // Description:  Touchscreen driver for Compaq IPAQ
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53
54 #include <pkgconf/devs_touch_ipaq.h>
55
56 #include <cyg/kernel/kapi.h>
57 #include <cyg/hal/hal_io.h>
58 #include <cyg/hal/hal_arch.h>
59 #include <cyg/hal/drv_api.h>
60 #include <cyg/hal/hal_intr.h>
61 #include <cyg/hal/hal_sa11x0.h>
62 #include <cyg/hal/ipaq.h>
63 #include <cyg/infra/cyg_type.h>
64 #include <cyg/infra/cyg_ass.h>
65
66 #include <cyg/fileio/fileio.h>  // For select() functionality
67 static cyg_selinfo      ts_select_info; 
68 static cyg_bool         ts_select_active;
69
70 #include <cyg/io/devtab.h>
71 #include <cyg/hal/atmel_support.h>
72
73 // Functions in this module
74
75 static Cyg_ErrNo ts_read(cyg_io_handle_t handle, 
76                          void *buffer, 
77                          cyg_uint32 *len);
78 static cyg_bool  ts_select(cyg_io_handle_t handle, 
79                            cyg_uint32 which, 
80                            cyg_addrword_t info);
81 static Cyg_ErrNo ts_set_config(cyg_io_handle_t handle, 
82                                cyg_uint32 key, 
83                                const void *buffer, 
84                                cyg_uint32 *len);
85 static Cyg_ErrNo ts_get_config(cyg_io_handle_t handle, 
86                                cyg_uint32 key, 
87                                void *buffer, 
88                                cyg_uint32 *len);
89 static bool      ts_init(struct cyg_devtab_entry *tab);
90 static Cyg_ErrNo ts_lookup(struct cyg_devtab_entry **tab, 
91                            struct cyg_devtab_entry *st, 
92                            const char *name);
93
94 CHAR_DEVIO_TABLE(ipaq_ts_handlers,
95                  NULL,                                   // Unsupported write() function
96                  ts_read,
97                  ts_select,
98                  ts_get_config,
99                  ts_set_config);
100
101 CHAR_DEVTAB_ENTRY(ipaq_ts_device,
102                   CYGDAT_DEVS_TOUCH_IPAQ_NAME,
103                   NULL,                                   // Base device name
104                   &ipaq_ts_handlers,
105                   ts_init,
106                   ts_lookup,
107                   NULL);                                  // Private data pointer
108
109 struct _event {
110     short button_state;
111     short xPos, yPos;
112     short _unused;
113 };
114 #define MAX_EVENTS CYGNUM_DEVS_TOUCH_IPAQ_EVENT_BUFFER_SIZE
115 static int   num_events;
116 static int   _event_put, _event_get;
117 static bool  pen_down = false;
118 static struct _event _events[MAX_EVENTS];
119
120 static bool _is_open = false;
121 #ifdef DEBUG_RAW_EVENTS
122 static unsigned char _ts_buf[512];
123 static int _ts_buf_ptr = 0;
124 #endif
125
126 //
127 // Note: this routine is called from the Atmel processing DSR
128 //
129 static void
130 ts_handler(atmel_pkt *pkt)
131 {
132     unsigned char *dp = pkt->data;
133     static short lastX, lastY;
134     short x, y;
135     struct _event *ev;
136
137 #ifdef DEBUG_RAW_EVENTS
138     memcpy(&_ts_buf[_ts_buf_ptr], pkt->data, 8);
139     _ts_buf_ptr += 8;
140     if (_ts_buf_ptr == 512) {
141         diag_printf("TS handler\n");
142         diag_dump_buf(_ts_buf, 512);
143         _ts_buf_ptr = 0;
144     }
145 #endif
146     // Try and interpret the mouse data
147     if ((dp[0] & 0x0F) == 0) {
148         // This is a pen up event
149         x = lastX;
150         y = lastY;
151         pen_down = false;
152     } else {
153         // Some sort of event with the pen down        
154         x = lastX = (dp[1] << 8) | dp[2];
155         y = lastY = (dp[3] << 8) | dp[4];
156         pen_down = true;
157     }
158     if (num_events < MAX_EVENTS) {
159         num_events++;
160         ev = &_events[_event_put++];
161         if (_event_put == MAX_EVENTS) {
162             _event_put = 0;
163         }
164         ev->button_state = pen_down ? 0x04 : 0x00;
165         ev->xPos = x;
166         ev->yPos = y;
167         if (ts_select_active) {
168             ts_select_active = false;
169             cyg_selwakeup(&ts_select_info);
170         }
171     }
172 }
173
174 typedef struct {
175     short min;
176     short max;
177     short span;
178 } bounds;
179
180 static bounds xBounds = {1024, 0, 1024};
181 static bounds yBounds = {1024, 0, 1024};
182
183 static Cyg_ErrNo 
184 ts_read(cyg_io_handle_t handle, 
185         void *buffer, 
186         cyg_uint32 *len)
187 {
188     struct _event *ev;
189     int tot = *len;
190     unsigned char *bp = (unsigned char *)buffer;
191
192     cyg_scheduler_lock();  // Prevent interaction with DSR code
193     while (tot >= sizeof(struct _event)) {
194         if (num_events > 0) {
195             ev = &_events[_event_get++];
196             if (_event_get == MAX_EVENTS) {
197                 _event_get = 0;
198             }
199             // Self calibrate
200             if (ev->xPos > xBounds.max) xBounds.max = ev->xPos;
201             if (ev->xPos < xBounds.min) xBounds.min = ev->xPos;
202             if (ev->yPos > yBounds.max) yBounds.max = ev->yPos;
203             if (ev->yPos < yBounds.min) yBounds.min = ev->yPos;
204             if ((xBounds.span = xBounds.max - xBounds.min) <= 1) {
205                 xBounds.span = 1;
206             }
207             if ((yBounds.span = yBounds.max - yBounds.min) <= 1) {
208                 yBounds.span = 1;
209             }
210             // Scale values - done here so these potentially lengthy
211             // operations take place outside of interrupt processing
212             ev->xPos = ((xBounds.max - ev->xPos) * 320) / xBounds.span;
213             ev->yPos = ((yBounds.max - ev->yPos) * 240) / yBounds.span;
214             memcpy(bp, ev, sizeof(*ev));
215             bp += sizeof(*ev);
216             tot -= sizeof(*ev);
217             num_events--;
218         } else {
219             break;  // No more events
220         }
221     }
222     cyg_scheduler_unlock(); // Allow DSRs again
223     *len -= tot;
224     return ENOERR;
225 }
226
227 static cyg_bool  
228 ts_select(cyg_io_handle_t handle, 
229           cyg_uint32 which, 
230           cyg_addrword_t info)
231 {
232     if (which == CYG_FREAD) {
233         cyg_scheduler_lock();  // Prevent interaction with DSR code
234         if (num_events > 0) {
235             cyg_scheduler_unlock();  // Reallow interaction with DSR code
236             return true;
237         }        
238         if (!ts_select_active) {
239             ts_select_active = true;
240             cyg_selrecord(info, &ts_select_info);
241         }
242         cyg_scheduler_unlock();  // Reallow interaction with DSR code
243     }
244     return false;
245 }
246
247 static Cyg_ErrNo 
248 ts_set_config(cyg_io_handle_t handle, 
249               cyg_uint32 key, 
250               const void *buffer, 
251               cyg_uint32 *len)
252 {
253     return EINVAL;
254 }
255
256 static Cyg_ErrNo 
257 ts_get_config(cyg_io_handle_t handle, 
258               cyg_uint32 key, 
259               void *buffer, 
260               cyg_uint32 *len)
261 {
262     return EINVAL;
263 }
264
265 static bool      
266 ts_init(struct cyg_devtab_entry *tab)
267 {
268     cyg_selinit(&ts_select_info);
269     return true;
270 }
271
272 static Cyg_ErrNo 
273 ts_lookup(struct cyg_devtab_entry **tab, 
274           struct cyg_devtab_entry *st, 
275           const char *name)
276 {
277     if (!_is_open) {
278         _is_open = true;
279         atmel_register(ATMEL_CMD_TOUCH, ts_handler);
280         atmel_interrupt_mode(true);
281     }
282     return ENOERR;
283 }