Subversion Repositories shark

Rev

Rev 547 | 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
        }
547 mauro 80
 
519 mauro 81
        return 0;
82
}
83
 
84
int kbd_disable(void)
85
{
86
        struct list_head *node;
87
 
88
        list_for_each(node,&kbd_handler.h_list) {
89
                struct input_handle *handle = to_handle_h(node);
90
                struct input_dev *dev = handle->dev;
91
 
92
                if (test_bit(EV_REP, dev->evbit)) {
93
                        input_event(dev, EV_PWR, 0, 0);
94
                }
95
        }
547 mauro 96
 
519 mauro 97
        return 0;
98
}
99
 
100
/*
101
 * Get data from the keyboard (primary port)
102
 *
103
 * it's follow the port_receive() semantic
104
 */
105
int kbd_get(unsigned int *data, BYTE access)
106
{
107
        if ( ((ktail+1) & KEYB_BUFFERMASK) == ((khead) & KEYB_BUFFERMASK) )
108
                return -1;
109
 
110
        ktail = (ktail+1) & KEYB_BUFFERMASK;
111
        *data = kbuffer[ktail].keycode;
112
 
113
        return kbuffer[ktail].down;
114
}
115
 
116
/*
117
 * Making beeps and bells.
118
 */
119
static void kbd_nosound(unsigned long ignored)
120
{
121
        struct list_head * node;
122
 
123
        list_for_each(node,&kbd_handler.h_list) {
124
                struct input_handle *handle = to_handle_h(node);
125
                if (test_bit(EV_SND, handle->dev->evbit)) {
126
                        if (test_bit(SND_TONE, handle->dev->sndbit))
127
                                input_event(handle->dev, EV_SND, SND_TONE, 0);
128
                        if (test_bit(SND_BELL, handle->dev->sndbit))
129
                                input_event(handle->dev, EV_SND, SND_BELL, 0);
130
                }
131
        }
132
}
133
 
134
static struct timer_list kd_mksound_timer =
135
                TIMER_INITIALIZER(kbd_nosound, 0, 0);
136
 
137
void kbd_mksound(unsigned int hz, unsigned int ticks)
138
{
139
        struct list_head * node;
140
 
141
        del_timer(&kd_mksound_timer);
142
 
143
        if (hz) {
144
                list_for_each_prev(node,&kbd_handler.h_list) {
145
                        struct input_handle *handle = to_handle_h(node);
146
                        if (test_bit(EV_SND, handle->dev->evbit)) {
147
                                if (test_bit(SND_TONE, handle->dev->sndbit)) {
148
                                        input_event(handle->dev, EV_SND, SND_TONE, hz);
149
                                        break;
150
                                }
151
                                if (test_bit(SND_BELL, handle->dev->sndbit)) {
152
                                        input_event(handle->dev, EV_SND, SND_BELL, 1);
153
                                        break;
154
                                }
155
                        }
156
                }
157
                if (ticks)
158
                        mod_timer(&kd_mksound_timer, jiffies26 + ticks);
159
        } else
160
                kbd_nosound(0);
161
}
162
 
163
/*
164
 * Setting the keyboard rate.
165
 */
166
 
167
//int kbd_rate(struct kbd_repeat *rep)
168
int kbd_rate(unsigned int *delay, unsigned int *period)
169
{
170
        struct list_head *node;
171
        unsigned int d = 0;
172
        unsigned int p = 0;
173
 
174
        list_for_each(node,&kbd_handler.h_list) {
175
                struct input_handle *handle = to_handle_h(node);
176
                struct input_dev *dev = handle->dev;
177
 
178
                if (test_bit(EV_REP, dev->evbit)) {
179
                        if (*delay > 0)
180
                                input_event(dev, EV_REP, REP_DELAY, *delay);
181
                        if (*period > 0)
182
                                input_event(dev, EV_REP, REP_PERIOD, *period);
183
                        d = dev->rep[REP_DELAY];
184
                        p = dev->rep[REP_PERIOD];
185
                }
186
        }
187
        *delay  = d;
188
        *period = p;
189
        return 0;
190
}
191
 
192
/*
193
 * This allows a keyboard to pick the LED state.
194
 */
195
void kbd_refresh_leds(void)
196
{
197
        struct list_head * node;
198
        unsigned char leds = ledstate;
199
 
200
        list_for_each(node,&kbd_handler.h_list) {
201
                struct input_handle * handle = to_handle_h(node);
202
                input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
203
                input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
204
                input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
205
                input_sync(handle->dev);
206
        }
207
}
208
 
209
void kbd_setleds(unsigned int led)
210
{
211
        ledstate = led;
212
        kbd_refresh_leds();
213
}
214
 
215
static void kbd_event(struct input_handle *handle, unsigned int type, unsigned int keycode, int down)
216
{
217
        if (type != EV_KEY)
218
                return;
219
 
220
#ifdef DEBUG_KBD
221
        printk(KERN_DEBUG "keyboard.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, keycode, down);
222
#endif
223
 
224
        if (ktail != khead) {
225
                kbuffer[khead].keycode = keycode;
226
                kbuffer[khead].down = down;
227
                khead = (khead+1) & KEYB_BUFFERMASK;
228
        }
229
 
522 mauro 230
        shark_kbd_exec();
519 mauro 231
}
232
 
233
static struct input_handle *kbd_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
234
{
235
        struct input_handle *handle;
236
        int i;
237
 
238
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
239
                if (test_bit(i, dev->keybit)) break;
240
 
241
        if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
242
                return NULL;
243
 
244
        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
245
                return NULL;
246
        memset(handle, 0, sizeof(struct input_handle));
247
 
248
        handle->dev = dev;
249
        handle->handler = handler;
250
        handle->name = kbd_name;
251
 
252
        input_open_device(handle);
253
#ifdef DEBUG_KBD
254
        printk(KERN_DEBUG "keyboard.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
255
#endif
256
        return handle;
257
}
258
 
259
static void kbd_disconnect(struct input_handle *handle)
260
{
261
#ifdef DEBUG_KBD
262
        printk(KERN_DEBUG "keyboard.c: Disconnected device: %s\n", handle->dev->phys);
263
#endif
264
 
265
        input_close_device(handle);
266
 
267
        kfree(handle);
268
}
269
 
270
static struct input_device_id kbd_ids[] = {
271
        {
272
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
273
                .evbit = { BIT(EV_KEY) },
274
        },
275
 
276
        {
277
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
278
                .evbit = { BIT(EV_SND) },
279
        },     
280
 
281
        { },    /* Terminating entry */
282
};
283
 
284
MODULE_DEVICE_TABLE(input, kbd_ids);
285
 
286
static struct input_handler kbd_handler = {
287
        .event =        kbd_event,
288
        .connect =      kbd_connect,
289
        .disconnect =   kbd_disconnect,
290
        .name =         "kbd",
291
        .id_table =     kbd_ids,
292
};
293
 
294
int __init kbd_init(void)
295
{
296
        /* Initialize Buffer Variables */
297
        khead=1;
298
        ktail=0;
299
 
300
        input_register_handler(&kbd_handler);
301
 
302
        return 0;
303
}
304
 
305
void __exit kbd_exit(void)
306
{
307
        input_unregister_handler(&kbd_handler);
308
}
309
 
310
module_init(kbd_init);
311
module_exit(kbd_exit);