Subversion Repositories shark

Rev

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

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