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

Commit 864ee6cb 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: fix typo in keycode validation supporting large scancodes
  Input: aiptek - tighten up permissions on sysfs attributes
  Input: sysrq - pass along lone Alt + SysRq
parents 973d168d de391d12
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -752,7 +752,7 @@ static int input_default_setkeycode(struct input_dev *dev,
	if (index >= dev->keycodemax)
		return -EINVAL;

	if (dev->keycodesize < sizeof(dev->keycode) &&
	if (dev->keycodesize < sizeof(ke->keycode) &&
			(ke->keycode >> (dev->keycodesize * 8)))
		return -EINVAL;

+14 −14
Original line number Diff line number Diff line
@@ -1097,7 +1097,7 @@ store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(pointer_mode,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletPointerMode, store_tabletPointerMode);

/***********************************************************************
@@ -1134,7 +1134,7 @@ store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, co
}

static DEVICE_ATTR(coordinate_mode,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletCoordinateMode, store_tabletCoordinateMode);

/***********************************************************************
@@ -1176,7 +1176,7 @@ store_tabletToolMode(struct device *dev, struct device_attribute *attr, const ch
}

static DEVICE_ATTR(tool_mode,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletToolMode, store_tabletToolMode);

/***********************************************************************
@@ -1219,7 +1219,7 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
}

static DEVICE_ATTR(xtilt,
		   S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt);
		   S_IRUGO | S_IWUSR, show_tabletXtilt, store_tabletXtilt);

/***********************************************************************
 * support routines for the 'ytilt' file. Note that this file
@@ -1261,7 +1261,7 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
}

static DEVICE_ATTR(ytilt,
		   S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt);
		   S_IRUGO | S_IWUSR, show_tabletYtilt, store_tabletYtilt);

/***********************************************************************
 * support routines for the 'jitter' file. Note that this file
@@ -1288,7 +1288,7 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(jitter,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletJitterDelay, store_tabletJitterDelay);

/***********************************************************************
@@ -1317,7 +1317,7 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
}

static DEVICE_ATTR(delay,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletProgrammableDelay, store_tabletProgrammableDelay);

/***********************************************************************
@@ -1406,7 +1406,7 @@ store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(stylus_upper,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletStylusUpper, store_tabletStylusUpper);

/***********************************************************************
@@ -1437,7 +1437,7 @@ store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(stylus_lower,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletStylusLower, store_tabletStylusLower);

/***********************************************************************
@@ -1475,7 +1475,7 @@ store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const c
}

static DEVICE_ATTR(mouse_left,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletMouseLeft, store_tabletMouseLeft);

/***********************************************************************
@@ -1505,7 +1505,7 @@ store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(mouse_middle,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletMouseMiddle, store_tabletMouseMiddle);

/***********************************************************************
@@ -1535,7 +1535,7 @@ store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const
}

static DEVICE_ATTR(mouse_right,
		   S_IRUGO | S_IWUGO,
		   S_IRUGO | S_IWUSR,
		   show_tabletMouseRight, store_tabletMouseRight);

/***********************************************************************
@@ -1567,7 +1567,7 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
}

static DEVICE_ATTR(wheel,
		   S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel);
		   S_IRUGO | S_IWUSR, show_tabletWheel, store_tabletWheel);

/***********************************************************************
 * support routines for the 'execute' file. Note that this file
@@ -1600,7 +1600,7 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
}

static DEVICE_ATTR(execute,
		   S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute);
		   S_IRUGO | S_IWUSR, show_tabletExecute, store_tabletExecute);

/***********************************************************************
 * support routines for the 'odm_code' file. Note that this file
+124 −45
Original line number Diff line number Diff line
@@ -554,7 +554,7 @@ EXPORT_SYMBOL(handle_sysrq);
#ifdef CONFIG_INPUT

/* Simple translation table for the SysRq keys */
static const unsigned char sysrq_xlate[KEY_MAX + 1] =
static const unsigned char sysrq_xlate[KEY_CNT] =
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
@@ -563,52 +563,128 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] =
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
        "\r\000/";                                      /* 0x60 - 0x6f */

static bool sysrq_down;
static int sysrq_alt_use;
static int sysrq_alt;
static DEFINE_SPINLOCK(sysrq_event_lock);
struct sysrq_state {
	struct input_handle handle;
	struct work_struct reinject_work;
	unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];
	unsigned int alt;
	unsigned int alt_use;
	bool active;
	bool need_reinject;
};

static bool sysrq_filter(struct input_handle *handle, unsigned int type,
		         unsigned int code, int value)
static void sysrq_reinject_alt_sysrq(struct work_struct *work)
{
	struct sysrq_state *sysrq =
			container_of(work, struct sysrq_state, reinject_work);
	struct input_handle *handle = &sysrq->handle;
	unsigned int alt_code = sysrq->alt_use;

	if (sysrq->need_reinject) {
		/* Simulate press and release of Alt + SysRq */
		input_inject_event(handle, EV_KEY, alt_code, 1);
		input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1);
		input_inject_event(handle, EV_SYN, SYN_REPORT, 1);

		input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0);
		input_inject_event(handle, EV_KEY, alt_code, 0);
		input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
	}
}

static bool sysrq_filter(struct input_handle *handle,
			 unsigned int type, unsigned int code, int value)
{
	struct sysrq_state *sysrq = handle->private;
	bool was_active = sysrq->active;
	bool suppress;

	/* We are called with interrupts disabled, just take the lock */
	spin_lock(&sysrq_event_lock);
	switch (type) {

	if (type != EV_KEY)
		goto out;
	case EV_SYN:
		suppress = false;
		break;

	case EV_KEY:
		switch (code) {

		case KEY_LEFTALT:
		case KEY_RIGHTALT:
		if (value)
			sysrq_alt = code;
		else {
			if (sysrq_down && code == sysrq_alt_use)
				sysrq_down = false;
			if (!value) {
				/* One of ALTs is being released */
				if (sysrq->active && code == sysrq->alt_use)
					sysrq->active = false;

			sysrq_alt = 0;
				sysrq->alt = KEY_RESERVED;

			} else if (value != 2) {
				sysrq->alt = code;
				sysrq->need_reinject = false;
			}
			break;

		case KEY_SYSRQ:
		if (value == 1 && sysrq_alt) {
			sysrq_down = true;
			sysrq_alt_use = sysrq_alt;
			if (value == 1 && sysrq->alt != KEY_RESERVED) {
				sysrq->active = true;
				sysrq->alt_use = sysrq->alt;
				/*
				 * If nothing else will be pressed we'll need
				 * to * re-inject Alt-SysRq keysroke.
				 */
				sysrq->need_reinject = true;
			}

			/*
			 * Pretend that sysrq was never pressed at all. This
			 * is needed to properly handle KGDB which will try
			 * to release all keys after exiting debugger. If we
			 * do not clear key bit it KGDB will end up sending
			 * release events for Alt and SysRq, potentially
			 * triggering print screen function.
			 */
			if (sysrq->active)
				clear_bit(KEY_SYSRQ, handle->dev->key);

			break;

		default:
		if (sysrq_down && value && value != 2)
			if (sysrq->active && value && value != 2) {
				sysrq->need_reinject = false;
				__handle_sysrq(sysrq_xlate[code], true);
			}
			break;
		}

out:
	suppress = sysrq_down;
	spin_unlock(&sysrq_event_lock);
		suppress = sysrq->active;

		if (!sysrq->active) {
			/*
			 * If we are not suppressing key presses keep track of
			 * keyboard state so we can release keys that have been
			 * pressed before entering SysRq mode.
			 */
			if (value)
				set_bit(code, sysrq->key_down);
			else
				clear_bit(code, sysrq->key_down);

			if (was_active)
				schedule_work(&sysrq->reinject_work);

		} else if (value == 0 &&
			   test_and_clear_bit(code, sysrq->key_down)) {
			/*
			 * Pass on release events for keys that was pressed before
			 * entering SysRq mode.
			 */
			suppress = false;
		}
		break;

	default:
		suppress = sysrq->active;
		break;
	}

	return suppress;
}
@@ -617,28 +693,28 @@ static int sysrq_connect(struct input_handler *handler,
			 struct input_dev *dev,
			 const struct input_device_id *id)
{
	struct input_handle *handle;
	struct sysrq_state *sysrq;
	int error;

	sysrq_down = false;
	sysrq_alt = 0;

	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
	if (!handle)
	sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL);
	if (!sysrq)
		return -ENOMEM;

	handle->dev = dev;
	handle->handler = handler;
	handle->name = "sysrq";
	INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq);

	sysrq->handle.dev = dev;
	sysrq->handle.handler = handler;
	sysrq->handle.name = "sysrq";
	sysrq->handle.private = sysrq;

	error = input_register_handle(handle);
	error = input_register_handle(&sysrq->handle);
	if (error) {
		pr_err("Failed to register input sysrq handler, error %d\n",
			error);
		goto err_free;
	}

	error = input_open_device(handle);
	error = input_open_device(&sysrq->handle);
	if (error) {
		pr_err("Failed to open input device, error %d\n", error);
		goto err_unregister;
@@ -647,17 +723,20 @@ static int sysrq_connect(struct input_handler *handler,
	return 0;

 err_unregister:
	input_unregister_handle(handle);
	input_unregister_handle(&sysrq->handle);
 err_free:
	kfree(handle);
	kfree(sysrq);
	return error;
}

static void sysrq_disconnect(struct input_handle *handle)
{
	struct sysrq_state *sysrq = handle->private;

	input_close_device(handle);
	cancel_work_sync(&sysrq->reinject_work);
	input_unregister_handle(handle);
	kfree(handle);
	kfree(sysrq);
}

/*