]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/char/scan_keyb.c
Linux-2.6.12-rc2
[mirror_ubuntu-hirsute-kernel.git] / drivers / char / scan_keyb.c
1 /*
2 * $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $
3 * Copyright (C) 2000 YAEGASHI Takeshi
4 * Generic scan keyboard driver
5 */
6
7 #include <linux/spinlock.h>
8 #include <linux/sched.h>
9 #include <linux/interrupt.h>
10 #include <linux/tty.h>
11 #include <linux/mm.h>
12 #include <linux/signal.h>
13 #include <linux/init.h>
14 #include <linux/kbd_ll.h>
15 #include <linux/delay.h>
16 #include <linux/random.h>
17 #include <linux/poll.h>
18 #include <linux/miscdevice.h>
19 #include <linux/slab.h>
20 #include <linux/kbd_kern.h>
21 #include <linux/timer.h>
22
23 #define SCANHZ (HZ/20)
24
25 struct scan_keyboard {
26 struct scan_keyboard *next;
27 int (*scan)(unsigned char *buffer);
28 const unsigned char *table;
29 unsigned char *s0, *s1;
30 int length;
31 };
32
33 static int scan_jiffies=0;
34 static struct scan_keyboard *keyboards=NULL;
35 struct timer_list scan_timer;
36
37 static void check_kbd(const unsigned char *table,
38 unsigned char *new, unsigned char *old, int length)
39 {
40 int need_tasklet_schedule=0;
41 unsigned int xor, bit;
42
43 while(length-->0) {
44 if((xor=*new^*old)==0) {
45 table+=8;
46 }
47 else {
48 for(bit=0x01; bit<0x100; bit<<=1) {
49 if(xor&bit) {
50 handle_scancode(*table, !(*new&bit));
51 need_tasklet_schedule=1;
52 #if 0
53 printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed");
54 #endif
55 }
56 table++;
57 }
58 }
59 new++; old++;
60 }
61
62 if(need_tasklet_schedule)
63 tasklet_schedule(&keyboard_tasklet);
64 }
65
66
67 static void scan_kbd(unsigned long dummy)
68 {
69 struct scan_keyboard *kbd;
70
71 scan_jiffies++;
72
73 for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) {
74 if(scan_jiffies&1) {
75 if(!kbd->scan(kbd->s0))
76 check_kbd(kbd->table,
77 kbd->s0, kbd->s1, kbd->length);
78 else
79 memcpy(kbd->s0, kbd->s1, kbd->length);
80 }
81 else {
82 if(!kbd->scan(kbd->s1))
83 check_kbd(kbd->table,
84 kbd->s1, kbd->s0, kbd->length);
85 else
86 memcpy(kbd->s1, kbd->s0, kbd->length);
87 }
88
89 }
90
91 init_timer(&scan_timer);
92 scan_timer.expires = jiffies + SCANHZ;
93 scan_timer.data = 0;
94 scan_timer.function = scan_kbd;
95 add_timer(&scan_timer);
96 }
97
98
99 int register_scan_keyboard(int (*scan)(unsigned char *buffer),
100 const unsigned char *table,
101 int length)
102 {
103 struct scan_keyboard *kbd;
104
105 kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL);
106 if (kbd == NULL)
107 goto error_out;
108
109 kbd->scan=scan;
110 kbd->table=table;
111 kbd->length=length;
112
113 kbd->s0 = kmalloc(length, GFP_KERNEL);
114 if (kbd->s0 == NULL)
115 goto error_free_kbd;
116
117 kbd->s1 = kmalloc(length, GFP_KERNEL);
118 if (kbd->s1 == NULL)
119 goto error_free_s0;
120
121 memset(kbd->s0, -1, kbd->length);
122 memset(kbd->s1, -1, kbd->length);
123
124 kbd->next=keyboards;
125 keyboards=kbd;
126
127 return 0;
128
129 error_free_s0:
130 kfree(kbd->s0);
131
132 error_free_kbd:
133 kfree(kbd);
134
135 error_out:
136 return -ENOMEM;
137 }
138
139
140 void __init scan_kbd_init(void)
141 {
142 init_timer(&scan_timer);
143 scan_timer.expires = jiffies + SCANHZ;
144 scan_timer.data = 0;
145 scan_timer.function = scan_kbd;
146 add_timer(&scan_timer);
147
148 printk(KERN_INFO "Generic scan keyboard driver initialized\n");
149 }