blob: 2b5bb4f5754dc8828389bfef2b298335fc418ac1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
25struct 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
33static int scan_jiffies=0;
34static struct scan_keyboard *keyboards=NULL;
35struct timer_list scan_timer;
36
37static 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
67static 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
99int 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
140void __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}