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: matrix_keypad - increase the limit of rows and columns Input: wacom - fix error path in wacom_probe() Input: ads7846 - check proper condition when freeing gpio Revert "Input: do not pass injected events back to the originating handler" Input: sysrq - rework re-inject logic Input: serio - clear pending rescans after sysfs driver rebind Input: rotary_encoder - use proper irqflags Input: wacom_w8001 - report resolution to userland
This commit is contained in:
commit
87450bd55d
|
@ -75,7 +75,6 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
|
||||||
* dev->event_lock held and interrupts disabled.
|
* dev->event_lock held and interrupts disabled.
|
||||||
*/
|
*/
|
||||||
static void input_pass_event(struct input_dev *dev,
|
static void input_pass_event(struct input_dev *dev,
|
||||||
struct input_handler *src_handler,
|
|
||||||
unsigned int type, unsigned int code, int value)
|
unsigned int type, unsigned int code, int value)
|
||||||
{
|
{
|
||||||
struct input_handler *handler;
|
struct input_handler *handler;
|
||||||
|
@ -94,15 +93,6 @@ static void input_pass_event(struct input_dev *dev,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
handler = handle->handler;
|
handler = handle->handler;
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is the handler that injected this
|
|
||||||
* particular event we want to skip it to avoid
|
|
||||||
* filters firing again and again.
|
|
||||||
*/
|
|
||||||
if (handler == src_handler)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!handler->filter) {
|
if (!handler->filter) {
|
||||||
if (filtered)
|
if (filtered)
|
||||||
break;
|
break;
|
||||||
|
@ -132,7 +122,7 @@ static void input_repeat_key(unsigned long data)
|
||||||
if (test_bit(dev->repeat_key, dev->key) &&
|
if (test_bit(dev->repeat_key, dev->key) &&
|
||||||
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
|
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
|
||||||
|
|
||||||
input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);
|
input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
|
||||||
|
|
||||||
if (dev->sync) {
|
if (dev->sync) {
|
||||||
/*
|
/*
|
||||||
|
@ -141,7 +131,7 @@ static void input_repeat_key(unsigned long data)
|
||||||
* Otherwise assume that the driver will send
|
* Otherwise assume that the driver will send
|
||||||
* SYN_REPORT once it's done.
|
* SYN_REPORT once it's done.
|
||||||
*/
|
*/
|
||||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->rep[REP_PERIOD])
|
if (dev->rep[REP_PERIOD])
|
||||||
|
@ -174,7 +164,6 @@ static void input_stop_autorepeat(struct input_dev *dev)
|
||||||
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
|
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
|
||||||
|
|
||||||
static int input_handle_abs_event(struct input_dev *dev,
|
static int input_handle_abs_event(struct input_dev *dev,
|
||||||
struct input_handler *src_handler,
|
|
||||||
unsigned int code, int *pval)
|
unsigned int code, int *pval)
|
||||||
{
|
{
|
||||||
bool is_mt_event;
|
bool is_mt_event;
|
||||||
|
@ -218,15 +207,13 @@ static int input_handle_abs_event(struct input_dev *dev,
|
||||||
/* Flush pending "slot" event */
|
/* Flush pending "slot" event */
|
||||||
if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_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_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
|
||||||
input_pass_event(dev, src_handler,
|
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
|
||||||
EV_ABS, ABS_MT_SLOT, dev->slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return INPUT_PASS_TO_HANDLERS;
|
return INPUT_PASS_TO_HANDLERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void input_handle_event(struct input_dev *dev,
|
static void input_handle_event(struct input_dev *dev,
|
||||||
struct input_handler *src_handler,
|
|
||||||
unsigned int type, unsigned int code, int value)
|
unsigned int type, unsigned int code, int value)
|
||||||
{
|
{
|
||||||
int disposition = INPUT_IGNORE_EVENT;
|
int disposition = INPUT_IGNORE_EVENT;
|
||||||
|
@ -279,8 +266,7 @@ static void input_handle_event(struct input_dev *dev,
|
||||||
|
|
||||||
case EV_ABS:
|
case EV_ABS:
|
||||||
if (is_event_supported(code, dev->absbit, ABS_MAX))
|
if (is_event_supported(code, dev->absbit, ABS_MAX))
|
||||||
disposition = input_handle_abs_event(dev, src_handler,
|
disposition = input_handle_abs_event(dev, code, &value);
|
||||||
code, &value);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -338,7 +324,7 @@ static void input_handle_event(struct input_dev *dev,
|
||||||
dev->event(dev, type, code, value);
|
dev->event(dev, type, code, value);
|
||||||
|
|
||||||
if (disposition & INPUT_PASS_TO_HANDLERS)
|
if (disposition & INPUT_PASS_TO_HANDLERS)
|
||||||
input_pass_event(dev, src_handler, type, code, value);
|
input_pass_event(dev, type, code, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -367,7 +353,7 @@ void input_event(struct input_dev *dev,
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->event_lock, flags);
|
spin_lock_irqsave(&dev->event_lock, flags);
|
||||||
add_input_randomness(type, code, value);
|
add_input_randomness(type, code, value);
|
||||||
input_handle_event(dev, NULL, type, code, value);
|
input_handle_event(dev, type, code, value);
|
||||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,8 +383,7 @@ void input_inject_event(struct input_handle *handle,
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
grab = rcu_dereference(dev->grab);
|
grab = rcu_dereference(dev->grab);
|
||||||
if (!grab || grab == handle)
|
if (!grab || grab == handle)
|
||||||
input_handle_event(dev, handle->handler,
|
input_handle_event(dev, type, code, value);
|
||||||
type, code, value);
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||||
|
@ -611,10 +596,10 @@ static void input_dev_release_keys(struct input_dev *dev)
|
||||||
for (code = 0; code <= KEY_MAX; code++) {
|
for (code = 0; code <= KEY_MAX; code++) {
|
||||||
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
|
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
|
||||||
__test_and_clear_bit(code, dev->key)) {
|
__test_and_clear_bit(code, dev->key)) {
|
||||||
input_pass_event(dev, NULL, EV_KEY, code, 0);
|
input_pass_event(dev, EV_KEY, code, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,9 +874,9 @@ int input_set_keycode(struct input_dev *dev,
|
||||||
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
|
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
|
||||||
__test_and_clear_bit(old_keycode, dev->key)) {
|
__test_and_clear_bit(old_keycode, dev->key)) {
|
||||||
|
|
||||||
input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
|
input_pass_event(dev, EV_KEY, old_keycode, 0);
|
||||||
if (dev->sync)
|
if (dev->sync)
|
||||||
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
|
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -176,7 +176,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
/* request the IRQs */
|
/* request the IRQs */
|
||||||
err = request_irq(encoder->irq_a, &rotary_encoder_irq,
|
err = request_irq(encoder->irq_a, &rotary_encoder_irq,
|
||||||
IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
|
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||||
DRV_NAME, encoder);
|
DRV_NAME, encoder);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "unable to request IRQ %d\n",
|
dev_err(&pdev->dev, "unable to request IRQ %d\n",
|
||||||
|
@ -185,7 +185,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = request_irq(encoder->irq_b, &rotary_encoder_irq,
|
err = request_irq(encoder->irq_b, &rotary_encoder_irq,
|
||||||
IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
|
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||||
DRV_NAME, encoder);
|
DRV_NAME, encoder);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "unable to request IRQ %d\n",
|
dev_err(&pdev->dev, "unable to request IRQ %d\n",
|
||||||
|
|
|
@ -188,7 +188,8 @@ static void serio_free_event(struct serio_event *event)
|
||||||
kfree(event);
|
kfree(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serio_remove_duplicate_events(struct serio_event *event)
|
static void serio_remove_duplicate_events(void *object,
|
||||||
|
enum serio_event_type type)
|
||||||
{
|
{
|
||||||
struct serio_event *e, *next;
|
struct serio_event *e, *next;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -196,13 +197,13 @@ static void serio_remove_duplicate_events(struct serio_event *event)
|
||||||
spin_lock_irqsave(&serio_event_lock, flags);
|
spin_lock_irqsave(&serio_event_lock, flags);
|
||||||
|
|
||||||
list_for_each_entry_safe(e, next, &serio_event_list, node) {
|
list_for_each_entry_safe(e, next, &serio_event_list, node) {
|
||||||
if (event->object == e->object) {
|
if (object == e->object) {
|
||||||
/*
|
/*
|
||||||
* If this event is of different type we should not
|
* If this event is of different type we should not
|
||||||
* look further - we only suppress duplicate events
|
* look further - we only suppress duplicate events
|
||||||
* that were sent back-to-back.
|
* that were sent back-to-back.
|
||||||
*/
|
*/
|
||||||
if (event->type != e->type)
|
if (type != e->type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
list_del_init(&e->node);
|
list_del_init(&e->node);
|
||||||
|
@ -245,7 +246,7 @@ static void serio_handle_event(struct work_struct *work)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
serio_remove_duplicate_events(event);
|
serio_remove_duplicate_events(event->object, event->type);
|
||||||
serio_free_event(event);
|
serio_free_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,10 +437,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
|
||||||
} else if (!strncmp(buf, "rescan", count)) {
|
} else if (!strncmp(buf, "rescan", count)) {
|
||||||
serio_disconnect_port(serio);
|
serio_disconnect_port(serio);
|
||||||
serio_find_driver(serio);
|
serio_find_driver(serio);
|
||||||
|
serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
|
||||||
} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
|
} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
|
||||||
serio_disconnect_port(serio);
|
serio_disconnect_port(serio);
|
||||||
error = serio_bind_driver(serio, to_serio_driver(drv));
|
error = serio_bind_driver(serio, to_serio_driver(drv));
|
||||||
put_driver(drv);
|
put_driver(drv);
|
||||||
|
serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
|
||||||
} else {
|
} else {
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,7 +519,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
/* Retrieve the physical and logical size for OEM devices */
|
/* Retrieve the physical and logical size for OEM devices */
|
||||||
error = wacom_retrieve_hid_descriptor(intf, features);
|
error = wacom_retrieve_hid_descriptor(intf, features);
|
||||||
if (error)
|
if (error)
|
||||||
goto fail2;
|
goto fail3;
|
||||||
|
|
||||||
wacom_setup_device_quirks(features);
|
wacom_setup_device_quirks(features);
|
||||||
|
|
||||||
|
|
|
@ -941,19 +941,15 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
|
||||||
struct ads7846_platform_data *pdata = spi->dev.platform_data;
|
struct ads7846_platform_data *pdata = spi->dev.platform_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* REVISIT when the irq can be triggered active-low, or if for some
|
/*
|
||||||
|
* REVISIT when the irq can be triggered active-low, or if for some
|
||||||
* reason the touchscreen isn't hooked up, we don't need to access
|
* reason the touchscreen isn't hooked up, we don't need to access
|
||||||
* the pendown state.
|
* the pendown state.
|
||||||
*/
|
*/
|
||||||
if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) {
|
|
||||||
dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdata->get_pendown_state) {
|
if (pdata->get_pendown_state) {
|
||||||
ts->get_pendown_state = pdata->get_pendown_state;
|
ts->get_pendown_state = pdata->get_pendown_state;
|
||||||
return 0;
|
} else if (gpio_is_valid(pdata->gpio_pendown)) {
|
||||||
}
|
|
||||||
|
|
||||||
err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
|
err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -964,6 +960,11 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
|
||||||
|
|
||||||
ts->gpio_pendown = pdata->gpio_pendown;
|
ts->gpio_pendown = pdata->gpio_pendown;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1354,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
||||||
err_put_regulator:
|
err_put_regulator:
|
||||||
regulator_put(ts->reg);
|
regulator_put(ts->reg);
|
||||||
err_free_gpio:
|
err_free_gpio:
|
||||||
if (ts->gpio_pendown != -1)
|
if (!ts->get_pendown_state)
|
||||||
gpio_free(ts->gpio_pendown);
|
gpio_free(ts->gpio_pendown);
|
||||||
err_cleanup_filter:
|
err_cleanup_filter:
|
||||||
if (ts->filter_cleanup)
|
if (ts->filter_cleanup)
|
||||||
|
@ -1383,8 +1384,13 @@ static int __devexit ads7846_remove(struct spi_device *spi)
|
||||||
regulator_disable(ts->reg);
|
regulator_disable(ts->reg);
|
||||||
regulator_put(ts->reg);
|
regulator_put(ts->reg);
|
||||||
|
|
||||||
if (ts->gpio_pendown != -1)
|
if (!ts->get_pendown_state) {
|
||||||
|
/*
|
||||||
|
* If we are not using specialized pendown method we must
|
||||||
|
* have been relying on gpio we set up ourselves.
|
||||||
|
*/
|
||||||
gpio_free(ts->gpio_pendown);
|
gpio_free(ts->gpio_pendown);
|
||||||
|
}
|
||||||
|
|
||||||
if (ts->filter_cleanup)
|
if (ts->filter_cleanup)
|
||||||
ts->filter_cleanup(ts->filter_data);
|
ts->filter_cleanup(ts->filter_data);
|
||||||
|
|
|
@ -51,6 +51,10 @@ MODULE_LICENSE("GPL");
|
||||||
#define W8001_PKTLEN_TPCCTL 11 /* control packet */
|
#define W8001_PKTLEN_TPCCTL 11 /* control packet */
|
||||||
#define W8001_PKTLEN_TOUCH2FG 13
|
#define W8001_PKTLEN_TOUCH2FG 13
|
||||||
|
|
||||||
|
/* resolution in points/mm */
|
||||||
|
#define W8001_PEN_RESOLUTION 100
|
||||||
|
#define W8001_TOUCH_RESOLUTION 10
|
||||||
|
|
||||||
struct w8001_coord {
|
struct w8001_coord {
|
||||||
u8 rdy;
|
u8 rdy;
|
||||||
u8 tsw;
|
u8 tsw;
|
||||||
|
@ -198,7 +202,7 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
|
||||||
query->y = 1024;
|
query->y = 1024;
|
||||||
if (query->panel_res)
|
if (query->panel_res)
|
||||||
query->x = query->y = (1 << query->panel_res);
|
query->x = query->y = (1 << query->panel_res);
|
||||||
query->panel_res = 10;
|
query->panel_res = W8001_TOUCH_RESOLUTION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,6 +398,8 @@ static int w8001_setup(struct w8001 *w8001)
|
||||||
|
|
||||||
input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
|
input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
|
||||||
input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
|
input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
|
||||||
|
input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION);
|
||||||
|
input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION);
|
||||||
input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
|
input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
|
||||||
if (coord.tilt_x && coord.tilt_y) {
|
if (coord.tilt_x && coord.tilt_y) {
|
||||||
input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
|
input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
|
||||||
|
@ -418,14 +424,17 @@ static int w8001_setup(struct w8001 *w8001)
|
||||||
w8001->max_touch_x = touch.x;
|
w8001->max_touch_x = touch.x;
|
||||||
w8001->max_touch_y = touch.y;
|
w8001->max_touch_y = touch.y;
|
||||||
|
|
||||||
/* scale to pen maximum */
|
|
||||||
if (w8001->max_pen_x && w8001->max_pen_y) {
|
if (w8001->max_pen_x && w8001->max_pen_y) {
|
||||||
|
/* if pen is supported scale to pen maximum */
|
||||||
touch.x = w8001->max_pen_x;
|
touch.x = w8001->max_pen_x;
|
||||||
touch.y = w8001->max_pen_y;
|
touch.y = w8001->max_pen_y;
|
||||||
|
touch.panel_res = W8001_PEN_RESOLUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
|
input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
|
||||||
input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
|
input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
|
||||||
|
input_abs_set_res(dev, ABS_X, touch.panel_res);
|
||||||
|
input_abs_set_res(dev, ABS_Y, touch.panel_res);
|
||||||
|
|
||||||
switch (touch.sensor_id) {
|
switch (touch.sensor_id) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -571,6 +571,7 @@ struct sysrq_state {
|
||||||
unsigned int alt_use;
|
unsigned int alt_use;
|
||||||
bool active;
|
bool active;
|
||||||
bool need_reinject;
|
bool need_reinject;
|
||||||
|
bool reinjecting;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sysrq_reinject_alt_sysrq(struct work_struct *work)
|
static void sysrq_reinject_alt_sysrq(struct work_struct *work)
|
||||||
|
@ -581,6 +582,10 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work)
|
||||||
unsigned int alt_code = sysrq->alt_use;
|
unsigned int alt_code = sysrq->alt_use;
|
||||||
|
|
||||||
if (sysrq->need_reinject) {
|
if (sysrq->need_reinject) {
|
||||||
|
/* we do not want the assignment to be reordered */
|
||||||
|
sysrq->reinjecting = true;
|
||||||
|
mb();
|
||||||
|
|
||||||
/* Simulate press and release of Alt + SysRq */
|
/* Simulate press and release of Alt + SysRq */
|
||||||
input_inject_event(handle, EV_KEY, alt_code, 1);
|
input_inject_event(handle, EV_KEY, alt_code, 1);
|
||||||
input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1);
|
input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1);
|
||||||
|
@ -589,6 +594,9 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work)
|
||||||
input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0);
|
input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0);
|
||||||
input_inject_event(handle, EV_KEY, alt_code, 0);
|
input_inject_event(handle, EV_KEY, alt_code, 0);
|
||||||
input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
|
input_inject_event(handle, EV_SYN, SYN_REPORT, 1);
|
||||||
|
|
||||||
|
mb();
|
||||||
|
sysrq->reinjecting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,6 +607,13 @@ static bool sysrq_filter(struct input_handle *handle,
|
||||||
bool was_active = sysrq->active;
|
bool was_active = sysrq->active;
|
||||||
bool suppress;
|
bool suppress;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not filter anything if we are in the process of re-injecting
|
||||||
|
* Alt+SysRq combination.
|
||||||
|
*/
|
||||||
|
if (sysrq->reinjecting)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case EV_SYN:
|
case EV_SYN:
|
||||||
|
@ -629,7 +644,7 @@ static bool sysrq_filter(struct input_handle *handle,
|
||||||
sysrq->alt_use = sysrq->alt;
|
sysrq->alt_use = sysrq->alt;
|
||||||
/*
|
/*
|
||||||
* If nothing else will be pressed we'll need
|
* If nothing else will be pressed we'll need
|
||||||
* to * re-inject Alt-SysRq keysroke.
|
* to re-inject Alt-SysRq keysroke.
|
||||||
*/
|
*/
|
||||||
sysrq->need_reinject = true;
|
sysrq->need_reinject = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#define MATRIX_MAX_ROWS 16
|
#define MATRIX_MAX_ROWS 32
|
||||||
#define MATRIX_MAX_COLS 16
|
#define MATRIX_MAX_COLS 32
|
||||||
|
|
||||||
#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
|
#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
|
||||||
(((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
|
(((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
|
||||||
|
|
Loading…
Reference in New Issue