Import changeset
[linux-flexiantxendom0-3.2.10.git] / drivers / input / keybdev.c
1 /*
2  * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
3  *
4  *  Copyright (c) 1999-2000 Vojtech Pavlik
5  *
6  *  Input driver to keyboard driver binding.
7  *
8  *  Sponsored by SuSE
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  * Should you need to contact me, the author, you can do so either by
27  * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
28  * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
29  */
30
31 #include <linux/config.h>
32 #include <linux/kbd_ll.h>
33 #include <linux/input.h>
34 #include <linux/malloc.h>
35 #include <linux/init.h>
36 #include <linux/module.h>
37 #include <linux/kbd_kern.h>
38
39 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || defined(__mips__)
40
41 static int x86_sysrq_alt = 0;
42
43 static unsigned short x86_keycodes[256] =
44         { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
45          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
46          32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
47          48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48          64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
49          80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
50         284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
51         367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
52         360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
53         103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
54         291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
55         118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
56         271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
57         308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
58         332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
59
60 static int emulate_raw(unsigned int keycode, int down)
61 {
62         if (keycode > 255 || !x86_keycodes[keycode])
63                 return -1; 
64
65         if (keycode == KEY_PAUSE) {
66                 handle_scancode(0xe1, 1);
67                 handle_scancode(0x1d, down);
68                 handle_scancode(0x45, down);
69                 return 0;
70         } 
71
72         if (keycode == KEY_SYSRQ && x86_sysrq_alt) {
73                 handle_scancode(0x54, down);
74                 return 0;
75         }
76
77         if (x86_keycodes[keycode] & 0x100)
78                 handle_scancode(0xe0, 1);
79
80         handle_scancode(x86_keycodes[keycode] & 0x7f, down);
81
82         if (keycode == KEY_SYSRQ) {
83                 handle_scancode(0xe0, 1);
84                 handle_scancode(0x37, down);
85         }
86
87         if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
88                 x86_sysrq_alt = down;
89
90         return 0;
91 }
92
93 #elif defined(CONFIG_ADB_KEYBOARD)
94
95 static unsigned char mac_keycodes[128] =
96         { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
97          12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,128,  1,
98           2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
99          11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
100          97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
101          84, 85, 82, 65, 42,  0, 10,103,111,  0,  0,  0,  0,  0,  0,  0,
102          76,125, 75,105,124,  0,115, 62,116, 59, 60,119, 61,121,114,117,
103           0,  0,  0,  0,127, 81,  0,113,  0,  0,  0,  0,  0, 55, 55 };
104
105 static int emulate_raw(unsigned int keycode, int down)
106 {
107         if (keycode > 127 || !mac_keycodes[keycode])
108                 return -1;
109
110         handle_scancode(mac_keycodes[keycode] & 0x7f, down);
111
112         return 0;
113 }
114
115 #endif
116
117 static struct input_handler keybdev_handler;
118
119 void keybdev_ledfunc(unsigned int led)
120 {
121         struct input_handle *handle;    
122
123         for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
124
125                 input_event(handle->dev, EV_LED, LED_SCROLLL, !!(led & 0x01));
126                 input_event(handle->dev, EV_LED, LED_NUML,    !!(led & 0x02));
127                 input_event(handle->dev, EV_LED, LED_CAPSL,   !!(led & 0x04));
128
129         }
130 }
131
132 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
133 {
134         if (type != EV_KEY) return;
135
136         if (emulate_raw(code, down))
137                 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
138
139         tasklet_schedule(&keyboard_tasklet);
140 }
141
142 static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev)
143 {
144         struct input_handle *handle;
145         int i;
146
147         if (!test_bit(EV_KEY, dev->evbit))
148                 return NULL;
149
150         for (i = KEY_RESERVED; i < BTN_MISC; i++)
151                 if (test_bit(i, dev->keybit)) break;
152
153         if (i == BTN_MISC)
154                 return NULL;
155
156         if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
157                 return NULL;
158         memset(handle, 0, sizeof(struct input_handle));
159
160         handle->dev = dev;
161         handle->handler = handler;
162
163         input_open_device(handle);
164
165         printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
166
167         return handle;
168 }
169
170 static void keybdev_disconnect(struct input_handle *handle)
171 {
172         printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
173         input_close_device(handle);
174         kfree(handle);
175 }
176         
177 static struct input_handler keybdev_handler = {
178         event:          keybdev_event,
179         connect:        keybdev_connect,
180         disconnect:     keybdev_disconnect,
181 };
182
183 static int __init keybdev_init(void)
184 {
185         input_register_handler(&keybdev_handler);
186         kbd_ledfunc = keybdev_ledfunc;
187         return 0;
188 }
189
190 static void __exit keybdev_exit(void)
191 {
192         kbd_ledfunc = NULL;
193         input_unregister_handler(&keybdev_handler);
194 }
195
196 module_init(keybdev_init);
197 module_exit(keybdev_exit);
198
199 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
200 MODULE_DESCRIPTION("Input driver to keyboard driver binding");