xref: /linux/drivers/hid/usbhid/usbkbd.c (revision a44ebccea873cf7d58b63605f1cdd6da9dfec70f)
16db3dfefSJiri Kosina /*
26db3dfefSJiri Kosina  *  Copyright (c) 1999-2001 Vojtech Pavlik
36db3dfefSJiri Kosina  *
46db3dfefSJiri Kosina  *  USB HIDBP Keyboard support
56db3dfefSJiri Kosina  */
66db3dfefSJiri Kosina 
76db3dfefSJiri Kosina /*
86db3dfefSJiri Kosina  * This program is free software; you can redistribute it and/or modify
96db3dfefSJiri Kosina  * it under the terms of the GNU General Public License as published by
106db3dfefSJiri Kosina  * the Free Software Foundation; either version 2 of the License, or
116db3dfefSJiri Kosina  * (at your option) any later version.
126db3dfefSJiri Kosina  *
136db3dfefSJiri Kosina  * This program is distributed in the hope that it will be useful,
146db3dfefSJiri Kosina  * but WITHOUT ANY WARRANTY; without even the implied warranty of
156db3dfefSJiri Kosina  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
166db3dfefSJiri Kosina  * GNU General Public License for more details.
176db3dfefSJiri Kosina  *
186db3dfefSJiri Kosina  * You should have received a copy of the GNU General Public License
196db3dfefSJiri Kosina  * along with this program; if not, write to the Free Software
206db3dfefSJiri Kosina  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
216db3dfefSJiri Kosina  *
226db3dfefSJiri Kosina  * Should you need to contact me, the author, you can do so either by
236db3dfefSJiri Kosina  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
246db3dfefSJiri Kosina  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
256db3dfefSJiri Kosina  */
266db3dfefSJiri Kosina 
276db3dfefSJiri Kosina #include <linux/kernel.h>
286db3dfefSJiri Kosina #include <linux/slab.h>
296db3dfefSJiri Kosina #include <linux/module.h>
306db3dfefSJiri Kosina #include <linux/init.h>
316db3dfefSJiri Kosina #include <linux/usb/input.h>
326db3dfefSJiri Kosina #include <linux/hid.h>
336db3dfefSJiri Kosina 
346db3dfefSJiri Kosina /*
356db3dfefSJiri Kosina  * Version Information
366db3dfefSJiri Kosina  */
376db3dfefSJiri Kosina #define DRIVER_VERSION ""
386db3dfefSJiri Kosina #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
396db3dfefSJiri Kosina #define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
406db3dfefSJiri Kosina #define DRIVER_LICENSE "GPL"
416db3dfefSJiri Kosina 
426db3dfefSJiri Kosina MODULE_AUTHOR(DRIVER_AUTHOR);
436db3dfefSJiri Kosina MODULE_DESCRIPTION(DRIVER_DESC);
446db3dfefSJiri Kosina MODULE_LICENSE(DRIVER_LICENSE);
456db3dfefSJiri Kosina 
46*a44ebcceSMing Lei static const unsigned char usb_kbd_keycode[256] = {
476db3dfefSJiri Kosina 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
486db3dfefSJiri Kosina 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
496db3dfefSJiri Kosina 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
506db3dfefSJiri Kosina 	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
516db3dfefSJiri Kosina 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
526db3dfefSJiri Kosina 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
536db3dfefSJiri Kosina 	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
546db3dfefSJiri Kosina 	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
556db3dfefSJiri Kosina 	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
566db3dfefSJiri Kosina 	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
576db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
586db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
596db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
606db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
616db3dfefSJiri Kosina 	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
626db3dfefSJiri Kosina 	150,158,159,128,136,177,178,176,142,152,173,140
636db3dfefSJiri Kosina };
646db3dfefSJiri Kosina 
656db3dfefSJiri Kosina struct usb_kbd {
666db3dfefSJiri Kosina 	struct input_dev *dev;
676db3dfefSJiri Kosina 	struct usb_device *usbdev;
686db3dfefSJiri Kosina 	unsigned char old[8];
696db3dfefSJiri Kosina 	struct urb *irq, *led;
706db3dfefSJiri Kosina 	unsigned char newleds;
716db3dfefSJiri Kosina 	char name[128];
726db3dfefSJiri Kosina 	char phys[64];
736db3dfefSJiri Kosina 
746db3dfefSJiri Kosina 	unsigned char *new;
756db3dfefSJiri Kosina 	struct usb_ctrlrequest *cr;
766db3dfefSJiri Kosina 	unsigned char *leds;
776db3dfefSJiri Kosina 	dma_addr_t cr_dma;
786db3dfefSJiri Kosina 	dma_addr_t new_dma;
796db3dfefSJiri Kosina 	dma_addr_t leds_dma;
806db3dfefSJiri Kosina };
816db3dfefSJiri Kosina 
826db3dfefSJiri Kosina static void usb_kbd_irq(struct urb *urb)
836db3dfefSJiri Kosina {
846db3dfefSJiri Kosina 	struct usb_kbd *kbd = urb->context;
856db3dfefSJiri Kosina 	int i;
866db3dfefSJiri Kosina 
876db3dfefSJiri Kosina 	switch (urb->status) {
886db3dfefSJiri Kosina 	case 0:			/* success */
896db3dfefSJiri Kosina 		break;
906db3dfefSJiri Kosina 	case -ECONNRESET:	/* unlink */
916db3dfefSJiri Kosina 	case -ENOENT:
926db3dfefSJiri Kosina 	case -ESHUTDOWN:
936db3dfefSJiri Kosina 		return;
946db3dfefSJiri Kosina 	/* -EPIPE:  should clear the halt */
956db3dfefSJiri Kosina 	default:		/* error */
966db3dfefSJiri Kosina 		goto resubmit;
976db3dfefSJiri Kosina 	}
986db3dfefSJiri Kosina 
996db3dfefSJiri Kosina 	for (i = 0; i < 8; i++)
1006db3dfefSJiri Kosina 		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
1016db3dfefSJiri Kosina 
1026db3dfefSJiri Kosina 	for (i = 2; i < 8; i++) {
1036db3dfefSJiri Kosina 
1046db3dfefSJiri Kosina 		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
1056db3dfefSJiri Kosina 			if (usb_kbd_keycode[kbd->old[i]])
1066db3dfefSJiri Kosina 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
1076db3dfefSJiri Kosina 			else
1086db3dfefSJiri Kosina 				info("Unknown key (scancode %#x) released.", kbd->old[i]);
1096db3dfefSJiri Kosina 		}
1106db3dfefSJiri Kosina 
1116db3dfefSJiri Kosina 		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
1126db3dfefSJiri Kosina 			if (usb_kbd_keycode[kbd->new[i]])
1136db3dfefSJiri Kosina 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
1146db3dfefSJiri Kosina 			else
1156db3dfefSJiri Kosina 				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
1166db3dfefSJiri Kosina 		}
1176db3dfefSJiri Kosina 	}
1186db3dfefSJiri Kosina 
1196db3dfefSJiri Kosina 	input_sync(kbd->dev);
1206db3dfefSJiri Kosina 
1216db3dfefSJiri Kosina 	memcpy(kbd->old, kbd->new, 8);
1226db3dfefSJiri Kosina 
1236db3dfefSJiri Kosina resubmit:
1246db3dfefSJiri Kosina 	i = usb_submit_urb (urb, GFP_ATOMIC);
1256db3dfefSJiri Kosina 	if (i)
12658037eb9SJiri Kosina 		err_hid ("can't resubmit intr, %s-%s/input0, status %d",
1276db3dfefSJiri Kosina 				kbd->usbdev->bus->bus_name,
1286db3dfefSJiri Kosina 				kbd->usbdev->devpath, i);
1296db3dfefSJiri Kosina }
1306db3dfefSJiri Kosina 
1316db3dfefSJiri Kosina static int usb_kbd_event(struct input_dev *dev, unsigned int type,
1326db3dfefSJiri Kosina 			 unsigned int code, int value)
1336db3dfefSJiri Kosina {
134e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
1356db3dfefSJiri Kosina 
1366db3dfefSJiri Kosina 	if (type != EV_LED)
1376db3dfefSJiri Kosina 		return -1;
1386db3dfefSJiri Kosina 
1396db3dfefSJiri Kosina 	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
1406db3dfefSJiri Kosina 		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
1416db3dfefSJiri Kosina 		       (!!test_bit(LED_NUML,    dev->led));
1426db3dfefSJiri Kosina 
1436db3dfefSJiri Kosina 	if (kbd->led->status == -EINPROGRESS)
1446db3dfefSJiri Kosina 		return 0;
1456db3dfefSJiri Kosina 
1466db3dfefSJiri Kosina 	if (*(kbd->leds) == kbd->newleds)
1476db3dfefSJiri Kosina 		return 0;
1486db3dfefSJiri Kosina 
1496db3dfefSJiri Kosina 	*(kbd->leds) = kbd->newleds;
1506db3dfefSJiri Kosina 	kbd->led->dev = kbd->usbdev;
1516db3dfefSJiri Kosina 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
15258037eb9SJiri Kosina 		err_hid("usb_submit_urb(leds) failed");
1536db3dfefSJiri Kosina 
1546db3dfefSJiri Kosina 	return 0;
1556db3dfefSJiri Kosina }
1566db3dfefSJiri Kosina 
1576db3dfefSJiri Kosina static void usb_kbd_led(struct urb *urb)
1586db3dfefSJiri Kosina {
1596db3dfefSJiri Kosina 	struct usb_kbd *kbd = urb->context;
1606db3dfefSJiri Kosina 
1616db3dfefSJiri Kosina 	if (urb->status)
1626db3dfefSJiri Kosina 		warn("led urb status %d received", urb->status);
1636db3dfefSJiri Kosina 
1646db3dfefSJiri Kosina 	if (*(kbd->leds) == kbd->newleds)
1656db3dfefSJiri Kosina 		return;
1666db3dfefSJiri Kosina 
1676db3dfefSJiri Kosina 	*(kbd->leds) = kbd->newleds;
1686db3dfefSJiri Kosina 	kbd->led->dev = kbd->usbdev;
1696db3dfefSJiri Kosina 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
17058037eb9SJiri Kosina 		err_hid("usb_submit_urb(leds) failed");
1716db3dfefSJiri Kosina }
1726db3dfefSJiri Kosina 
1736db3dfefSJiri Kosina static int usb_kbd_open(struct input_dev *dev)
1746db3dfefSJiri Kosina {
175e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
1766db3dfefSJiri Kosina 
1776db3dfefSJiri Kosina 	kbd->irq->dev = kbd->usbdev;
1786db3dfefSJiri Kosina 	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
1796db3dfefSJiri Kosina 		return -EIO;
1806db3dfefSJiri Kosina 
1816db3dfefSJiri Kosina 	return 0;
1826db3dfefSJiri Kosina }
1836db3dfefSJiri Kosina 
1846db3dfefSJiri Kosina static void usb_kbd_close(struct input_dev *dev)
1856db3dfefSJiri Kosina {
186e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
1876db3dfefSJiri Kosina 
1886db3dfefSJiri Kosina 	usb_kill_urb(kbd->irq);
1896db3dfefSJiri Kosina }
1906db3dfefSJiri Kosina 
1916db3dfefSJiri Kosina static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
1926db3dfefSJiri Kosina {
1936db3dfefSJiri Kosina 	if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
1946db3dfefSJiri Kosina 		return -1;
1956db3dfefSJiri Kosina 	if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
1966db3dfefSJiri Kosina 		return -1;
1976db3dfefSJiri Kosina 	if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
1986db3dfefSJiri Kosina 		return -1;
1996db3dfefSJiri Kosina 	if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
2006db3dfefSJiri Kosina 		return -1;
2016db3dfefSJiri Kosina 	if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
2026db3dfefSJiri Kosina 		return -1;
2036db3dfefSJiri Kosina 
2046db3dfefSJiri Kosina 	return 0;
2056db3dfefSJiri Kosina }
2066db3dfefSJiri Kosina 
2076db3dfefSJiri Kosina static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
2086db3dfefSJiri Kosina {
2096db3dfefSJiri Kosina 	usb_free_urb(kbd->irq);
2106db3dfefSJiri Kosina 	usb_free_urb(kbd->led);
2116db3dfefSJiri Kosina 	usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
2126db3dfefSJiri Kosina 	usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
2136db3dfefSJiri Kosina 	usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
2146db3dfefSJiri Kosina }
2156db3dfefSJiri Kosina 
2166db3dfefSJiri Kosina static int usb_kbd_probe(struct usb_interface *iface,
2176db3dfefSJiri Kosina 			 const struct usb_device_id *id)
2186db3dfefSJiri Kosina {
2196db3dfefSJiri Kosina 	struct usb_device *dev = interface_to_usbdev(iface);
2206db3dfefSJiri Kosina 	struct usb_host_interface *interface;
2216db3dfefSJiri Kosina 	struct usb_endpoint_descriptor *endpoint;
2226db3dfefSJiri Kosina 	struct usb_kbd *kbd;
2236db3dfefSJiri Kosina 	struct input_dev *input_dev;
2246db3dfefSJiri Kosina 	int i, pipe, maxp;
2255d6341c6SDmitry Torokhov 	int error = -ENOMEM;
2266db3dfefSJiri Kosina 
2276db3dfefSJiri Kosina 	interface = iface->cur_altsetting;
2286db3dfefSJiri Kosina 
2296db3dfefSJiri Kosina 	if (interface->desc.bNumEndpoints != 1)
2306db3dfefSJiri Kosina 		return -ENODEV;
2316db3dfefSJiri Kosina 
2326db3dfefSJiri Kosina 	endpoint = &interface->endpoint[0].desc;
2336db3dfefSJiri Kosina 	if (!usb_endpoint_is_int_in(endpoint))
2346db3dfefSJiri Kosina 		return -ENODEV;
2356db3dfefSJiri Kosina 
236b0e66824SJiri Kosina #ifdef CONFIG_USB_HID
2379f6b3727SPascal Terjan 	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
2389f6b3727SPascal Terjan 				le16_to_cpu(dev->descriptor.idProduct))
2399f6b3727SPascal Terjan 			& HID_QUIRK_IGNORE) {
2409f6b3727SPascal Terjan 		return -ENODEV;
2419f6b3727SPascal Terjan 	}
242b0e66824SJiri Kosina #endif
2439f6b3727SPascal Terjan 
2446db3dfefSJiri Kosina 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
2456db3dfefSJiri Kosina 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
2466db3dfefSJiri Kosina 
2476db3dfefSJiri Kosina 	kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
2486db3dfefSJiri Kosina 	input_dev = input_allocate_device();
2496db3dfefSJiri Kosina 	if (!kbd || !input_dev)
2506db3dfefSJiri Kosina 		goto fail1;
2516db3dfefSJiri Kosina 
2526db3dfefSJiri Kosina 	if (usb_kbd_alloc_mem(dev, kbd))
2536db3dfefSJiri Kosina 		goto fail2;
2546db3dfefSJiri Kosina 
2556db3dfefSJiri Kosina 	kbd->usbdev = dev;
2566db3dfefSJiri Kosina 	kbd->dev = input_dev;
2576db3dfefSJiri Kosina 
2586db3dfefSJiri Kosina 	if (dev->manufacturer)
2596db3dfefSJiri Kosina 		strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
2606db3dfefSJiri Kosina 
2616db3dfefSJiri Kosina 	if (dev->product) {
2626db3dfefSJiri Kosina 		if (dev->manufacturer)
2636db3dfefSJiri Kosina 			strlcat(kbd->name, " ", sizeof(kbd->name));
2646db3dfefSJiri Kosina 		strlcat(kbd->name, dev->product, sizeof(kbd->name));
2656db3dfefSJiri Kosina 	}
2666db3dfefSJiri Kosina 
2676db3dfefSJiri Kosina 	if (!strlen(kbd->name))
2686db3dfefSJiri Kosina 		snprintf(kbd->name, sizeof(kbd->name),
2696db3dfefSJiri Kosina 			 "USB HIDBP Keyboard %04x:%04x",
2706db3dfefSJiri Kosina 			 le16_to_cpu(dev->descriptor.idVendor),
2716db3dfefSJiri Kosina 			 le16_to_cpu(dev->descriptor.idProduct));
2726db3dfefSJiri Kosina 
2736db3dfefSJiri Kosina 	usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
2746db3dfefSJiri Kosina 	strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
2756db3dfefSJiri Kosina 
2766db3dfefSJiri Kosina 	input_dev->name = kbd->name;
2776db3dfefSJiri Kosina 	input_dev->phys = kbd->phys;
2786db3dfefSJiri Kosina 	usb_to_input_id(dev, &input_dev->id);
279e0712985SDmitry Torokhov 	input_dev->dev.parent = &iface->dev;
280e0712985SDmitry Torokhov 
281e0712985SDmitry Torokhov 	input_set_drvdata(input_dev, kbd);
2826db3dfefSJiri Kosina 
2837b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
2847b19ada2SJiri Slaby 		BIT_MASK(EV_REP);
2857b19ada2SJiri Slaby 	input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
2867b19ada2SJiri Slaby 		BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) |
2877b19ada2SJiri Slaby 		BIT_MASK(LED_KANA);
2886db3dfefSJiri Kosina 
2896db3dfefSJiri Kosina 	for (i = 0; i < 255; i++)
2906db3dfefSJiri Kosina 		set_bit(usb_kbd_keycode[i], input_dev->keybit);
2916db3dfefSJiri Kosina 	clear_bit(0, input_dev->keybit);
2926db3dfefSJiri Kosina 
2936db3dfefSJiri Kosina 	input_dev->event = usb_kbd_event;
2946db3dfefSJiri Kosina 	input_dev->open = usb_kbd_open;
2956db3dfefSJiri Kosina 	input_dev->close = usb_kbd_close;
2966db3dfefSJiri Kosina 
2976db3dfefSJiri Kosina 	usb_fill_int_urb(kbd->irq, dev, pipe,
2986db3dfefSJiri Kosina 			 kbd->new, (maxp > 8 ? 8 : maxp),
2996db3dfefSJiri Kosina 			 usb_kbd_irq, kbd, endpoint->bInterval);
3006db3dfefSJiri Kosina 	kbd->irq->transfer_dma = kbd->new_dma;
3016db3dfefSJiri Kosina 	kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
3026db3dfefSJiri Kosina 
3036db3dfefSJiri Kosina 	kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
3046db3dfefSJiri Kosina 	kbd->cr->bRequest = 0x09;
3056db3dfefSJiri Kosina 	kbd->cr->wValue = cpu_to_le16(0x200);
3066db3dfefSJiri Kosina 	kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
3076db3dfefSJiri Kosina 	kbd->cr->wLength = cpu_to_le16(1);
3086db3dfefSJiri Kosina 
3096db3dfefSJiri Kosina 	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
3106db3dfefSJiri Kosina 			     (void *) kbd->cr, kbd->leds, 1,
3116db3dfefSJiri Kosina 			     usb_kbd_led, kbd);
3126db3dfefSJiri Kosina 	kbd->led->setup_dma = kbd->cr_dma;
3136db3dfefSJiri Kosina 	kbd->led->transfer_dma = kbd->leds_dma;
3146db3dfefSJiri Kosina 	kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
3156db3dfefSJiri Kosina 
3165d6341c6SDmitry Torokhov 	error = input_register_device(kbd->dev);
3175d6341c6SDmitry Torokhov 	if (error)
3185d6341c6SDmitry Torokhov 		goto fail2;
3196db3dfefSJiri Kosina 
3206db3dfefSJiri Kosina 	usb_set_intfdata(iface, kbd);
3216db3dfefSJiri Kosina 	return 0;
3226db3dfefSJiri Kosina 
3235d6341c6SDmitry Torokhov fail2:
3245d6341c6SDmitry Torokhov 	usb_kbd_free_mem(dev, kbd);
3255d6341c6SDmitry Torokhov fail1:
3265d6341c6SDmitry Torokhov 	input_free_device(input_dev);
3276db3dfefSJiri Kosina 	kfree(kbd);
3285d6341c6SDmitry Torokhov 	return error;
3296db3dfefSJiri Kosina }
3306db3dfefSJiri Kosina 
3316db3dfefSJiri Kosina static void usb_kbd_disconnect(struct usb_interface *intf)
3326db3dfefSJiri Kosina {
3336db3dfefSJiri Kosina 	struct usb_kbd *kbd = usb_get_intfdata (intf);
3346db3dfefSJiri Kosina 
3356db3dfefSJiri Kosina 	usb_set_intfdata(intf, NULL);
3366db3dfefSJiri Kosina 	if (kbd) {
3376db3dfefSJiri Kosina 		usb_kill_urb(kbd->irq);
3386db3dfefSJiri Kosina 		input_unregister_device(kbd->dev);
3396db3dfefSJiri Kosina 		usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
3406db3dfefSJiri Kosina 		kfree(kbd);
3416db3dfefSJiri Kosina 	}
3426db3dfefSJiri Kosina }
3436db3dfefSJiri Kosina 
3446db3dfefSJiri Kosina static struct usb_device_id usb_kbd_id_table [] = {
3456db3dfefSJiri Kosina 	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
3466db3dfefSJiri Kosina 		USB_INTERFACE_PROTOCOL_KEYBOARD) },
3476db3dfefSJiri Kosina 	{ }						/* Terminating entry */
3486db3dfefSJiri Kosina };
3496db3dfefSJiri Kosina 
3506db3dfefSJiri Kosina MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
3516db3dfefSJiri Kosina 
3526db3dfefSJiri Kosina static struct usb_driver usb_kbd_driver = {
3536db3dfefSJiri Kosina 	.name =		"usbkbd",
3546db3dfefSJiri Kosina 	.probe =	usb_kbd_probe,
3556db3dfefSJiri Kosina 	.disconnect =	usb_kbd_disconnect,
3566db3dfefSJiri Kosina 	.id_table =	usb_kbd_id_table,
3576db3dfefSJiri Kosina };
3586db3dfefSJiri Kosina 
3596db3dfefSJiri Kosina static int __init usb_kbd_init(void)
3606db3dfefSJiri Kosina {
3616db3dfefSJiri Kosina 	int result = usb_register(&usb_kbd_driver);
3626db3dfefSJiri Kosina 	if (result == 0)
3636db3dfefSJiri Kosina 		info(DRIVER_VERSION ":" DRIVER_DESC);
3646db3dfefSJiri Kosina 	return result;
3656db3dfefSJiri Kosina }
3666db3dfefSJiri Kosina 
3676db3dfefSJiri Kosina static void __exit usb_kbd_exit(void)
3686db3dfefSJiri Kosina {
3696db3dfefSJiri Kosina 	usb_deregister(&usb_kbd_driver);
3706db3dfefSJiri Kosina }
3716db3dfefSJiri Kosina 
3726db3dfefSJiri Kosina module_init(usb_kbd_init);
3736db3dfefSJiri Kosina module_exit(usb_kbd_exit);
374