Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e1e6325 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input: (24 commits)
  Input: ati_remote - use msec instead of jiffies
  Input: ati_remote - add missing input_sync()
  Input: ati_remote - relax permissions sysfs module parameters
  Input: ati_remote - make filter time a module parameter
  Input: atkbd - restore repeat rate when resuming
  Input: trackpoint - activate protocol when resuming
  Input: logips2pp - fix button mapping for MX300
  Input: keyboard - change to use kzalloc
  Input: serio/gameport - check whether driver core calls succeeded
  Input: spaceball - make 4000FLX Lefty work
  Input: keyboard - simplify emulate_raw() implementation
  Input: keyboard - remove static variable and clean up initialization
  Input: hiddev - use standard list implementation
  Input: add missing handler->start() call
  Input: HID - fix potential out-of-bound array access
  Input: fix list iteration in input_release_device()
  Input: iforce - add Trust Force Feedback Race Master support
  Input: iforce - check array bounds before accessing elements
  Input: libps2 - warn instead of oopsing when passed bad arguments
  Input: fm801-gp - fix use after free
  ...
parents a05ef8bf 2ffc1cca
Loading
Loading
Loading
Loading
+78 −61
Original line number Diff line number Diff line
@@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);

struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
static struct kbd_struct kbd0;

int spawnpid, spawnsig;

@@ -227,9 +226,9 @@ static void kd_nosound(unsigned long ignored)
		struct input_handle *handle = to_handle_h(node);
		if (test_bit(EV_SND, handle->dev->evbit)) {
			if (test_bit(SND_TONE, handle->dev->sndbit))
				input_event(handle->dev, EV_SND, SND_TONE, 0);
				input_inject_event(handle, EV_SND, SND_TONE, 0);
			if (test_bit(SND_BELL, handle->dev->sndbit))
				input_event(handle->dev, EV_SND, SND_BELL, 0);
				input_inject_event(handle, EV_SND, SND_BELL, 0);
		}
	}
}
@@ -247,11 +246,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
			struct input_handle *handle = to_handle_h(node);
			if (test_bit(EV_SND, handle->dev->evbit)) {
				if (test_bit(SND_TONE, handle->dev->sndbit)) {
					input_event(handle->dev, EV_SND, SND_TONE, hz);
					input_inject_event(handle, EV_SND, SND_TONE, hz);
					break;
				}
				if (test_bit(SND_BELL, handle->dev->sndbit)) {
					input_event(handle->dev, EV_SND, SND_BELL, 1);
					input_inject_event(handle, EV_SND, SND_BELL, 1);
					break;
				}
			}
@@ -278,9 +277,9 @@ int kbd_rate(struct kbd_repeat *rep)

		if (test_bit(EV_REP, dev->evbit)) {
			if (rep->delay > 0)
				input_event(dev, EV_REP, REP_DELAY, rep->delay);
				input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
			if (rep->period > 0)
				input_event(dev, EV_REP, REP_PERIOD, rep->period);
				input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
			d = dev->rep[REP_DELAY];
			p = dev->rep[REP_PERIOD];
		}
@@ -988,7 +987,7 @@ static inline unsigned char getleds(void)
 * interrupt routines for this thing allows us to easily mask
 * this when we don't want any of the above to happen.
 * This allows for easy and efficient race-condition prevention
 * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
 * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
 */

static void kbd_bh(unsigned long dummy)
@@ -999,10 +998,10 @@ static void kbd_bh(unsigned long dummy)
	if (leds != ledstate) {
		list_for_each(node, &kbd_handler.h_list) {
			struct input_handle *handle = to_handle_h(node);
			input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
			input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
			input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
			input_sync(handle->dev);
			input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
			input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
			input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
			input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
		}
	}

@@ -1011,23 +1010,6 @@ static void kbd_bh(unsigned long dummy)

DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);

/*
 * This allows a newly plugged keyboard to pick the LED state.
 */
static void kbd_refresh_leds(struct input_handle *handle)
{
	unsigned char leds = ledstate;

	tasklet_disable(&keyboard_tasklet);
	if (leds != 0xff) {
		input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
		input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
		input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
		input_sync(handle->dev);
	}
	tasklet_enable(&keyboard_tasklet);
}

#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
    defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
    defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
@@ -1043,7 +1025,7 @@ static const unsigned short x86_keycodes[256] =
	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
	 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
	284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
	103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -1065,38 +1047,55 @@ extern void sun_do_break(void);
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
		       unsigned char up_flag)
{
	if (keycode > 255 || !x86_keycodes[keycode])
		return -1;
	int code;

	switch (keycode) {
		case KEY_PAUSE:
			put_queue(vc, 0xe1);
			put_queue(vc, 0x1d | up_flag);
			put_queue(vc, 0x45 | up_flag);
			return 0;
			break;

		case KEY_HANGEUL:
			if (!up_flag)
				put_queue(vc, 0xf2);
			return 0;
			break;

		case KEY_HANJA:
			if (!up_flag)
				put_queue(vc, 0xf1);
			return 0;
	}
			break;

	if (keycode == KEY_SYSRQ && sysrq_alt) {
		case KEY_SYSRQ:
			/*
			 * Real AT keyboards (that's what we're trying
			 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
			 * pressing PrtSc/SysRq alone, but simply 0x54
			 * when pressing Alt+PrtSc/SysRq.
			 */
			if (sysrq_alt) {
				put_queue(vc, 0x54 | up_flag);
		return 0;
			} else {
				put_queue(vc, 0xe0);
				put_queue(vc, 0x2a | up_flag);
				put_queue(vc, 0xe0);
				put_queue(vc, 0x37 | up_flag);
			}
			break;

	if (x86_keycodes[keycode] & 0x100)
		put_queue(vc, 0xe0);
		default:
			if (keycode > 255)
				return -1;

	put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
			code = x86_keycodes[keycode];
			if (!code)
				return -1;

	if (keycode == KEY_SYSRQ) {
			if (code & 0x100)
				put_queue(vc, 0xe0);
		put_queue(vc, 0x37 | up_flag);
			put_queue(vc, (code & 0x7f) | up_flag);

			break;
	}

	return 0;
@@ -1298,16 +1297,15 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
	if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
		return NULL;

	if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
	if (!handle)
		return NULL;
	memset(handle, 0, sizeof(struct input_handle));

	handle->dev = dev;
	handle->handler = handler;
	handle->name = "kbd";

	input_open_device(handle);
	kbd_refresh_leds(handle);

	return handle;
}
@@ -1318,6 +1316,24 @@ static void kbd_disconnect(struct input_handle *handle)
	kfree(handle);
}

/*
 * Start keyboard handler on the new keyboard by refreshing LED state to
 * match the rest of the system.
 */
static void kbd_start(struct input_handle *handle)
{
	unsigned char leds = ledstate;

	tasklet_disable(&keyboard_tasklet);
	if (leds != 0xff) {
		input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
		input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
		input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
		input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
	}
	tasklet_enable(&keyboard_tasklet);
}

static struct input_device_id kbd_ids[] = {
	{
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1338,6 +1354,7 @@ static struct input_handler kbd_handler = {
	.event		= kbd_event,
	.connect	= kbd_connect,
	.disconnect	= kbd_disconnect,
	.start		= kbd_start,
	.name		= "kbd",
	.id_table	= kbd_ids,
};
@@ -1346,15 +1363,15 @@ int __init kbd_init(void)
{
	int i;

        kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
        kbd0.ledmode = LED_SHOW_FLAGS;
        kbd0.lockstate = KBD_DEFLOCK;
        kbd0.slockstate = 0;
        kbd0.modeflags = KBD_DEFMODE;
        kbd0.kbdmode = VC_XLATE;

        for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
                kbd_table[i] = kbd0;
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
		kbd_table[i].ledflagstate = KBD_DEFLEDS;
		kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
		kbd_table[i].ledmode = LED_SHOW_FLAGS;
		kbd_table[i].lockstate = KBD_DEFLOCK;
		kbd_table[i].slockstate = 0;
		kbd_table[i].modeflags = KBD_DEFMODE;
		kbd_table[i].kbdmode = VC_XLATE;
	}

	input_register_handler(&kbd_handler);

+3 −7
Original line number Diff line number Diff line
@@ -127,14 +127,10 @@ static int evdev_open(struct inode * inode, struct file * file)
{
	struct evdev_list *list;
	int i = iminor(inode) - EVDEV_MINOR_BASE;
	int accept_err;

	if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
		return -ENODEV;

	if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
		return accept_err;

	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
		return -ENOMEM;

@@ -260,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_

		if (evdev_event_from_user(buffer + retval, &event))
			return -EFAULT;
		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
		input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
		retval += evdev_event_size();
	}

@@ -428,8 +424,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
			if (get_user(v, ip + 1))
				return -EFAULT;

			input_event(dev, EV_REP, REP_DELAY, u);
			input_event(dev, EV_REP, REP_PERIOD, v);
			input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
			input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);

			return 0;

+2 −2
Original line number Diff line number Diff line
@@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
	gp->gameport = port;
	gp->res_port = request_region(port->io, 0x10, "FM801 GP");
	if (!gp->res_port) {
		kfree(gp);
		gameport_free_port(port);
		printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
			port->io, port->io + 0x0f);
		gameport_free_port(port);
		kfree(gp);
		return -EBUSY;
	}

+49 −17
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ static LIST_HEAD(gameport_list);

static struct bus_type gameport_bus;

static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
static void gameport_reconnect_port(struct gameport *gameport);
@@ -211,8 +212,14 @@ static void gameport_release_driver(struct gameport *gameport)

static void gameport_find_driver(struct gameport *gameport)
{
	int error;

	down_write(&gameport_bus.subsys.rwsem);
	device_attach(&gameport->dev);
	error = device_attach(&gameport->dev);
	if (error < 0)
		printk(KERN_WARNING
			"gameport: device_attach() failed for %s (%s), error: %d\n",
			gameport->phys, gameport->name, error);
	up_write(&gameport_bus.subsys.rwsem);
}

@@ -316,7 +323,6 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
	spin_unlock_irqrestore(&gameport_event_lock, flags);
}


static struct gameport_event *gameport_get_event(void)
{
	struct gameport_event *event;
@@ -342,7 +348,6 @@ static struct gameport_event *gameport_get_event(void)
static void gameport_handle_event(void)
{
	struct gameport_event *event;
	struct gameport_driver *gameport_drv;

	mutex_lock(&gameport_mutex);

@@ -369,8 +374,7 @@ static void gameport_handle_event(void)
				break;

			case GAMEPORT_REGISTER_DRIVER:
				gameport_drv = event->object;
				driver_register(&gameport_drv->driver);
				gameport_add_driver(event->object);
				break;

			default:
@@ -532,6 +536,7 @@ static void gameport_init_port(struct gameport *gameport)
	if (gameport->parent)
		gameport->dev.parent = &gameport->parent->dev;

	INIT_LIST_HEAD(&gameport->node);
	spin_lock_init(&gameport->timer_lock);
	init_timer(&gameport->poll_timer);
	gameport->poll_timer.function = gameport_run_poll_handler;
@@ -544,6 +549,8 @@ static void gameport_init_port(struct gameport *gameport)
 */
static void gameport_add_port(struct gameport *gameport)
{
	int error;

	if (gameport->parent)
		gameport->parent->child = gameport;

@@ -558,7 +565,12 @@ static void gameport_add_port(struct gameport *gameport)
		printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
			gameport->name, gameport->phys, gameport->speed);

	device_add(&gameport->dev);
	error = device_add(&gameport->dev);
	if (error)
		printk(KERN_ERR
			"gameport: device_add() failed for %s (%s), error: %d\n",
			gameport->phys, gameport->name, error);
	else
		gameport->registered = 1;
}

@@ -583,10 +595,11 @@ static void gameport_destroy_port(struct gameport *gameport)

	if (gameport->registered) {
		device_del(&gameport->dev);
		list_del_init(&gameport->node);
		gameport->registered = 0;
	}

	list_del_init(&gameport->node);

	gameport_remove_pending_events(gameport);
	put_device(&gameport->dev);
}
@@ -709,6 +722,17 @@ static struct bus_type gameport_bus = {
	.remove	= gameport_driver_remove,
};

static void gameport_add_driver(struct gameport_driver *drv)
{
	int error;

	error = driver_register(&drv->driver);
	if (error)
		printk(KERN_ERR
			"gameport: driver_register() failed for %s, error: %d\n",
			drv->driver.name, error);
}

void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
	drv->driver.bus = &gameport_bus;
@@ -778,16 +802,24 @@ void gameport_close(struct gameport *gameport)

static int __init gameport_init(void)
{
	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
	if (IS_ERR(gameport_task)) {
		printk(KERN_ERR "gameport: Failed to start kgameportd\n");
		return PTR_ERR(gameport_task);
	}
	int error;

	gameport_bus.dev_attrs = gameport_device_attrs;
	gameport_bus.drv_attrs = gameport_driver_attrs;
	gameport_bus.match = gameport_bus_match;
	bus_register(&gameport_bus);
	error = bus_register(&gameport_bus);
	if (error) {
		printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
		return error;
	}

	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
	if (IS_ERR(gameport_task)) {
		bus_unregister(&gameport_bus);
		error = PTR_ERR(gameport_task);
		printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
		return error;
	}

	return 0;
}
+44 −13
Original line number Diff line number Diff line
@@ -35,6 +35,16 @@ static LIST_HEAD(input_handler_list);

static struct input_handler *input_table[8];

/**
 * input_event() - report new input event
 * @handle: device that generated the event
 * @type: type of the event
 * @code: event code
 * @value: value of the event
 *
 * This function should be used by drivers implementing various input devices
 * See also input_inject_event()
 */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
	struct input_handle *handle;
@@ -183,6 +193,23 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
}
EXPORT_SYMBOL(input_event);

/**
 * input_inject_event() - send input event from input handler
 * @handle: input handle to send event through
 * @type: type of the event
 * @code: event code
 * @value: value of the event
 *
 * Similar to input_event() but will ignore event if device is "grabbed" and handle
 * injecting event is not the one that owns the device.
 */
void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
	if (!handle->dev->grab || handle->dev->grab == handle)
		input_event(handle->dev, type, code, value);
}
EXPORT_SYMBOL(input_inject_event);

static void input_repeat_key(unsigned long data)
{
	struct input_dev *dev = (void *) data;
@@ -197,15 +224,6 @@ static void input_repeat_key(unsigned long data)
		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}

int input_accept_process(struct input_handle *handle, struct file *file)
{
	if (handle->dev->accept)
		return handle->dev->accept(handle->dev, file);

	return 0;
}
EXPORT_SYMBOL(input_accept_process);

int input_grab_device(struct input_handle *handle)
{
	if (handle->dev->grab)
@@ -218,8 +236,15 @@ EXPORT_SYMBOL(input_grab_device);

void input_release_device(struct input_handle *handle)
{
	if (handle->dev->grab == handle)
		handle->dev->grab = NULL;
	struct input_dev *dev = handle->dev;

	if (dev->grab == handle) {
		dev->grab = NULL;

		list_for_each_entry(handle, &dev->h_list, d_node)
			if (handle->handler->start)
				handle->handler->start(handle);
	}
}
EXPORT_SYMBOL(input_release_device);

@@ -963,8 +988,11 @@ int input_register_device(struct input_dev *dev)
	list_for_each_entry(handler, &input_handler_list, node)
		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
			if ((id = input_match_device(handler->id_table, dev)))
				if ((handle = handler->connect(handler, dev, id)))
				if ((handle = handler->connect(handler, dev, id))) {
					input_link_handle(handle);
					if (handler->start)
						handler->start(handle);
				}

	input_wakeup_procfs_readers();

@@ -1028,8 +1056,11 @@ void input_register_handler(struct input_handler *handler)
	list_for_each_entry(dev, &input_dev_list, node)
		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
			if ((id = input_match_device(handler->id_table, dev)))
				if ((handle = handler->connect(handler, dev, id)))
				if ((handle = handler->connect(handler, dev, id))) {
					input_link_handle(handle);
					if (handler->start)
						handler->start(handle);
				}

	input_wakeup_procfs_readers();
}
Loading