Commit 864ee6cb authored by Linus Torvalds's avatar Linus Torvalds

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

* '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
...@@ -752,7 +752,7 @@ static int input_default_setkeycode(struct input_dev *dev, ...@@ -752,7 +752,7 @@ static int input_default_setkeycode(struct input_dev *dev,
if (index >= dev->keycodemax) if (index >= dev->keycodemax)
return -EINVAL; return -EINVAL;
if (dev->keycodesize < sizeof(dev->keycode) && if (dev->keycodesize < sizeof(ke->keycode) &&
(ke->keycode >> (dev->keycodesize * 8))) (ke->keycode >> (dev->keycodesize * 8)))
return -EINVAL; return -EINVAL;
......
...@@ -1097,7 +1097,7 @@ store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const ...@@ -1097,7 +1097,7 @@ store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(pointer_mode, static DEVICE_ATTR(pointer_mode,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletPointerMode, store_tabletPointerMode); show_tabletPointerMode, store_tabletPointerMode);
/*********************************************************************** /***********************************************************************
...@@ -1134,7 +1134,7 @@ store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, co ...@@ -1134,7 +1134,7 @@ store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, co
} }
static DEVICE_ATTR(coordinate_mode, static DEVICE_ATTR(coordinate_mode,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletCoordinateMode, store_tabletCoordinateMode); show_tabletCoordinateMode, store_tabletCoordinateMode);
/*********************************************************************** /***********************************************************************
...@@ -1176,7 +1176,7 @@ store_tabletToolMode(struct device *dev, struct device_attribute *attr, const ch ...@@ -1176,7 +1176,7 @@ store_tabletToolMode(struct device *dev, struct device_attribute *attr, const ch
} }
static DEVICE_ATTR(tool_mode, static DEVICE_ATTR(tool_mode,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletToolMode, store_tabletToolMode); show_tabletToolMode, store_tabletToolMode);
/*********************************************************************** /***********************************************************************
...@@ -1219,7 +1219,7 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char ...@@ -1219,7 +1219,7 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
} }
static DEVICE_ATTR(xtilt, 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 * 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 ...@@ -1261,7 +1261,7 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
} }
static DEVICE_ATTR(ytilt, 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 * support routines for the 'jitter' file. Note that this file
...@@ -1288,7 +1288,7 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const ...@@ -1288,7 +1288,7 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(jitter, static DEVICE_ATTR(jitter,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletJitterDelay, store_tabletJitterDelay); show_tabletJitterDelay, store_tabletJitterDelay);
/*********************************************************************** /***********************************************************************
...@@ -1317,7 +1317,7 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, ...@@ -1317,7 +1317,7 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
} }
static DEVICE_ATTR(delay, static DEVICE_ATTR(delay,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletProgrammableDelay, store_tabletProgrammableDelay); show_tabletProgrammableDelay, store_tabletProgrammableDelay);
/*********************************************************************** /***********************************************************************
...@@ -1406,7 +1406,7 @@ store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const ...@@ -1406,7 +1406,7 @@ store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(stylus_upper, static DEVICE_ATTR(stylus_upper,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletStylusUpper, store_tabletStylusUpper); show_tabletStylusUpper, store_tabletStylusUpper);
/*********************************************************************** /***********************************************************************
...@@ -1437,7 +1437,7 @@ store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const ...@@ -1437,7 +1437,7 @@ store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(stylus_lower, static DEVICE_ATTR(stylus_lower,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletStylusLower, store_tabletStylusLower); show_tabletStylusLower, store_tabletStylusLower);
/*********************************************************************** /***********************************************************************
...@@ -1475,7 +1475,7 @@ store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const c ...@@ -1475,7 +1475,7 @@ store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const c
} }
static DEVICE_ATTR(mouse_left, static DEVICE_ATTR(mouse_left,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletMouseLeft, store_tabletMouseLeft); show_tabletMouseLeft, store_tabletMouseLeft);
/*********************************************************************** /***********************************************************************
...@@ -1505,7 +1505,7 @@ store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const ...@@ -1505,7 +1505,7 @@ store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(mouse_middle, static DEVICE_ATTR(mouse_middle,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletMouseMiddle, store_tabletMouseMiddle); show_tabletMouseMiddle, store_tabletMouseMiddle);
/*********************************************************************** /***********************************************************************
...@@ -1535,7 +1535,7 @@ store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const ...@@ -1535,7 +1535,7 @@ store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const
} }
static DEVICE_ATTR(mouse_right, static DEVICE_ATTR(mouse_right,
S_IRUGO | S_IWUGO, S_IRUGO | S_IWUSR,
show_tabletMouseRight, store_tabletMouseRight); show_tabletMouseRight, store_tabletMouseRight);
/*********************************************************************** /***********************************************************************
...@@ -1567,7 +1567,7 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char ...@@ -1567,7 +1567,7 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
} }
static DEVICE_ATTR(wheel, 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 * 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 ...@@ -1600,7 +1600,7 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
} }
static DEVICE_ATTR(execute, 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 * support routines for the 'odm_code' file. Note that this file
......
...@@ -554,7 +554,7 @@ EXPORT_SYMBOL(handle_sysrq); ...@@ -554,7 +554,7 @@ EXPORT_SYMBOL(handle_sysrq);
#ifdef CONFIG_INPUT #ifdef CONFIG_INPUT
/* Simple translation table for the SysRq keys */ /* 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 */ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
...@@ -563,52 +563,128 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] = ...@@ -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 */ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
"\r\000/"; /* 0x60 - 0x6f */ "\r\000/"; /* 0x60 - 0x6f */
static bool sysrq_down; struct sysrq_state {
static int sysrq_alt_use; struct input_handle handle;
static int sysrq_alt; struct work_struct reinject_work;
static DEFINE_SPINLOCK(sysrq_event_lock); 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, static void sysrq_reinject_alt_sysrq(struct work_struct *work)
unsigned int code, int value)
{ {
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; bool suppress;
/* We are called with interrupts disabled, just take the lock */ switch (type) {
spin_lock(&sysrq_event_lock);
if (type != EV_KEY) case EV_SYN:
goto out; suppress = false;
break;
case EV_KEY:
switch (code) { switch (code) {
case KEY_LEFTALT: case KEY_LEFTALT:
case KEY_RIGHTALT: case KEY_RIGHTALT:
if (value) if (!value) {
sysrq_alt = code; /* One of ALTs is being released */
else { if (sysrq->active && code == sysrq->alt_use)
if (sysrq_down && code == sysrq_alt_use) sysrq->active = false;
sysrq_down = false;
sysrq_alt = 0; sysrq->alt = KEY_RESERVED;
} else if (value != 2) {
sysrq->alt = code;
sysrq->need_reinject = false;
} }
break; break;
case KEY_SYSRQ: case KEY_SYSRQ:
if (value == 1 && sysrq_alt) { if (value == 1 && sysrq->alt != KEY_RESERVED) {
sysrq_down = true; sysrq->active = true;
sysrq_alt_use = sysrq_alt; 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; break;
default: default:
if (sysrq_down && value && value != 2) if (sysrq->active && value && value != 2) {
sysrq->need_reinject = false;
__handle_sysrq(sysrq_xlate[code], true); __handle_sysrq(sysrq_xlate[code], true);
}
break; break;
} }
out: suppress = sysrq->active;
suppress = sysrq_down;
spin_unlock(&sysrq_event_lock); 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; return suppress;
} }
...@@ -617,28 +693,28 @@ static int sysrq_connect(struct input_handler *handler, ...@@ -617,28 +693,28 @@ static int sysrq_connect(struct input_handler *handler,
struct input_dev *dev, struct input_dev *dev,
const struct input_device_id *id) const struct input_device_id *id)
{ {
struct input_handle *handle; struct sysrq_state *sysrq;
int error; int error;
sysrq_down = false; sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL);
sysrq_alt = 0; if (!sysrq)
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
return -ENOMEM; return -ENOMEM;
handle->dev = dev; INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq);
handle->handler = handler;
handle->name = "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) { if (error) {
pr_err("Failed to register input sysrq handler, error %d\n", pr_err("Failed to register input sysrq handler, error %d\n",
error); error);
goto err_free; goto err_free;
} }
error = input_open_device(handle); error = input_open_device(&sysrq->handle);
if (error) { if (error) {
pr_err("Failed to open input device, error %d\n", error); pr_err("Failed to open input device, error %d\n", error);
goto err_unregister; goto err_unregister;
...@@ -647,17 +723,20 @@ static int sysrq_connect(struct input_handler *handler, ...@@ -647,17 +723,20 @@ static int sysrq_connect(struct input_handler *handler,
return 0; return 0;
err_unregister: err_unregister:
input_unregister_handle(handle); input_unregister_handle(&sysrq->handle);
err_free: err_free:
kfree(handle); kfree(sysrq);
return error; return error;
} }
static void sysrq_disconnect(struct input_handle *handle) static void sysrq_disconnect(struct input_handle *handle)
{ {
struct sysrq_state *sysrq = handle->private;
input_close_device(handle); input_close_device(handle);
cancel_work_sync(&sysrq->reinject_work);
input_unregister_handle(handle); input_unregister_handle(handle);
kfree(handle); kfree(sysrq);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment