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
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>
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)
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
=
63 usb_kbd_handle_key(unsigned char key
, int down
)
65 int scancode
= (int) usb_kbd_map
[key
];
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
);
79 usb_kbd_repeat(unsigned long dev_id
)
81 struct usb_keyboard
*kbd
= (struct usb_keyboard
*) dev_id
;
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
);
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
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
;
129 /* handle modifier change */
130 modsdelta
= (*(unsigned char*) down
^ *(unsigned char*) kbd
->down
);
133 for(i
= 0; i
< 8; i
++)
137 int pressed
= (*(unsigned char*) down
>> i
) & 0x01;
139 i
+ USBKBD_MODIFIER_BASE
,
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
++)
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 */
162 for(i
= 0; i
< USBKBD_KEYCODE_COUNT
; 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 */
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];
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)
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)
212 printk(KERN_INFO
"USB HID boot protocol keyboard detected.\n");
214 kbd
= kmalloc(sizeof(struct usb_keyboard
), GFP_KERNEL
);
217 memset(kbd
, 0, sizeof(*kbd
));
221 if (usb_set_configuration(dev
, dev
->config
[0].bConfigurationValue
)) {
222 printk (KERN_INFO
" Failed usb_set_configuration: kbd\n");
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
);
244 usb_kbd_disconnect(struct usb_device
*dev
)
246 struct usb_keyboard
*kbd
= (struct usb_keyboard
*) dev
->private;
250 list_del(&kbd
->list
);
251 del_timer(&kbd
->repeat_timer
);
255 printk(KERN_INFO
"USB HID boot protocol keyboard removed.\n");
258 int usb_kbd_init(void)
260 usb_register(&usb_kbd_driver
);
264 void usb_kbd_cleanup(void)
266 struct list_head
*cur
, *head
= &usb_kbd_list
;
270 while (cur
!= head
) {
271 struct usb_keyboard
*kbd
= list_entry(cur
, struct usb_keyboard
, list
);
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
);
289 int init_module(void)
291 return usb_kbd_init();
294 void cleanup_module(void)