xref: /openbmc/linux/drivers/hid/usbhid/usbkbd.c (revision eeeec27d)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
26db3dfefSJiri Kosina /*
36db3dfefSJiri Kosina  *  Copyright (c) 1999-2001 Vojtech Pavlik
46db3dfefSJiri Kosina  *
56db3dfefSJiri Kosina  *  USB HIDBP Keyboard support
66db3dfefSJiri Kosina  */
76db3dfefSJiri Kosina 
86db3dfefSJiri Kosina /*
96db3dfefSJiri Kosina  *
106db3dfefSJiri Kosina  * Should you need to contact me, the author, you can do so either by
116db3dfefSJiri Kosina  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
126db3dfefSJiri Kosina  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
136db3dfefSJiri Kosina  */
146db3dfefSJiri Kosina 
154291ee30SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
164291ee30SJoe Perches 
176db3dfefSJiri Kosina #include <linux/kernel.h>
186db3dfefSJiri Kosina #include <linux/slab.h>
196db3dfefSJiri Kosina #include <linux/module.h>
206db3dfefSJiri Kosina #include <linux/init.h>
216db3dfefSJiri Kosina #include <linux/usb/input.h>
226db3dfefSJiri Kosina #include <linux/hid.h>
236db3dfefSJiri Kosina 
246db3dfefSJiri Kosina /*
256db3dfefSJiri Kosina  * Version Information
266db3dfefSJiri Kosina  */
276db3dfefSJiri Kosina #define DRIVER_VERSION ""
286db3dfefSJiri Kosina #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
296db3dfefSJiri Kosina #define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
306db3dfefSJiri Kosina 
316db3dfefSJiri Kosina MODULE_AUTHOR(DRIVER_AUTHOR);
326db3dfefSJiri Kosina MODULE_DESCRIPTION(DRIVER_DESC);
337021b600SGrant Grundler MODULE_LICENSE("GPL");
346db3dfefSJiri Kosina 
35a44ebcceSMing Lei static const unsigned char usb_kbd_keycode[256] = {
366db3dfefSJiri Kosina 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
376db3dfefSJiri Kosina 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
386db3dfefSJiri Kosina 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
396db3dfefSJiri Kosina 	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
406db3dfefSJiri Kosina 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
416db3dfefSJiri Kosina 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
426db3dfefSJiri Kosina 	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
436db3dfefSJiri Kosina 	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
446db3dfefSJiri Kosina 	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
456db3dfefSJiri Kosina 	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
466db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
476db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
486db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
496db3dfefSJiri Kosina 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
506db3dfefSJiri Kosina 	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
516db3dfefSJiri Kosina 	150,158,159,128,136,177,178,176,142,152,173,140
526db3dfefSJiri Kosina };
536db3dfefSJiri Kosina 
54c196adf8SWillem Penninckx 
55c196adf8SWillem Penninckx /**
56c196adf8SWillem Penninckx  * struct usb_kbd - state of each attached keyboard
57c196adf8SWillem Penninckx  * @dev:	input device associated with this keyboard
58c196adf8SWillem Penninckx  * @usbdev:	usb device associated with this keyboard
59c196adf8SWillem Penninckx  * @old:	data received in the past from the @irq URB representing which
60c196adf8SWillem Penninckx  *		keys were pressed. By comparing with the current list of keys
61c196adf8SWillem Penninckx  *		that are pressed, we are able to see key releases.
62c196adf8SWillem Penninckx  * @irq:	URB for receiving a list of keys that are pressed when a
63c196adf8SWillem Penninckx  *		new key is pressed or a key that was pressed is released.
64c196adf8SWillem Penninckx  * @led:	URB for sending LEDs (e.g. numlock, ...)
65c196adf8SWillem Penninckx  * @newleds:	data that will be sent with the @led URB representing which LEDs
664cbf8aa7SLee Jones  *		should be on
67c196adf8SWillem Penninckx  * @name:	Name of the keyboard. @dev's name field points to this buffer
68c196adf8SWillem Penninckx  * @phys:	Physical path of the keyboard. @dev's phys field points to this
69c196adf8SWillem Penninckx  *		buffer
70c196adf8SWillem Penninckx  * @new:	Buffer for the @irq URB
71c196adf8SWillem Penninckx  * @cr:		Control request for @led URB
72c196adf8SWillem Penninckx  * @leds:	Buffer for the @led URB
73c196adf8SWillem Penninckx  * @new_dma:	DMA address for @irq URB
74c196adf8SWillem Penninckx  * @leds_dma:	DMA address for @led URB
75c196adf8SWillem Penninckx  * @leds_lock:	spinlock that protects @leds, @newleds, and @led_urb_submitted
76c196adf8SWillem Penninckx  * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been
77c196adf8SWillem Penninckx  *		submitted and its completion handler has not returned yet
78c196adf8SWillem Penninckx  *		without	resubmitting @led
79c196adf8SWillem Penninckx  */
806db3dfefSJiri Kosina struct usb_kbd {
816db3dfefSJiri Kosina 	struct input_dev *dev;
826db3dfefSJiri Kosina 	struct usb_device *usbdev;
836db3dfefSJiri Kosina 	unsigned char old[8];
846db3dfefSJiri Kosina 	struct urb *irq, *led;
856db3dfefSJiri Kosina 	unsigned char newleds;
866db3dfefSJiri Kosina 	char name[128];
876db3dfefSJiri Kosina 	char phys[64];
886db3dfefSJiri Kosina 
896db3dfefSJiri Kosina 	unsigned char *new;
906db3dfefSJiri Kosina 	struct usb_ctrlrequest *cr;
916db3dfefSJiri Kosina 	unsigned char *leds;
926db3dfefSJiri Kosina 	dma_addr_t new_dma;
936db3dfefSJiri Kosina 	dma_addr_t leds_dma;
94c196adf8SWillem Penninckx 
95c196adf8SWillem Penninckx 	spinlock_t leds_lock;
96c196adf8SWillem Penninckx 	bool led_urb_submitted;
97c196adf8SWillem Penninckx 
986db3dfefSJiri Kosina };
996db3dfefSJiri Kosina 
usb_kbd_irq(struct urb * urb)1006db3dfefSJiri Kosina static void usb_kbd_irq(struct urb *urb)
1016db3dfefSJiri Kosina {
1026db3dfefSJiri Kosina 	struct usb_kbd *kbd = urb->context;
1036db3dfefSJiri Kosina 	int i;
1046db3dfefSJiri Kosina 
1056db3dfefSJiri Kosina 	switch (urb->status) {
1066db3dfefSJiri Kosina 	case 0:			/* success */
1076db3dfefSJiri Kosina 		break;
1086db3dfefSJiri Kosina 	case -ECONNRESET:	/* unlink */
1096db3dfefSJiri Kosina 	case -ENOENT:
1106db3dfefSJiri Kosina 	case -ESHUTDOWN:
1116db3dfefSJiri Kosina 		return;
1126db3dfefSJiri Kosina 	/* -EPIPE:  should clear the halt */
1136db3dfefSJiri Kosina 	default:		/* error */
1146db3dfefSJiri Kosina 		goto resubmit;
1156db3dfefSJiri Kosina 	}
1166db3dfefSJiri Kosina 
1176db3dfefSJiri Kosina 	for (i = 0; i < 8; i++)
1186db3dfefSJiri Kosina 		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
1196db3dfefSJiri Kosina 
1206db3dfefSJiri Kosina 	for (i = 2; i < 8; i++) {
1216db3dfefSJiri Kosina 
1226db3dfefSJiri Kosina 		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
1236db3dfefSJiri Kosina 			if (usb_kbd_keycode[kbd->old[i]])
1246db3dfefSJiri Kosina 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
1256db3dfefSJiri Kosina 			else
1264291ee30SJoe Perches 				hid_info(urb->dev,
1274291ee30SJoe Perches 					 "Unknown key (scancode %#x) released.\n",
1284291ee30SJoe Perches 					 kbd->old[i]);
1296db3dfefSJiri Kosina 		}
1306db3dfefSJiri Kosina 
1316db3dfefSJiri Kosina 		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
1326db3dfefSJiri Kosina 			if (usb_kbd_keycode[kbd->new[i]])
1336db3dfefSJiri Kosina 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
1346db3dfefSJiri Kosina 			else
1354291ee30SJoe Perches 				hid_info(urb->dev,
1369fee8240SAdam Cozzette 					 "Unknown key (scancode %#x) pressed.\n",
1374291ee30SJoe Perches 					 kbd->new[i]);
1386db3dfefSJiri Kosina 		}
1396db3dfefSJiri Kosina 	}
1406db3dfefSJiri Kosina 
1416db3dfefSJiri Kosina 	input_sync(kbd->dev);
1426db3dfefSJiri Kosina 
1436db3dfefSJiri Kosina 	memcpy(kbd->old, kbd->new, 8);
1446db3dfefSJiri Kosina 
1456db3dfefSJiri Kosina resubmit:
1466db3dfefSJiri Kosina 	i = usb_submit_urb (urb, GFP_ATOMIC);
1476db3dfefSJiri Kosina 	if (i)
1484291ee30SJoe Perches 		hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d",
1496db3dfefSJiri Kosina 			kbd->usbdev->bus->bus_name,
1506db3dfefSJiri Kosina 			kbd->usbdev->devpath, i);
1516db3dfefSJiri Kosina }
1526db3dfefSJiri Kosina 
usb_kbd_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)1536db3dfefSJiri Kosina static int usb_kbd_event(struct input_dev *dev, unsigned int type,
1546db3dfefSJiri Kosina 			 unsigned int code, int value)
1556db3dfefSJiri Kosina {
156c196adf8SWillem Penninckx 	unsigned long flags;
157e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
1586db3dfefSJiri Kosina 
1596db3dfefSJiri Kosina 	if (type != EV_LED)
1606db3dfefSJiri Kosina 		return -1;
1616db3dfefSJiri Kosina 
162c196adf8SWillem Penninckx 	spin_lock_irqsave(&kbd->leds_lock, flags);
1636db3dfefSJiri Kosina 	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
1646db3dfefSJiri Kosina 		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
1656db3dfefSJiri Kosina 		       (!!test_bit(LED_NUML,    dev->led));
1666db3dfefSJiri Kosina 
167c196adf8SWillem Penninckx 	if (kbd->led_urb_submitted){
168c196adf8SWillem Penninckx 		spin_unlock_irqrestore(&kbd->leds_lock, flags);
1696db3dfefSJiri Kosina 		return 0;
170c196adf8SWillem Penninckx 	}
1716db3dfefSJiri Kosina 
172c196adf8SWillem Penninckx 	if (*(kbd->leds) == kbd->newleds){
173c196adf8SWillem Penninckx 		spin_unlock_irqrestore(&kbd->leds_lock, flags);
1746db3dfefSJiri Kosina 		return 0;
175c196adf8SWillem Penninckx 	}
1766db3dfefSJiri Kosina 
1776db3dfefSJiri Kosina 	*(kbd->leds) = kbd->newleds;
178c196adf8SWillem Penninckx 
1796db3dfefSJiri Kosina 	kbd->led->dev = kbd->usbdev;
1806db3dfefSJiri Kosina 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
1814291ee30SJoe Perches 		pr_err("usb_submit_urb(leds) failed\n");
182c196adf8SWillem Penninckx 	else
183c196adf8SWillem Penninckx 		kbd->led_urb_submitted = true;
184c196adf8SWillem Penninckx 
185c196adf8SWillem Penninckx 	spin_unlock_irqrestore(&kbd->leds_lock, flags);
1866db3dfefSJiri Kosina 
1876db3dfefSJiri Kosina 	return 0;
1886db3dfefSJiri Kosina }
1896db3dfefSJiri Kosina 
usb_kbd_led(struct urb * urb)1906db3dfefSJiri Kosina static void usb_kbd_led(struct urb *urb)
1916db3dfefSJiri Kosina {
192c196adf8SWillem Penninckx 	unsigned long flags;
1936db3dfefSJiri Kosina 	struct usb_kbd *kbd = urb->context;
1946db3dfefSJiri Kosina 
1956db3dfefSJiri Kosina 	if (urb->status)
1964291ee30SJoe Perches 		hid_warn(urb->dev, "led urb status %d received\n",
1977d89fe12SFrom: Greg Kroah-Hartman 			 urb->status);
1986db3dfefSJiri Kosina 
199c196adf8SWillem Penninckx 	spin_lock_irqsave(&kbd->leds_lock, flags);
200c196adf8SWillem Penninckx 
201c196adf8SWillem Penninckx 	if (*(kbd->leds) == kbd->newleds){
202c196adf8SWillem Penninckx 		kbd->led_urb_submitted = false;
203c196adf8SWillem Penninckx 		spin_unlock_irqrestore(&kbd->leds_lock, flags);
2046db3dfefSJiri Kosina 		return;
205c196adf8SWillem Penninckx 	}
2066db3dfefSJiri Kosina 
2076db3dfefSJiri Kosina 	*(kbd->leds) = kbd->newleds;
208c196adf8SWillem Penninckx 
2096db3dfefSJiri Kosina 	kbd->led->dev = kbd->usbdev;
210c196adf8SWillem Penninckx 	if (usb_submit_urb(kbd->led, GFP_ATOMIC)){
2114291ee30SJoe Perches 		hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
212c196adf8SWillem Penninckx 		kbd->led_urb_submitted = false;
213c196adf8SWillem Penninckx 	}
214c196adf8SWillem Penninckx 	spin_unlock_irqrestore(&kbd->leds_lock, flags);
215c196adf8SWillem Penninckx 
2166db3dfefSJiri Kosina }
2176db3dfefSJiri Kosina 
usb_kbd_open(struct input_dev * dev)2186db3dfefSJiri Kosina static int usb_kbd_open(struct input_dev *dev)
2196db3dfefSJiri Kosina {
220e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
2216db3dfefSJiri Kosina 
2226db3dfefSJiri Kosina 	kbd->irq->dev = kbd->usbdev;
2236db3dfefSJiri Kosina 	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
2246db3dfefSJiri Kosina 		return -EIO;
2256db3dfefSJiri Kosina 
2266db3dfefSJiri Kosina 	return 0;
2276db3dfefSJiri Kosina }
2286db3dfefSJiri Kosina 
usb_kbd_close(struct input_dev * dev)2296db3dfefSJiri Kosina static void usb_kbd_close(struct input_dev *dev)
2306db3dfefSJiri Kosina {
231e0712985SDmitry Torokhov 	struct usb_kbd *kbd = input_get_drvdata(dev);
2326db3dfefSJiri Kosina 
2336db3dfefSJiri Kosina 	usb_kill_urb(kbd->irq);
2346db3dfefSJiri Kosina }
2356db3dfefSJiri Kosina 
usb_kbd_alloc_mem(struct usb_device * dev,struct usb_kbd * kbd)2366db3dfefSJiri Kosina static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
2376db3dfefSJiri Kosina {
2386db3dfefSJiri Kosina 	if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
2396db3dfefSJiri Kosina 		return -1;
2406db3dfefSJiri Kosina 	if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
2416db3dfefSJiri Kosina 		return -1;
242a3af901cSHyeonggon Yoo 	if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbd->new_dma)))
2436db3dfefSJiri Kosina 		return -1;
2440ede76fcSAlan Stern 	if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
2456db3dfefSJiri Kosina 		return -1;
246a3af901cSHyeonggon Yoo 	if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_KERNEL, &kbd->leds_dma)))
2476db3dfefSJiri Kosina 		return -1;
2486db3dfefSJiri Kosina 
2496db3dfefSJiri Kosina 	return 0;
2506db3dfefSJiri Kosina }
2516db3dfefSJiri Kosina 
usb_kbd_free_mem(struct usb_device * dev,struct usb_kbd * kbd)2526db3dfefSJiri Kosina static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
2536db3dfefSJiri Kosina {
2546db3dfefSJiri Kosina 	usb_free_urb(kbd->irq);
2556db3dfefSJiri Kosina 	usb_free_urb(kbd->led);
256997ea58eSDaniel Mack 	usb_free_coherent(dev, 8, kbd->new, kbd->new_dma);
2570ede76fcSAlan Stern 	kfree(kbd->cr);
258997ea58eSDaniel Mack 	usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma);
2596db3dfefSJiri Kosina }
2606db3dfefSJiri Kosina 
usb_kbd_probe(struct usb_interface * iface,const struct usb_device_id * id)2616db3dfefSJiri Kosina static int usb_kbd_probe(struct usb_interface *iface,
2626db3dfefSJiri Kosina 			 const struct usb_device_id *id)
2636db3dfefSJiri Kosina {
2646db3dfefSJiri Kosina 	struct usb_device *dev = interface_to_usbdev(iface);
2656db3dfefSJiri Kosina 	struct usb_host_interface *interface;
2666db3dfefSJiri Kosina 	struct usb_endpoint_descriptor *endpoint;
2676db3dfefSJiri Kosina 	struct usb_kbd *kbd;
2686db3dfefSJiri Kosina 	struct input_dev *input_dev;
2696db3dfefSJiri Kosina 	int i, pipe, maxp;
2705d6341c6SDmitry Torokhov 	int error = -ENOMEM;
2716db3dfefSJiri Kosina 
2726db3dfefSJiri Kosina 	interface = iface->cur_altsetting;
2736db3dfefSJiri Kosina 
2746db3dfefSJiri Kosina 	if (interface->desc.bNumEndpoints != 1)
2756db3dfefSJiri Kosina 		return -ENODEV;
2766db3dfefSJiri Kosina 
2776db3dfefSJiri Kosina 	endpoint = &interface->endpoint[0].desc;
2786db3dfefSJiri Kosina 	if (!usb_endpoint_is_int_in(endpoint))
2796db3dfefSJiri Kosina 		return -ENODEV;
2806db3dfefSJiri Kosina 
2816db3dfefSJiri Kosina 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
282b45cde33SVincent Mailhol 	maxp = usb_maxpacket(dev, pipe);
2836db3dfefSJiri Kosina 
2846db3dfefSJiri Kosina 	kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
2856db3dfefSJiri Kosina 	input_dev = input_allocate_device();
2866db3dfefSJiri Kosina 	if (!kbd || !input_dev)
2876db3dfefSJiri Kosina 		goto fail1;
2886db3dfefSJiri Kosina 
2896db3dfefSJiri Kosina 	if (usb_kbd_alloc_mem(dev, kbd))
2906db3dfefSJiri Kosina 		goto fail2;
2916db3dfefSJiri Kosina 
2926db3dfefSJiri Kosina 	kbd->usbdev = dev;
2936db3dfefSJiri Kosina 	kbd->dev = input_dev;
294c196adf8SWillem Penninckx 	spin_lock_init(&kbd->leds_lock);
2956db3dfefSJiri Kosina 
2966db3dfefSJiri Kosina 	if (dev->manufacturer)
297*eeeec27dSWolfram Sang 		strscpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
2986db3dfefSJiri Kosina 
2996db3dfefSJiri Kosina 	if (dev->product) {
3006db3dfefSJiri Kosina 		if (dev->manufacturer)
3016db3dfefSJiri Kosina 			strlcat(kbd->name, " ", sizeof(kbd->name));
3026db3dfefSJiri Kosina 		strlcat(kbd->name, dev->product, sizeof(kbd->name));
3036db3dfefSJiri Kosina 	}
3046db3dfefSJiri Kosina 
3056db3dfefSJiri Kosina 	if (!strlen(kbd->name))
3066db3dfefSJiri Kosina 		snprintf(kbd->name, sizeof(kbd->name),
3076db3dfefSJiri Kosina 			 "USB HIDBP Keyboard %04x:%04x",
3086db3dfefSJiri Kosina 			 le16_to_cpu(dev->descriptor.idVendor),
3096db3dfefSJiri Kosina 			 le16_to_cpu(dev->descriptor.idProduct));
3106db3dfefSJiri Kosina 
3116db3dfefSJiri Kosina 	usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
3126236dfaaSMárton Németh 	strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
3136db3dfefSJiri Kosina 
3146db3dfefSJiri Kosina 	input_dev->name = kbd->name;
3156db3dfefSJiri Kosina 	input_dev->phys = kbd->phys;
3166db3dfefSJiri Kosina 	usb_to_input_id(dev, &input_dev->id);
317e0712985SDmitry Torokhov 	input_dev->dev.parent = &iface->dev;
318e0712985SDmitry Torokhov 
319e0712985SDmitry Torokhov 	input_set_drvdata(input_dev, kbd);
3206db3dfefSJiri Kosina 
3217b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
3227b19ada2SJiri Slaby 		BIT_MASK(EV_REP);
3237b19ada2SJiri Slaby 	input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
3247b19ada2SJiri Slaby 		BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) |
3257b19ada2SJiri Slaby 		BIT_MASK(LED_KANA);
3266db3dfefSJiri Kosina 
3276db3dfefSJiri Kosina 	for (i = 0; i < 255; i++)
3286db3dfefSJiri Kosina 		set_bit(usb_kbd_keycode[i], input_dev->keybit);
3296db3dfefSJiri Kosina 	clear_bit(0, input_dev->keybit);
3306db3dfefSJiri Kosina 
3316db3dfefSJiri Kosina 	input_dev->event = usb_kbd_event;
3326db3dfefSJiri Kosina 	input_dev->open = usb_kbd_open;
3336db3dfefSJiri Kosina 	input_dev->close = usb_kbd_close;
3346db3dfefSJiri Kosina 
3356db3dfefSJiri Kosina 	usb_fill_int_urb(kbd->irq, dev, pipe,
3366db3dfefSJiri Kosina 			 kbd->new, (maxp > 8 ? 8 : maxp),
3376db3dfefSJiri Kosina 			 usb_kbd_irq, kbd, endpoint->bInterval);
3386db3dfefSJiri Kosina 	kbd->irq->transfer_dma = kbd->new_dma;
3396db3dfefSJiri Kosina 	kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
3406db3dfefSJiri Kosina 
3416db3dfefSJiri Kosina 	kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
3426db3dfefSJiri Kosina 	kbd->cr->bRequest = 0x09;
3436db3dfefSJiri Kosina 	kbd->cr->wValue = cpu_to_le16(0x200);
3446db3dfefSJiri Kosina 	kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
3456db3dfefSJiri Kosina 	kbd->cr->wLength = cpu_to_le16(1);
3466db3dfefSJiri Kosina 
3476db3dfefSJiri Kosina 	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
3486db3dfefSJiri Kosina 			     (void *) kbd->cr, kbd->leds, 1,
3496db3dfefSJiri Kosina 			     usb_kbd_led, kbd);
3506db3dfefSJiri Kosina 	kbd->led->transfer_dma = kbd->leds_dma;
3510ede76fcSAlan Stern 	kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
3526db3dfefSJiri Kosina 
3535d6341c6SDmitry Torokhov 	error = input_register_device(kbd->dev);
3545d6341c6SDmitry Torokhov 	if (error)
3555d6341c6SDmitry Torokhov 		goto fail2;
3566db3dfefSJiri Kosina 
3576db3dfefSJiri Kosina 	usb_set_intfdata(iface, kbd);
3583d61510fSAlan Stern 	device_set_wakeup_enable(&dev->dev, 1);
3596db3dfefSJiri Kosina 	return 0;
3606db3dfefSJiri Kosina 
3615d6341c6SDmitry Torokhov fail2:
3625d6341c6SDmitry Torokhov 	usb_kbd_free_mem(dev, kbd);
3635d6341c6SDmitry Torokhov fail1:
3645d6341c6SDmitry Torokhov 	input_free_device(input_dev);
3656db3dfefSJiri Kosina 	kfree(kbd);
3665d6341c6SDmitry Torokhov 	return error;
3676db3dfefSJiri Kosina }
3686db3dfefSJiri Kosina 
usb_kbd_disconnect(struct usb_interface * intf)3696db3dfefSJiri Kosina static void usb_kbd_disconnect(struct usb_interface *intf)
3706db3dfefSJiri Kosina {
3716db3dfefSJiri Kosina 	struct usb_kbd *kbd = usb_get_intfdata (intf);
3726db3dfefSJiri Kosina 
3736db3dfefSJiri Kosina 	usb_set_intfdata(intf, NULL);
3746db3dfefSJiri Kosina 	if (kbd) {
3756db3dfefSJiri Kosina 		usb_kill_urb(kbd->irq);
3766db3dfefSJiri Kosina 		input_unregister_device(kbd->dev);
377a2b2c20bSWillem Penninckx 		usb_kill_urb(kbd->led);
3786db3dfefSJiri Kosina 		usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
3796db3dfefSJiri Kosina 		kfree(kbd);
3806db3dfefSJiri Kosina 	}
3816db3dfefSJiri Kosina }
3826db3dfefSJiri Kosina 
38346cb3cf8SArvind Yadav static const struct usb_device_id usb_kbd_id_table[] = {
3846db3dfefSJiri Kosina 	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
3856db3dfefSJiri Kosina 		USB_INTERFACE_PROTOCOL_KEYBOARD) },
3866db3dfefSJiri Kosina 	{ }						/* Terminating entry */
3876db3dfefSJiri Kosina };
3886db3dfefSJiri Kosina 
3896db3dfefSJiri Kosina MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
3906db3dfefSJiri Kosina 
3916db3dfefSJiri Kosina static struct usb_driver usb_kbd_driver = {
3926db3dfefSJiri Kosina 	.name =		"usbkbd",
3936db3dfefSJiri Kosina 	.probe =	usb_kbd_probe,
3946db3dfefSJiri Kosina 	.disconnect =	usb_kbd_disconnect,
3956db3dfefSJiri Kosina 	.id_table =	usb_kbd_id_table,
3966db3dfefSJiri Kosina };
3976db3dfefSJiri Kosina 
39842f06a13SGreg Kroah-Hartman module_usb_driver(usb_kbd_driver);
399