]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/hid/usbhid/usbkbd.c
USB: remove uses of URB_NO_SETUP_DMA_MAP
[net-next-2.6.git] / drivers / hid / usbhid / usbkbd.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Copyright (c) 1999-2001 Vojtech Pavlik
3 *
4 * USB HIDBP Keyboard support
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
05f091ab 10 * the Free Software Foundation; either version 2 of the License, or
1da177e4 11 * (at your option) any later version.
05f091ab 12 *
1da177e4
LT
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
05f091ab 17 *
1da177e4
LT
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
05f091ab 21 *
1da177e4
LT
22 * Should you need to contact me, the author, you can do so either by
23 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
24 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
25 */
26
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/module.h>
1da177e4 30#include <linux/init.h>
ae0dadcf 31#include <linux/usb/input.h>
4ef2e23f 32#include <linux/hid.h>
1da177e4
LT
33
34/*
35 * Version Information
36 */
37#define DRIVER_VERSION ""
38#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
39#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
40#define DRIVER_LICENSE "GPL"
41
42MODULE_AUTHOR(DRIVER_AUTHOR);
43MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE(DRIVER_LICENSE);
45
a44ebcce 46static const unsigned char usb_kbd_keycode[256] = {
1da177e4
LT
47 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
48 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
49 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
50 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
51 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
52 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
53 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
54 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
55 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
56 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
62 150,158,159,128,136,177,178,176,142,152,173,140
63};
64
65struct usb_kbd {
c5b7c7c3 66 struct input_dev *dev;
1da177e4
LT
67 struct usb_device *usbdev;
68 unsigned char old[8];
69 struct urb *irq, *led;
70 unsigned char newleds;
71 char name[128];
72 char phys[64];
1da177e4
LT
73
74 unsigned char *new;
75 struct usb_ctrlrequest *cr;
76 unsigned char *leds;
1da177e4
LT
77 dma_addr_t new_dma;
78 dma_addr_t leds_dma;
79};
80
7d12e780 81static void usb_kbd_irq(struct urb *urb)
1da177e4
LT
82{
83 struct usb_kbd *kbd = urb->context;
84 int i;
85
86 switch (urb->status) {
87 case 0: /* success */
88 break;
89 case -ECONNRESET: /* unlink */
90 case -ENOENT:
91 case -ESHUTDOWN:
92 return;
93 /* -EPIPE: should clear the halt */
94 default: /* error */
95 goto resubmit;
96 }
97
1da177e4 98 for (i = 0; i < 8; i++)
c5b7c7c3 99 input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
1da177e4
LT
100
101 for (i = 2; i < 8; i++) {
102
103 if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
104 if (usb_kbd_keycode[kbd->old[i]])
c5b7c7c3 105 input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
1da177e4 106 else
ddbe3249
GKH
107 dev_info(&urb->dev->dev,
108 "Unknown key (scancode %#x) released.\n", kbd->old[i]);
1da177e4
LT
109 }
110
111 if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
112 if (usb_kbd_keycode[kbd->new[i]])
c5b7c7c3 113 input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
1da177e4 114 else
ddbe3249
GKH
115 dev_info(&urb->dev->dev,
116 "Unknown key (scancode %#x) released.\n", kbd->new[i]);
1da177e4
LT
117 }
118 }
119
c5b7c7c3 120 input_sync(kbd->dev);
1da177e4
LT
121
122 memcpy(kbd->old, kbd->new, 8);
123
124resubmit:
54e6ecb2 125 i = usb_submit_urb (urb, GFP_ATOMIC);
1da177e4 126 if (i)
58037eb9 127 err_hid ("can't resubmit intr, %s-%s/input0, status %d",
1da177e4
LT
128 kbd->usbdev->bus->bus_name,
129 kbd->usbdev->devpath, i);
130}
131
be5e3383
AB
132static int usb_kbd_event(struct input_dev *dev, unsigned int type,
133 unsigned int code, int value)
1da177e4 134{
e0712985 135 struct usb_kbd *kbd = input_get_drvdata(dev);
1da177e4
LT
136
137 if (type != EV_LED)
138 return -1;
139
1da177e4
LT
140 kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
141 (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
142 (!!test_bit(LED_NUML, dev->led));
143
144 if (kbd->led->status == -EINPROGRESS)
145 return 0;
146
147 if (*(kbd->leds) == kbd->newleds)
148 return 0;
149
150 *(kbd->leds) = kbd->newleds;
151 kbd->led->dev = kbd->usbdev;
152 if (usb_submit_urb(kbd->led, GFP_ATOMIC))
58037eb9 153 err_hid("usb_submit_urb(leds) failed");
1da177e4
LT
154
155 return 0;
156}
157
7d12e780 158static void usb_kbd_led(struct urb *urb)
1da177e4
LT
159{
160 struct usb_kbd *kbd = urb->context;
161
162 if (urb->status)
7d89fe12
GKH
163 dev_warn(&urb->dev->dev, "led urb status %d received\n",
164 urb->status);
05f091ab 165
1da177e4
LT
166 if (*(kbd->leds) == kbd->newleds)
167 return;
168
169 *(kbd->leds) = kbd->newleds;
170 kbd->led->dev = kbd->usbdev;
171 if (usb_submit_urb(kbd->led, GFP_ATOMIC))
58037eb9 172 err_hid("usb_submit_urb(leds) failed");
1da177e4
LT
173}
174
175static int usb_kbd_open(struct input_dev *dev)
176{
e0712985 177 struct usb_kbd *kbd = input_get_drvdata(dev);
1da177e4 178
1da177e4 179 kbd->irq->dev = kbd->usbdev;
65cde54b 180 if (usb_submit_urb(kbd->irq, GFP_KERNEL))
1da177e4 181 return -EIO;
1da177e4
LT
182
183 return 0;
184}
185
186static void usb_kbd_close(struct input_dev *dev)
187{
e0712985 188 struct usb_kbd *kbd = input_get_drvdata(dev);
1da177e4 189
65cde54b 190 usb_kill_urb(kbd->irq);
1da177e4
LT
191}
192
193static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
194{
195 if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
196 return -1;
197 if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
198 return -1;
54e6ecb2 199 if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
1da177e4 200 return -1;
0ede76fc 201 if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
1da177e4 202 return -1;
54e6ecb2 203 if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
1da177e4
LT
204 return -1;
205
206 return 0;
207}
208
209static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
210{
4ba0b2ed
MK
211 usb_free_urb(kbd->irq);
212 usb_free_urb(kbd->led);
6675c5bd 213 usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
0ede76fc 214 kfree(kbd->cr);
6675c5bd 215 usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
1da177e4
LT
216}
217
05f091ab 218static int usb_kbd_probe(struct usb_interface *iface,
1da177e4
LT
219 const struct usb_device_id *id)
220{
c5b7c7c3 221 struct usb_device *dev = interface_to_usbdev(iface);
1da177e4
LT
222 struct usb_host_interface *interface;
223 struct usb_endpoint_descriptor *endpoint;
224 struct usb_kbd *kbd;
c5b7c7c3 225 struct input_dev *input_dev;
1da177e4 226 int i, pipe, maxp;
5d6341c6 227 int error = -ENOMEM;
1da177e4
LT
228
229 interface = iface->cur_altsetting;
230
231 if (interface->desc.bNumEndpoints != 1)
232 return -ENODEV;
233
234 endpoint = &interface->endpoint[0].desc;
a20c3144 235 if (!usb_endpoint_is_int_in(endpoint))
1da177e4
LT
236 return -ENODEV;
237
238 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
239 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
240
c5b7c7c3
DT
241 kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
242 input_dev = input_allocate_device();
243 if (!kbd || !input_dev)
244 goto fail1;
1da177e4 245
c5b7c7c3
DT
246 if (usb_kbd_alloc_mem(dev, kbd))
247 goto fail2;
1da177e4
LT
248
249 kbd->usbdev = dev;
c5b7c7c3
DT
250 kbd->dev = input_dev;
251
252 if (dev->manufacturer)
253 strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
254
255 if (dev->product) {
256 if (dev->manufacturer)
257 strlcat(kbd->name, " ", sizeof(kbd->name));
258 strlcat(kbd->name, dev->product, sizeof(kbd->name));
259 }
260
261 if (!strlen(kbd->name))
262 snprintf(kbd->name, sizeof(kbd->name),
263 "USB HIDBP Keyboard %04x:%04x",
264 le16_to_cpu(dev->descriptor.idVendor),
265 le16_to_cpu(dev->descriptor.idProduct));
266
267 usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
6236dfaa 268 strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
1da177e4 269
c5b7c7c3
DT
270 input_dev->name = kbd->name;
271 input_dev->phys = kbd->phys;
272 usb_to_input_id(dev, &input_dev->id);
e0712985
DT
273 input_dev->dev.parent = &iface->dev;
274
275 input_set_drvdata(input_dev, kbd);
c5b7c7c3 276
7b19ada2
JS
277 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
278 BIT_MASK(EV_REP);
279 input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
280 BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) |
281 BIT_MASK(LED_KANA);
1da177e4
LT
282
283 for (i = 0; i < 255; i++)
c5b7c7c3
DT
284 set_bit(usb_kbd_keycode[i], input_dev->keybit);
285 clear_bit(0, input_dev->keybit);
05f091ab 286
c5b7c7c3
DT
287 input_dev->event = usb_kbd_event;
288 input_dev->open = usb_kbd_open;
289 input_dev->close = usb_kbd_close;
1da177e4
LT
290
291 usb_fill_int_urb(kbd->irq, dev, pipe,
292 kbd->new, (maxp > 8 ? 8 : maxp),
293 usb_kbd_irq, kbd, endpoint->bInterval);
294 kbd->irq->transfer_dma = kbd->new_dma;
295 kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
296
297 kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
298 kbd->cr->bRequest = 0x09;
299 kbd->cr->wValue = cpu_to_le16(0x200);
300 kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
301 kbd->cr->wLength = cpu_to_le16(1);
302
1da177e4
LT
303 usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
304 (void *) kbd->cr, kbd->leds, 1,
305 usb_kbd_led, kbd);
1da177e4 306 kbd->led->transfer_dma = kbd->leds_dma;
0ede76fc 307 kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1da177e4 308
5d6341c6
DT
309 error = input_register_device(kbd->dev);
310 if (error)
311 goto fail2;
1da177e4
LT
312
313 usb_set_intfdata(iface, kbd);
314 return 0;
c5b7c7c3 315
5d6341c6
DT
316fail2:
317 usb_kbd_free_mem(dev, kbd);
318fail1:
319 input_free_device(input_dev);
c5b7c7c3 320 kfree(kbd);
5d6341c6 321 return error;
1da177e4
LT
322}
323
324static void usb_kbd_disconnect(struct usb_interface *intf)
325{
326 struct usb_kbd *kbd = usb_get_intfdata (intf);
05f091ab 327
1da177e4
LT
328 usb_set_intfdata(intf, NULL);
329 if (kbd) {
330 usb_kill_urb(kbd->irq);
c5b7c7c3 331 input_unregister_device(kbd->dev);
1da177e4
LT
332 usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
333 kfree(kbd);
334 }
335}
336
337static struct usb_device_id usb_kbd_id_table [] = {
4ef2e23f
MO
338 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
339 USB_INTERFACE_PROTOCOL_KEYBOARD) },
1da177e4
LT
340 { } /* Terminating entry */
341};
342
343MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
344
345static struct usb_driver usb_kbd_driver = {
1da177e4
LT
346 .name = "usbkbd",
347 .probe = usb_kbd_probe,
348 .disconnect = usb_kbd_disconnect,
349 .id_table = usb_kbd_id_table,
350};
351
352static int __init usb_kbd_init(void)
353{
354 int result = usb_register(&usb_kbd_driver);
355 if (result == 0)
ddbe3249
GKH
356 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
357 DRIVER_DESC "\n");
1da177e4
LT
358 return result;
359}
360
361static void __exit usb_kbd_exit(void)
362{
363 usb_deregister(&usb_kbd_driver);
364}
365
366module_init(usb_kbd_init);
367module_exit(usb_kbd_exit);