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

Commit 04f2b976 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: xpad - add USB-ID for PL-3601 Xbox 360 pad
  Input: cy8ctmg100_ts - signedness bug
  Input: elantech - report position also with 3 fingers
  Input: elantech - discard the first 2 positions on some firmwares
  Input: adxl34x - do not mark device as disabled on startup
  Input: gpio_keys - add hooks to enable/disable device
  Input: evdev - rearrange ioctl handling
  Input: dynamically allocate ABS information
  Input: switch to input_abs_*() access functions
  Input: add static inline accessors for ABS properties
parents 9895850b 5fc0d36c
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -230,7 +230,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
				input_report_key(input, BTN_RIGHT, 0);
				input_report_key(input, BTN_MIDDLE, 0);
				input_report_abs(input, ABS_DISTANCE,
						input->absmax[ABS_DISTANCE]);
					input_abs_get_max(input, ABS_DISTANCE));
			} else {
				input_report_key(input, BTN_TOUCH, 0);
				input_report_key(input, BTN_STYLUS, 0);
@@ -383,38 +383,37 @@ move_on:

	/* Basics */
	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
	input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
		BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
	input->relbit[0] |= BIT(REL_WHEEL);
	set_bit(BTN_TOOL_PEN, input->keybit);
	set_bit(BTN_TOUCH, input->keybit);
	set_bit(BTN_STYLUS, input->keybit);
	set_bit(BTN_STYLUS2, input->keybit);
	set_bit(BTN_LEFT, input->keybit);
	set_bit(BTN_RIGHT, input->keybit);
	set_bit(BTN_MIDDLE, input->keybit);

	__set_bit(REL_WHEEL, input->relbit);

	__set_bit(BTN_TOOL_PEN, input->keybit);
	__set_bit(BTN_TOUCH, input->keybit);
	__set_bit(BTN_STYLUS, input->keybit);
	__set_bit(BTN_STYLUS2, input->keybit);
	__set_bit(BTN_LEFT, input->keybit);
	__set_bit(BTN_RIGHT, input->keybit);
	__set_bit(BTN_MIDDLE, input->keybit);

	/* Pad */
	input->evbit[0] |= BIT(EV_MSC);
	input->mscbit[0] |= BIT(MSC_SERIAL);
	set_bit(BTN_0, input->keybit);
	set_bit(BTN_1, input->keybit);
	set_bit(BTN_TOOL_FINGER, input->keybit);

	/* Distance, rubber and mouse */
	input->absbit[0] |= BIT(ABS_DISTANCE);
	set_bit(BTN_TOOL_RUBBER, input->keybit);
	set_bit(BTN_TOOL_MOUSE, input->keybit);
	__set_bit(MSC_SERIAL, input->mscbit);

	input->absmax[ABS_PRESSURE] = 511;
	input->absmax[ABS_DISTANCE] = 32;
	__set_bit(BTN_0, input->keybit);
	__set_bit(BTN_1, input->keybit);
	__set_bit(BTN_TOOL_FINGER, input->keybit);

	input->absmax[ABS_X] = 16704;
	input->absmax[ABS_Y] = 12064;
	input->absfuzz[ABS_X] = 4;
	input->absfuzz[ABS_Y] = 4;
	/* Distance, rubber and mouse */
	__set_bit(BTN_TOOL_RUBBER, input->keybit);
	__set_bit(BTN_TOOL_MOUSE, input->keybit);

	input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
	input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
	input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
	input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);

	return 0;

err_free:
	kfree(wdata);
	return ret;
+73 −79
Original line number Diff line number Diff line
@@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
}

#define OLD_KEY_MAX	0x1ff
static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode)
static int handle_eviocgbit(struct input_dev *dev,
			    unsigned int type, unsigned int size,
			    void __user *p, int compat_mode)
{
	static unsigned long keymax_warn_time;
	unsigned long *bits;
	int len;

	switch (_IOC_NR(cmd) & EV_MAX) {
	switch (type) {

	case      0: bits = dev->evbit;  len = EV_MAX;  break;
	case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
@@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
	 * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
	 * should be in bytes, not in bits.
	 */
	if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
	if (type == EV_KEY && size == OLD_KEY_MAX) {
		len = OLD_KEY_MAX;
		if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
			printk(KERN_WARNING
@@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
				BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
	}

	return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
	return bits_to_user(bits, len, size, p, compat_mode);
}
#undef OLD_KEY_MAX

@@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
	struct ff_effect effect;
	int __user *ip = (int __user *)p;
	unsigned int i, t, u, v;
	unsigned int size;
	int error;

	/* First we check for fixed-length commands */
	switch (cmd) {

	case EVIOCGVERSION:
@@ -610,87 +614,85 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
			return evdev_grab(evdev, client);
		else
			return evdev_ungrab(evdev, client);
	}

	default:
	size = _IOC_SIZE(cmd);

		if (_IOC_TYPE(cmd) != 'E')
			return -EINVAL;
	/* Now check variable-length commands */
#define EVIOC_MASK_SIZE(nr)	((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))

		if (_IOC_DIR(cmd) == _IOC_READ) {
	switch (EVIOC_MASK_SIZE(cmd)) {

			if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
				return handle_eviocgbit(dev, cmd, p, compat_mode);
	case EVIOCGKEY(0):
		return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
				return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
						    p, compat_mode);
	case EVIOCGLED(0):
		return bits_to_user(dev->led, LED_MAX, size, p, compat_mode);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
				return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
						    p, compat_mode);
	case EVIOCGSND(0):
		return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
				return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
						    p, compat_mode);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
				return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
						    p, compat_mode);
	case EVIOCGSW(0):
		return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
				return str_to_user(dev->name, _IOC_SIZE(cmd), p);
	case EVIOCGNAME(0):
		return str_to_user(dev->name, size, p);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
				return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
	case EVIOCGPHYS(0):
		return str_to_user(dev->phys, size, p);

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
				return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
	case EVIOCGUNIQ(0):
		return str_to_user(dev->uniq, size, p);

			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {

				t = _IOC_NR(cmd) & ABS_MAX;
	case EVIOC_MASK_SIZE(EVIOCSFF):
		if (input_ff_effect_from_user(p, size, &effect))
			return -EFAULT;

				abs.value = dev->abs[t];
				abs.minimum = dev->absmin[t];
				abs.maximum = dev->absmax[t];
				abs.fuzz = dev->absfuzz[t];
				abs.flat = dev->absflat[t];
				abs.resolution = dev->absres[t];
		error = input_ff_upload(dev, &effect, file);

				if (copy_to_user(p, &abs, min_t(size_t,
								_IOC_SIZE(cmd),
								sizeof(struct input_absinfo))))
		if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
			return -EFAULT;

				return 0;
		return error;
	}

		}
	/* Multi-number variable-length handlers */
	if (_IOC_TYPE(cmd) != 'E')
		return -EINVAL;

		if (_IOC_DIR(cmd) == _IOC_WRITE) {
	if (_IOC_DIR(cmd) == _IOC_READ) {

			if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
		if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
			return handle_eviocgbit(dev,
						_IOC_NR(cmd) & EV_MAX, size,
						p, compat_mode);

				if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
					return -EFAULT;
		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {

				error = input_ff_upload(dev, &effect, file);
			t = _IOC_NR(cmd) & ABS_MAX;
			abs = dev->absinfo[t];

				if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
			if (copy_to_user(p, &abs, min_t(size_t,
					size, sizeof(struct input_absinfo))))
				return -EFAULT;

				return error;
			return 0;
		}
	}

	if (_IOC_DIR(cmd) == _IOC_READ) {

		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {

			t = _IOC_NR(cmd) & ABS_MAX;

			if (copy_from_user(&abs, p, min_t(size_t,
								  _IOC_SIZE(cmd),
								  sizeof(struct input_absinfo))))
					size, sizeof(struct input_absinfo))))
				return -EFAULT;

			if (size < sizeof(struct input_absinfo))
				abs.resolution = 0;

			/* We can't change number of reserved MT slots */
			if (t == ABS_MT_SLOT)
				return -EINVAL;
@@ -701,21 +703,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
			 * of event.
			 */
			spin_lock_irq(&dev->event_lock);

				dev->abs[t] = abs.value;
				dev->absmin[t] = abs.minimum;
				dev->absmax[t] = abs.maximum;
				dev->absfuzz[t] = abs.fuzz;
				dev->absflat[t] = abs.flat;
				dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
							0 : abs.resolution;

			dev->absinfo[t] = abs;
			spin_unlock_irq(&dev->event_lock);

			return 0;
		}
	}
	}

	return -EINVAL;
}

+42 −4
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ static int input_handle_abs_event(struct input_dev *dev,
	is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;

	if (!is_mt_event) {
		pold = &dev->abs[code];
		pold = &dev->absinfo[code].value;
	} else if (dev->mt) {
		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
		pold = &mtslot->abs[code - ABS_MT_FIRST];
@@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev,

	if (pold) {
		*pval = input_defuzz_abs_event(*pval, *pold,
						dev->absfuzz[code]);
						dev->absinfo[code].fuzz);
		if (*pold == *pval)
			return INPUT_IGNORE_EVENT;

@@ -204,8 +204,8 @@ static int input_handle_abs_event(struct input_dev *dev,
	}

	/* Flush pending "slot" event */
	if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) {
		dev->abs[ABS_MT_SLOT] = dev->slot;
	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
	}

@@ -390,6 +390,43 @@ void input_inject_event(struct input_handle *handle,
}
EXPORT_SYMBOL(input_inject_event);

/**
 * input_alloc_absinfo - allocates array of input_absinfo structs
 * @dev: the input device emitting absolute events
 *
 * If the absinfo struct the caller asked for is already allocated, this
 * functions will not do anything.
 */
void input_alloc_absinfo(struct input_dev *dev)
{
	if (!dev->absinfo)
		dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
					GFP_KERNEL);

	WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
}
EXPORT_SYMBOL(input_alloc_absinfo);

void input_set_abs_params(struct input_dev *dev, unsigned int axis,
			  int min, int max, int fuzz, int flat)
{
	struct input_absinfo *absinfo;

	input_alloc_absinfo(dev);
	if (!dev->absinfo)
		return;

	absinfo = &dev->absinfo[axis];
	absinfo->minimum = min;
	absinfo->maximum = max;
	absinfo->fuzz = fuzz;
	absinfo->flat = flat;

	dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
}
EXPORT_SYMBOL(input_set_abs_params);


/**
 * input_grab_device - grabs device for exclusive use
 * @handle: input handle that wants to own the device
@@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device)

	input_ff_destroy(dev);
	input_mt_destroy_slots(dev);
	kfree(dev->absinfo);
	kfree(dev);

	module_put(THIS_MODULE);
+16 −15
Original line number Diff line number Diff line
@@ -530,7 +530,7 @@ static int joydev_ioctl_common(struct joydev *joydev,
{
	struct input_dev *dev = joydev->handle.dev;
	size_t len;
	int i, j;
	int i;
	const char *name;

	/* Process fixed-sized commands. */
@@ -565,9 +565,8 @@ static int joydev_ioctl_common(struct joydev *joydev,
			return -EFAULT;

		for (i = 0; i < joydev->nabs; i++) {
			j = joydev->abspam[i];
			joydev->abs[i] = joydev_correct(dev->abs[j],
							&joydev->corr[i]);
			int val = input_abs_get_val(dev, joydev->abspam[i]);
			joydev->abs[i] = joydev_correct(val, &joydev->corr[i]);
		}
		return 0;

@@ -848,24 +847,26 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,

	for (i = 0; i < joydev->nabs; i++) {
		j = joydev->abspam[i];
		if (dev->absmax[j] == dev->absmin[j]) {
		if (input_abs_get_max(dev, j) == input_abs_get_min(dev, j)) {
			joydev->corr[i].type = JS_CORR_NONE;
			joydev->abs[i] = dev->abs[j];
			joydev->abs[i] = input_abs_get_val(dev, j);
			continue;
		}
		joydev->corr[i].type = JS_CORR_BROKEN;
		joydev->corr[i].prec = dev->absfuzz[j];
		joydev->corr[i].coef[0] =
			(dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
		joydev->corr[i].coef[1] =
			(dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
		joydev->corr[i].prec = input_abs_get_fuzz(dev, j);

		t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2;
		joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j);
		joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j);

		t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j];
		t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2
			- 2 * input_abs_get_flat(dev, j);
		if (t) {
			joydev->corr[i].coef[2] = (1 << 29) / t;
			joydev->corr[i].coef[3] = (1 << 29) / t;

			joydev->abs[i] = joydev_correct(dev->abs[j],
			joydev->abs[i] =
				joydev_correct(input_abs_get_val(dev, j),
					       joydev->corr + i);
		}
	}
+2 −1
Original line number Diff line number Diff line
@@ -342,7 +342,8 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)

		for (i = 0; i < 4; i++) {
			if (i < 2)
				input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8);
				input_set_abs_params(input_dev, axes[i],
					48, input_abs_get_val(input_dev, axes[i]) * 2 - 48, 0, 8);
			else
				input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0);
			input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
Loading