Subversion Repositories shark

Rev

Rev 519 | Rev 538 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
519 mauro 1
/*
522 mauro 2
 * $Id: keyboard.c,v 1.2 2004-03-23 15:37:21 mauro Exp $
519 mauro 3
 *
4
 *  Copyright (c) 1999-2001 Vojtech Pavlik
5
 */
6
 
7
/*
8
 *  Input driver event debug module - dumps all events into syslog
9
 */
10
 
11
/*
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
 */
26
 
27
#include <linuxcomp.h>
28
 
29
#include <linux/slab.h>
30
#include <linux/module.h>
31
#include <linux/input.h>
32
#include <linux/init.h>
33
#include <linux/device.h>
34
 
35
#include <linux/kbd_kern.h>
36
#include <linux/kbd_diacr.h>
37
 
38
//#define DEBUG_KBD
39
 
40
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41
MODULE_DESCRIPTION("Input driver event debug module");
42
MODULE_LICENSE("GPL");
43
 
522 mauro 44
extern void shark_kbd_exec(void);
519 mauro 45
 
46
/* Buffer Ssize */
47
#define KEYB_BUFFERSIZE 256
48
 
49
/* Buffer Mask ( i=(i+1)&MASK is better than i=(i+1)%SIZE ) */
50
#define KEYB_BUFFERMASK 0xff
51
 
52
/* Circular Buffer */
53
static struct keyb_event {
54
        unsigned int keycode;
55
        int down;
56
} kbuffer[KEYB_BUFFERSIZE];
57
 
58
/*
59
 * Buffer Pointers
60
 * data is inserted to khead
61
 * data is kept from ktail+1
62
 * (khead point to ktail+1 when buffer is empty)
63
 */
64
static unsigned ktail, khead;
65
 
66
static char kbd_name[] = "kbd";
67
static struct input_handler kbd_handler;
68
 
69
static unsigned char ledstate = 0xff;                   /* undefined */
70
 
71
/*
72
 * Start / Stop Keyboard
73
 */
74
int kbd_enable(void)
75
{
76
        struct list_head *node;
77
 
78
        list_for_each(node,&kbd_handler.h_list) {
79
                struct input_handle *handle = to_handle_h(node);
80
                struct input_dev *dev = handle->dev;
81
 
82
                if (test_bit(EV_REP, dev->evbit)) {
83
                        input_event(dev, EV_PWR, 1, 0);
84
                }
85
        }
86
 
87
        return 0;
88
 
89
}
90
 
91
int kbd_disable(void)
92
{
93
        struct list_head *node;
94
 
95
        list_for_each(node,&kbd_handler.h_list) {
96
                struct input_handle *handle = to_handle_h(node);
97
                struct input_dev *dev = handle->dev;
98
 
99
                if (test_bit(EV_REP, dev->evbit)) {
100
                        input_event(dev, EV_PWR, 0, 0);
101
                }
102
        }
103
 
104
        return 0;
105
 
106
}
107
 
108
/*
109
 * Get data from the keyboard (primary port)
110
 *
111
 * it's follow the port_receive() semantic
112
 */
113
int kbd_get(unsigned int *data, BYTE access)
114
{
115
        if ( ((ktail+1) & KEYB_BUFFERMASK) == ((khead) & KEYB_BUFFERMASK) )
116
                return -1;
117
 
118
        ktail = (ktail+1) & KEYB_BUFFERMASK;
119
        *data = kbuffer[ktail].keycode;
120
 
121
        return kbuffer[ktail].down;
122
}
123
 
124
/*
125
 * Making beeps and bells.
126
 */
127
static void kbd_nosound(unsigned long ignored)
128
{
129
        struct list_head * node;
130
 
131
        list_for_each(node,&kbd_handler.h_list) {
132
                struct input_handle *handle = to_handle_h(node);
133
                if (test_bit(EV_SND, handle->dev->evbit)) {
134
                        if (test_bit(SND_TONE, handle->dev->sndbit))
135
                                input_event(handle->dev, EV_SND, SND_TONE, 0);
136
                        if (test_bit(SND_BELL, handle->dev->sndbit))
137
                                input_event(handle->dev, EV_SND, SND_BELL, 0);
138
                }
139
        }
140
}
141
 
142
static struct timer_list kd_mksound_timer =
143
                TIMER_INITIALIZER(kbd_nosound, 0, 0);
144
 
145
void kbd_mksound(unsigned int hz, unsigned int ticks)
146
{
147
        struct list_head * node;
148
 
149
        del_timer(&kd_mksound_timer);
150
 
151
        if (hz) {
152
                list_for_each_prev(node,&kbd_handler.h_list) {
153
                        struct input_handle *handle = to_handle_h(node);
154
                        if (test_bit(EV_SND, handle->dev->evbit)) {
155
                                if (test_bit(SND_TONE, handle->dev->sndbit)) {
156
                                        input_event(handle->dev, EV_SND, SND_TONE, hz);
157
                                        break;
158
                                }
159
                                if (test_bit(SND_BELL, handle->dev->sndbit)) {
160
                                        input_event(handle->dev, EV_SND, SND_BELL, 1);
161
                                        break;
162
                                }
163
                        }
164
                }
165
                if (ticks)
166
                        mod_timer(&kd_mksound_timer, jiffies26 + ticks);
167
        } else
168
                kbd_nosound(0);
169
}
170
 
171
/*
172
 * Setting the keyboard rate.
173
 */
174
 
175
//int kbd_rate(struct kbd_repeat *rep)
176
int kbd_rate(unsigned int *delay, unsigned int *period)
177
{
178
        struct list_head *node;
179
        unsigned int d = 0;
180
        unsigned int p = 0;
181
 
182
        list_for_each(node,&kbd_handler.h_list) {
183
                struct input_handle *handle = to_handle_h(node);
184
                struct input_dev *dev = handle->dev;
185
 
186
                if (test_bit(EV_REP, dev->evbit)) {
187
                        if (*delay > 0)
188
                                input_event(dev, EV_REP, REP_DELAY, *delay);
189
                        if (*period > 0)
190
                                input_event(dev, EV_REP, REP_PERIOD, *period);
191
                        d = dev->rep[REP_DELAY];
192
                        p = dev->rep[REP_PERIOD];
193
                }
194
        }
195
        *delay  = d;
196
        *period = p;
197
        return 0;
198
}
199
 
200
/*
201
 * This allows a keyboard to pick the LED state.
202
 */
203
void kbd_refresh_leds(void)
204
{
205
        struct list_head * node;
206
        unsigned char leds = ledstate;
207
 
208
        list_for_each(node,&kbd_handler.h_list) {
209
                struct input_handle * handle = to_handle_h(node);
210
                input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
211
                input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
212
                input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
213
                input_sync(handle->dev);
214
        }
215
}
216
 
217
void kbd_setleds(unsigned int led)
218
{
219
        ledstate = led;
220
        kbd_refresh_leds();
221
}
222
 
223
static void kbd_event(struct input_handle *handle, unsigned int type, unsigned int keycode, int down)
224
{
225
        if (type != EV_KEY)
226
                return;
227
 
228
#ifdef DEBUG_KBD
229
        printk(KERN_DEBUG "keyboard.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, keycode, down);
230
#endif
231
 
232
        if (ktail != khead) {
233
                kbuffer[khead].keycode = keycode;
234
                kbuffer[khead].down = down;
235
                khead = (khead+1) & KEYB_BUFFERMASK;
236
        }
237
 
522 mauro 238
        shark_kbd_exec();
519 mauro 239
}
240
 
241
static struct input_handle *kbd_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
242
{
243
        struct input_handle *handle;
244
        int i;
245
 
246
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
247
                if (test_bit(i, dev->keybit)) break;
248
 
249
        if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
250
                return NULL;
251
 
252
        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
253
                return NULL;
254
        memset(handle, 0, sizeof(struct input_handle));
255
 
256
        handle->dev = dev;
257
        handle->handler = handler;
258
        handle->name = kbd_name;
259
 
260
        input_open_device(handle);
261
#ifdef DEBUG_KBD
262
        printk(KERN_DEBUG "keyboard.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
263
#endif
264
        return handle;
265
}
266
 
267
static void kbd_disconnect(struct input_handle *handle)
268
{
269
#ifdef DEBUG_KBD
270
        printk(KERN_DEBUG "keyboard.c: Disconnected device: %s\n", handle->dev->phys);
271
#endif
272
 
273
        input_close_device(handle);
274
 
275
        kfree(handle);
276
}
277
 
278
static struct input_device_id kbd_ids[] = {
279
        {
280
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
281
                .evbit = { BIT(EV_KEY) },
282
        },
283
 
284
        {
285
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
286
                .evbit = { BIT(EV_SND) },
287
        },     
288
 
289
        { },    /* Terminating entry */
290
};
291
 
292
MODULE_DEVICE_TABLE(input, kbd_ids);
293
 
294
static struct input_handler kbd_handler = {
295
        .event =        kbd_event,
296
        .connect =      kbd_connect,
297
        .disconnect =   kbd_disconnect,
298
        .name =         "kbd",
299
        .id_table =     kbd_ids,
300
};
301
 
302
int __init kbd_init(void)
303
{
304
        /* Initialize Buffer Variables */
305
        khead=1;
306
        ktail=0;
307
 
308
        input_register_handler(&kbd_handler);
309
 
310
        return 0;
311
}
312
 
313
void __exit kbd_exit(void)
314
{
315
        input_unregister_handler(&kbd_handler);
316
}
317
 
318
module_init(kbd_init);
319
module_exit(kbd_exit);