Import 2.3.18pre1
[davej-history.git] / drivers / usb / keyboard.c
blob85ca4f6fb30923319100da110dafab1ae8ea99c6
1 /*
2 Fixes:
3 1999/09/04 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
4 Handle states in usb_kbd_irq
5 1999/09/06 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 rmmod usb-keyboard doesn't crash the system anymore: the irq
7 handlers are correctly released with usb_release_irq
8 */
9 #include <linux/kernel.h>
10 #include <linux/malloc.h>
11 #include <linux/string.h>
12 #include <linux/timer.h>
13 #include <linux/sched.h>
14 #include <linux/config.h>
15 #include <linux/module.h>
17 #include <linux/kbd_ll.h>
18 #include "usb.h"
20 #define PCKBD_PRESSED 0x00
21 #define PCKBD_RELEASED 0x80
22 #define PCKBD_NEEDS_E0 0x80
24 #define USBKBD_MODIFIER_BASE 120
25 #define USBKBD_KEYCODE_OFFSET 2
26 #define USBKBD_KEYCODE_COUNT 6
28 #define USBKBD_VALID_KEYCODE(key) ((unsigned char)(key) > 3)
29 #define USBKBD_FIND_KEYCODE(down, key, count) \
30 ((unsigned char*) memscan((down), (key), (count)) < ((down) + (count)))
32 #define USBKBD_REPEAT_DELAY (HZ / 4)
33 #define USBKBD_REPEAT_RATE (HZ / 20)
35 struct usb_keyboard
37 struct usb_device *dev;
38 unsigned long down[2];
39 unsigned char repeat_key;
40 struct timer_list repeat_timer;
41 struct list_head list;
42 void *irq_handler; /* host controller's IRQ transfer handle */
45 extern unsigned char usb_kbd_map[];
47 static int usb_kbd_probe(struct usb_device *dev);
48 static void usb_kbd_disconnect(struct usb_device *dev);
49 static void usb_kbd_repeat(unsigned long dummy);
51 static LIST_HEAD(usb_kbd_list);
53 static struct usb_driver usb_kbd_driver =
55 "keyboard",
56 usb_kbd_probe,
57 usb_kbd_disconnect,
58 {NULL, NULL}
62 static void
63 usb_kbd_handle_key(unsigned char key, int down)
65 int scancode = (int) usb_kbd_map[key];
66 if(scancode)
68 #ifndef CONFIG_MAC_KEYBOARD
69 if(scancode & PCKBD_NEEDS_E0)
71 handle_scancode(0xe0, 1);
73 #endif /* CONFIG_MAC_KEYBOARD */
74 handle_scancode((scancode & ~PCKBD_NEEDS_E0), down);
78 static void
79 usb_kbd_repeat(unsigned long dev_id)
81 struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id;
83 unsigned long flags;
84 save_flags(flags);
85 cli();
87 if(kbd->repeat_key)
89 usb_kbd_handle_key(kbd->repeat_key, 1);
91 /* reset repeat timer */
92 kbd->repeat_timer.function = usb_kbd_repeat;
93 kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_RATE;
94 kbd->repeat_timer.data = (unsigned long) kbd;
95 kbd->repeat_timer.prev = NULL;
96 kbd->repeat_timer.next = NULL;
97 add_timer(&kbd->repeat_timer);
100 restore_flags(flags);
103 static int
104 usb_kbd_irq(int state, void *buffer, int len, void *dev_id)
106 struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id;
107 unsigned long *down = (unsigned long*) buffer;
110 * USB_ST_NOERROR is the normal case.
111 * USB_ST_REMOVED occurs if keyboard disconnected
112 * On other states, ignore
115 switch (state) {
116 case USB_ST_REMOVED:
117 case USB_ST_INTERNALERROR:
118 printk(KERN_DEBUG "%s(%d): Suspending\n", __FILE__, __LINE__);
119 return 0; /* disable */
120 case USB_ST_NOERROR: break;
121 default: return 1; /* ignore */
124 if(kbd->down[0] != down[0] || kbd->down[1] != down[1]) {
125 unsigned char *olddown, *newdown;
126 unsigned char modsdelta, key;
127 int i;
129 /* handle modifier change */
130 modsdelta = (*(unsigned char*) down ^ *(unsigned char*) kbd->down);
131 if(modsdelta)
133 for(i = 0; i < 8; i++)
135 if(modsdelta & 0x01)
137 int pressed = (*(unsigned char*) down >> i) & 0x01;
138 usb_kbd_handle_key(
139 i + USBKBD_MODIFIER_BASE,
140 pressed);
142 modsdelta >>= 1;
146 olddown = (unsigned char*) kbd->down + USBKBD_KEYCODE_OFFSET;
147 newdown = (unsigned char*) down + USBKBD_KEYCODE_OFFSET;
149 /* handle released keys */
150 for(i = 0; i < USBKBD_KEYCODE_COUNT; i++)
152 key = olddown[i];
153 if(USBKBD_VALID_KEYCODE(key)
154 && !USBKBD_FIND_KEYCODE(newdown, key, USBKBD_KEYCODE_COUNT))
156 usb_kbd_handle_key(key, 0);
160 /* handle pressed keys */
161 kbd->repeat_key = 0;
162 for(i = 0; i < USBKBD_KEYCODE_COUNT; i++)
164 key = newdown[i];
165 if(USBKBD_VALID_KEYCODE(key)
166 && !USBKBD_FIND_KEYCODE(olddown, key, USBKBD_KEYCODE_COUNT))
168 usb_kbd_handle_key(key, 1);
169 kbd->repeat_key = key;
173 /* set repeat timer if any keys were pressed */
174 if(kbd->repeat_key)
176 del_timer(&kbd->repeat_timer);
177 kbd->repeat_timer.function = usb_kbd_repeat;
178 kbd->repeat_timer.expires = jiffies + USBKBD_REPEAT_DELAY;
179 kbd->repeat_timer.data = (unsigned long) kbd;
180 kbd->repeat_timer.prev = NULL;
181 kbd->repeat_timer.next = NULL;
182 add_timer(&kbd->repeat_timer);
185 kbd->down[0] = down[0];
186 kbd->down[1] = down[1];
189 return 1;
192 static int
193 usb_kbd_probe(struct usb_device *dev)
195 struct usb_interface_descriptor *interface;
196 struct usb_endpoint_descriptor *endpoint;
197 struct usb_keyboard *kbd;
199 if (dev->descriptor.bNumConfigurations < 1)
200 return -1;
202 interface = &dev->config[0].interface[0].altsetting[0];
203 endpoint = &interface->endpoint[0];
205 if(interface->bInterfaceClass != 3
206 || interface->bInterfaceSubClass != 1
207 || interface->bInterfaceProtocol != 1)
209 return -1;
212 printk(KERN_INFO "USB HID boot protocol keyboard detected.\n");
214 kbd = kmalloc(sizeof(struct usb_keyboard), GFP_KERNEL);
215 if(kbd)
217 memset(kbd, 0, sizeof(*kbd));
218 kbd->dev = dev;
219 dev->private = kbd;
221 if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
222 printk (KERN_INFO " Failed usb_set_configuration: kbd\n");
223 goto probe_err;
225 usb_set_protocol(dev, 0);
226 usb_set_idle(dev, 0, 0);
228 kbd->irq_handler = usb_request_irq(dev,
229 usb_rcvctrlpipe(dev, endpoint->bEndpointAddress),
230 usb_kbd_irq, endpoint->bInterval, kbd);
232 list_add(&kbd->list, &usb_kbd_list);
234 return 0;
237 probe_err:
238 if (kbd)
239 kfree (kbd);
240 return -1;
243 static void
244 usb_kbd_disconnect(struct usb_device *dev)
246 struct usb_keyboard *kbd = (struct usb_keyboard*) dev->private;
247 if(kbd)
249 dev->private = NULL;
250 list_del(&kbd->list);
251 del_timer(&kbd->repeat_timer);
252 kfree(kbd);
255 printk(KERN_INFO "USB HID boot protocol keyboard removed.\n");
258 int usb_kbd_init(void)
260 usb_register(&usb_kbd_driver);
261 return 0;
264 void usb_kbd_cleanup(void)
266 struct list_head *cur, *head = &usb_kbd_list;
268 cur = head->next;
270 while (cur != head) {
271 struct usb_keyboard *kbd = list_entry(cur, struct usb_keyboard, list);
273 cur = cur->next;
275 list_del(&kbd->list);
276 INIT_LIST_HEAD(&kbd->list);
278 if (kbd->irq_handler) {
279 usb_release_irq(kbd->dev, kbd->irq_handler);
280 /* never keep a reference to a released IRQ! */
281 kbd->irq_handler = NULL;
285 usb_deregister(&usb_kbd_driver);
288 #ifdef MODULE
289 int init_module(void)
291 return usb_kbd_init();
294 void cleanup_module(void)
296 usb_kbd_cleanup();
298 #endif