usbkbd.c 11.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 *  Copyright (c) 1999-2001 Vojtech Pavlik
 *
 *  USB HIDBP Keyboard support
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
L
Linus Torvalds 已提交
11
 * (at your option) any later version.
12
 *
L
Linus Torvalds 已提交
13 14 15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
17
 *
L
Linus Torvalds 已提交
18 19 20
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
 *
L
Linus Torvalds 已提交
22 23 24 25 26
 * Should you need to contact me, the author, you can do so either by
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 */

27 28
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

L
Linus Torvalds 已提交
29 30 31 32
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
33
#include <linux/usb/input.h>
34
#include <linux/hid.h>
L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47

/*
 * Version Information
 */
#define DRIVER_VERSION ""
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
#define DRIVER_LICENSE "GPL"

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

48
static const unsigned char usb_kbd_keycode[256] = {
L
Linus Torvalds 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
	150,158,159,128,136,177,178,176,142,152,173,140
};

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

/**
 * struct usb_kbd - state of each attached keyboard
 * @dev:	input device associated with this keyboard
 * @usbdev:	usb device associated with this keyboard
 * @old:	data received in the past from the @irq URB representing which
 *		keys were pressed. By comparing with the current list of keys
 *		that are pressed, we are able to see key releases.
 * @irq:	URB for receiving a list of keys that are pressed when a
 *		new key is pressed or a key that was pressed is released.
 * @led:	URB for sending LEDs (e.g. numlock, ...)
 * @newleds:	data that will be sent with the @led URB representing which LEDs
 		should be on
 * @name:	Name of the keyboard. @dev's name field points to this buffer
 * @phys:	Physical path of the keyboard. @dev's phys field points to this
 *		buffer
 * @new:	Buffer for the @irq URB
 * @cr:		Control request for @led URB
 * @leds:	Buffer for the @led URB
 * @new_dma:	DMA address for @irq URB
 * @leds_dma:	DMA address for @led URB
 * @leds_lock:	spinlock that protects @leds, @newleds, and @led_urb_submitted
 * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been
 *		submitted and its completion handler has not returned yet
 *		without	resubmitting @led
 */
L
Linus Torvalds 已提交
93
struct usb_kbd {
94
	struct input_dev *dev;
L
Linus Torvalds 已提交
95 96 97 98 99 100 101 102 103 104 105 106
	struct usb_device *usbdev;
	unsigned char old[8];
	struct urb *irq, *led;
	unsigned char newleds;
	char name[128];
	char phys[64];

	unsigned char *new;
	struct usb_ctrlrequest *cr;
	unsigned char *leds;
	dma_addr_t new_dma;
	dma_addr_t leds_dma;
107 108 109 110
	
	spinlock_t leds_lock;
	bool led_urb_submitted;

L
Linus Torvalds 已提交
111 112
};

113
static void usb_kbd_irq(struct urb *urb)
L
Linus Torvalds 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
{
	struct usb_kbd *kbd = urb->context;
	int i;

	switch (urb->status) {
	case 0:			/* success */
		break;
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	/* -EPIPE:  should clear the halt */
	default:		/* error */
		goto resubmit;
	}

	for (i = 0; i < 8; i++)
131
		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
L
Linus Torvalds 已提交
132 133 134 135 136

	for (i = 2; i < 8; i++) {

		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
			if (usb_kbd_keycode[kbd->old[i]])
137
				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
L
Linus Torvalds 已提交
138
			else
139 140 141
				hid_info(urb->dev,
					 "Unknown key (scancode %#x) released.\n",
					 kbd->old[i]);
L
Linus Torvalds 已提交
142 143 144 145
		}

		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
			if (usb_kbd_keycode[kbd->new[i]])
146
				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
L
Linus Torvalds 已提交
147
			else
148 149 150
				hid_info(urb->dev,
					 "Unknown key (scancode %#x) released.\n",
					 kbd->new[i]);
L
Linus Torvalds 已提交
151 152 153
		}
	}

154
	input_sync(kbd->dev);
L
Linus Torvalds 已提交
155 156 157 158

	memcpy(kbd->old, kbd->new, 8);

resubmit:
159
	i = usb_submit_urb (urb, GFP_ATOMIC);
L
Linus Torvalds 已提交
160
	if (i)
161 162 163
		hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d",
			kbd->usbdev->bus->bus_name,
			kbd->usbdev->devpath, i);
L
Linus Torvalds 已提交
164 165
}

166 167
static int usb_kbd_event(struct input_dev *dev, unsigned int type,
			 unsigned int code, int value)
L
Linus Torvalds 已提交
168
{
169
	unsigned long flags;
170
	struct usb_kbd *kbd = input_get_drvdata(dev);
L
Linus Torvalds 已提交
171 172 173 174

	if (type != EV_LED)
		return -1;

175
	spin_lock_irqsave(&kbd->leds_lock, flags);
L
Linus Torvalds 已提交
176 177 178 179
	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
		       (!!test_bit(LED_NUML,    dev->led));

180 181
	if (kbd->led_urb_submitted){
		spin_unlock_irqrestore(&kbd->leds_lock, flags);
L
Linus Torvalds 已提交
182
		return 0;
183
	}
L
Linus Torvalds 已提交
184

185 186
	if (*(kbd->leds) == kbd->newleds){
		spin_unlock_irqrestore(&kbd->leds_lock, flags);
L
Linus Torvalds 已提交
187
		return 0;
188
	}
L
Linus Torvalds 已提交
189 190

	*(kbd->leds) = kbd->newleds;
191
	
L
Linus Torvalds 已提交
192 193
	kbd->led->dev = kbd->usbdev;
	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
194
		pr_err("usb_submit_urb(leds) failed\n");
195 196 197 198 199
	else
		kbd->led_urb_submitted = true;
	
	spin_unlock_irqrestore(&kbd->leds_lock, flags);
	
L
Linus Torvalds 已提交
200 201 202
	return 0;
}

203
static void usb_kbd_led(struct urb *urb)
L
Linus Torvalds 已提交
204
{
205
	unsigned long flags;
L
Linus Torvalds 已提交
206 207 208
	struct usb_kbd *kbd = urb->context;

	if (urb->status)
209
		hid_warn(urb->dev, "led urb status %d received\n",
210
			 urb->status);
211

212 213 214 215 216
	spin_lock_irqsave(&kbd->leds_lock, flags);

	if (*(kbd->leds) == kbd->newleds){
		kbd->led_urb_submitted = false;
		spin_unlock_irqrestore(&kbd->leds_lock, flags);
L
Linus Torvalds 已提交
217
		return;
218
	}
L
Linus Torvalds 已提交
219 220

	*(kbd->leds) = kbd->newleds;
221
	
L
Linus Torvalds 已提交
222
	kbd->led->dev = kbd->usbdev;
223
	if (usb_submit_urb(kbd->led, GFP_ATOMIC)){
224
		hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
225 226 227 228
		kbd->led_urb_submitted = false;
	}
	spin_unlock_irqrestore(&kbd->leds_lock, flags);
	
L
Linus Torvalds 已提交
229 230 231 232
}

static int usb_kbd_open(struct input_dev *dev)
{
233
	struct usb_kbd *kbd = input_get_drvdata(dev);
L
Linus Torvalds 已提交
234 235

	kbd->irq->dev = kbd->usbdev;
236
	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
L
Linus Torvalds 已提交
237 238 239 240 241 242 243
		return -EIO;

	return 0;
}

static void usb_kbd_close(struct input_dev *dev)
{
244
	struct usb_kbd *kbd = input_get_drvdata(dev);
L
Linus Torvalds 已提交
245

246
	usb_kill_urb(kbd->irq);
L
Linus Torvalds 已提交
247 248 249 250 251 252 253 254
}

static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
	if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
		return -1;
	if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
		return -1;
255
	if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
L
Linus Torvalds 已提交
256
		return -1;
257
	if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
L
Linus Torvalds 已提交
258
		return -1;
259
	if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
L
Linus Torvalds 已提交
260 261 262 263 264 265 266
		return -1;

	return 0;
}

static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
M
Mariusz Kozlowski 已提交
267 268
	usb_free_urb(kbd->irq);
	usb_free_urb(kbd->led);
269
	usb_free_coherent(dev, 8, kbd->new, kbd->new_dma);
270
	kfree(kbd->cr);
271
	usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma);
L
Linus Torvalds 已提交
272 273
}

274
static int usb_kbd_probe(struct usb_interface *iface,
L
Linus Torvalds 已提交
275 276
			 const struct usb_device_id *id)
{
277
	struct usb_device *dev = interface_to_usbdev(iface);
L
Linus Torvalds 已提交
278 279 280
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_kbd *kbd;
281
	struct input_dev *input_dev;
L
Linus Torvalds 已提交
282
	int i, pipe, maxp;
283
	int error = -ENOMEM;
L
Linus Torvalds 已提交
284 285 286 287 288 289 290

	interface = iface->cur_altsetting;

	if (interface->desc.bNumEndpoints != 1)
		return -ENODEV;

	endpoint = &interface->endpoint[0].desc;
291
	if (!usb_endpoint_is_int_in(endpoint))
L
Linus Torvalds 已提交
292 293 294 295 296
		return -ENODEV;

	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

297 298 299 300
	kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!kbd || !input_dev)
		goto fail1;
L
Linus Torvalds 已提交
301

302 303
	if (usb_kbd_alloc_mem(dev, kbd))
		goto fail2;
L
Linus Torvalds 已提交
304 305

	kbd->usbdev = dev;
306
	kbd->dev = input_dev;
307
	spin_lock_init(&kbd->leds_lock);
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324

	if (dev->manufacturer)
		strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));

	if (dev->product) {
		if (dev->manufacturer)
			strlcat(kbd->name, " ", sizeof(kbd->name));
		strlcat(kbd->name, dev->product, sizeof(kbd->name));
	}

	if (!strlen(kbd->name))
		snprintf(kbd->name, sizeof(kbd->name),
			 "USB HIDBP Keyboard %04x:%04x",
			 le16_to_cpu(dev->descriptor.idVendor),
			 le16_to_cpu(dev->descriptor.idProduct));

	usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
325
	strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
L
Linus Torvalds 已提交
326

327 328 329
	input_dev->name = kbd->name;
	input_dev->phys = kbd->phys;
	usb_to_input_id(dev, &input_dev->id);
330 331 332
	input_dev->dev.parent = &iface->dev;

	input_set_drvdata(input_dev, kbd);
333

334 335 336 337 338
	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
		BIT_MASK(EV_REP);
	input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
		BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) |
		BIT_MASK(LED_KANA);
L
Linus Torvalds 已提交
339 340

	for (i = 0; i < 255; i++)
341 342
		set_bit(usb_kbd_keycode[i], input_dev->keybit);
	clear_bit(0, input_dev->keybit);
343

344 345 346
	input_dev->event = usb_kbd_event;
	input_dev->open = usb_kbd_open;
	input_dev->close = usb_kbd_close;
L
Linus Torvalds 已提交
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

	usb_fill_int_urb(kbd->irq, dev, pipe,
			 kbd->new, (maxp > 8 ? 8 : maxp),
			 usb_kbd_irq, kbd, endpoint->bInterval);
	kbd->irq->transfer_dma = kbd->new_dma;
	kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
	kbd->cr->bRequest = 0x09;
	kbd->cr->wValue = cpu_to_le16(0x200);
	kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
	kbd->cr->wLength = cpu_to_le16(1);

	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
			     (void *) kbd->cr, kbd->leds, 1,
			     usb_kbd_led, kbd);
	kbd->led->transfer_dma = kbd->leds_dma;
364
	kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
L
Linus Torvalds 已提交
365

366 367 368
	error = input_register_device(kbd->dev);
	if (error)
		goto fail2;
L
Linus Torvalds 已提交
369 370

	usb_set_intfdata(iface, kbd);
371
	device_set_wakeup_enable(&dev->dev, 1);
L
Linus Torvalds 已提交
372
	return 0;
373

374 375 376 377
fail2:	
	usb_kbd_free_mem(dev, kbd);
fail1:	
	input_free_device(input_dev);
378
	kfree(kbd);
379
	return error;
L
Linus Torvalds 已提交
380 381 382 383 384
}

static void usb_kbd_disconnect(struct usb_interface *intf)
{
	struct usb_kbd *kbd = usb_get_intfdata (intf);
385

L
Linus Torvalds 已提交
386 387 388
	usb_set_intfdata(intf, NULL);
	if (kbd) {
		usb_kill_urb(kbd->irq);
389
		input_unregister_device(kbd->dev);
390
		usb_kill_urb(kbd->led);
L
Linus Torvalds 已提交
391 392 393 394 395 396
		usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
		kfree(kbd);
	}
}

static struct usb_device_id usb_kbd_id_table [] = {
397 398
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_KEYBOARD) },
L
Linus Torvalds 已提交
399 400 401 402 403 404 405 406 407 408 409 410
	{ }						/* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);

static struct usb_driver usb_kbd_driver = {
	.name =		"usbkbd",
	.probe =	usb_kbd_probe,
	.disconnect =	usb_kbd_disconnect,
	.id_table =	usb_kbd_id_table,
};

411
module_usb_driver(usb_kbd_driver);