]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/kbd/arm/ipaq/v2_0/src/ipaq_kbd.c
Initial revision
[karo-tx-redboot.git] / packages / devs / kbd / arm / ipaq / v2_0 / src / ipaq_kbd.c
1 //==========================================================================
2 //
3 //      ipaq_kbd.c
4 //
5 //      Keypad 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-15
46 // Purpose:      
47 // Description:  Keypad driver for Compaq IPAQ
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53
54 #include <pkgconf/devs_kbd_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      kbd_select_info; 
68 static cyg_bool         kbd_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 kbd_read(cyg_io_handle_t handle, 
76                           void *buffer, 
77                           cyg_uint32 *len);
78 static cyg_bool  kbd_select(cyg_io_handle_t handle, 
79                             cyg_uint32 which, 
80                             cyg_addrword_t info);
81 static Cyg_ErrNo kbd_set_config(cyg_io_handle_t handle, 
82                                 cyg_uint32 key, 
83                                 const void *buffer, 
84                                 cyg_uint32 *len);
85 static Cyg_ErrNo kbd_get_config(cyg_io_handle_t handle, 
86                                 cyg_uint32 key, 
87                                 void *buffer, 
88                                 cyg_uint32 *len);
89 static bool      kbd_init(struct cyg_devtab_entry *tab);
90 static Cyg_ErrNo kbd_lookup(struct cyg_devtab_entry **tab, 
91                             struct cyg_devtab_entry *st, 
92                             const char *name);
93
94 CHAR_DEVIO_TABLE(ipaq_kbd_handlers,
95                  NULL,                                   // Unsupported write() function
96                  kbd_read,
97                  kbd_select,
98                  kbd_get_config,
99                  kbd_set_config);
100
101 CHAR_DEVTAB_ENTRY(ipaq_kbd_device,
102                   CYGDAT_DEVS_KBD_IPAQ_NAME,
103                   NULL,                                   // Base device name
104                   &ipaq_kbd_handlers,
105                   kbd_init,
106                   kbd_lookup,
107                   NULL);                                  // Private data pointer
108
109 #define MAX_EVENTS CYGNUM_DEVS_KBD_IPAQ_EVENT_BUFFER_SIZE
110 static int   num_events;
111 static int   _event_put, _event_get;
112 static unsigned char _events[MAX_EVENTS];
113
114 static bool _is_open = false;
115
116 //
117 // Note: this routine is called from the Atmel processing DSR
118 //
119 static void
120 kbd_handler(atmel_pkt *pkt)
121 {
122     unsigned char *dp = pkt->data;
123     unsigned char *ev;
124
125 //    diag_printf("KBD = %x\n", dp[1]);
126     if (num_events < MAX_EVENTS) {
127         num_events++;
128         ev = &_events[_event_put++];
129         if (_event_put == MAX_EVENTS) {
130             _event_put = 0;
131         }
132         *ev = dp[1];
133         if (kbd_select_active) {
134             kbd_select_active = false;
135             cyg_selwakeup(&kbd_select_info);
136         }
137     }
138 }
139
140 static Cyg_ErrNo 
141 kbd_read(cyg_io_handle_t handle, 
142          void *buffer, 
143          cyg_uint32 *len)
144 {
145     unsigned char *ev;
146     int tot = *len;
147     unsigned char *bp = (unsigned char *)buffer;
148
149     cyg_scheduler_lock();  // Prevent interaction with DSR code
150     while (tot >= sizeof(*ev)) {
151         if (num_events > 0) {
152             ev = &_events[_event_get++];
153             if (_event_get == MAX_EVENTS) {
154                 _event_get = 0;
155             }
156             memcpy(bp, ev, sizeof(*ev));
157             bp += sizeof(*ev);
158             tot -= sizeof(*ev);
159             num_events--;
160         } else {
161             break;  // No more events
162         }
163     }
164     cyg_scheduler_unlock(); // Allow DSRs again
165     *len -= tot;
166     return ENOERR;
167 }
168
169 static cyg_bool  
170 kbd_select(cyg_io_handle_t handle, 
171            cyg_uint32 which, 
172            cyg_addrword_t info)
173 {
174     if (which == CYG_FREAD) {
175         cyg_scheduler_lock();  // Prevent interaction with DSR code
176         if (num_events > 0) {
177             cyg_scheduler_unlock();  // Reallow interaction with DSR code
178             return true;
179         }        
180         if (!kbd_select_active) {
181             kbd_select_active = true;
182             cyg_selrecord(info, &kbd_select_info);
183         }
184         cyg_scheduler_unlock();  // Reallow interaction with DSR code
185     }
186     return false;
187 }
188
189 static Cyg_ErrNo 
190 kbd_set_config(cyg_io_handle_t handle, 
191                cyg_uint32 key, 
192                const void *buffer, 
193                cyg_uint32 *len)
194 {
195     return EINVAL;
196 }
197
198 static Cyg_ErrNo 
199 kbd_get_config(cyg_io_handle_t handle, 
200                cyg_uint32 key, 
201                void *buffer, 
202                cyg_uint32 *len)
203 {
204     return EINVAL;
205 }
206
207 static bool      
208 kbd_init(struct cyg_devtab_entry *tab)
209 {
210     cyg_selinit(&kbd_select_info);
211     return true;
212 }
213
214 static Cyg_ErrNo 
215 kbd_lookup(struct cyg_devtab_entry **tab, 
216            struct cyg_devtab_entry *st, 
217            const char *name)
218 {
219     if (!_is_open) {
220         _is_open = true;
221         atmel_register(ATMEL_CMD_KEYBD, kbd_handler);
222         atmel_interrupt_mode(true);
223     }
224     return ENOERR;
225 }