From patchwork Thu Oct 7 20:35:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wessel X-Patchwork-Id: 238921 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o97Katdc012785 for ; Thu, 7 Oct 2010 20:36:56 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755718Ab0JGUgX (ORCPT ); Thu, 7 Oct 2010 16:36:23 -0400 Received: from mail.windriver.com ([147.11.1.11]:57529 "EHLO mail.windriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755617Ab0JGUgJ (ORCPT ); Thu, 7 Oct 2010 16:36:09 -0400 Received: from ALA-MAIL03.corp.ad.wrs.com (ala-mail03 [147.11.57.144]) by mail.windriver.com (8.14.3/8.14.3) with ESMTP id o97KZsTQ016053; Thu, 7 Oct 2010 13:35:54 -0700 (PDT) Received: from ala-mail06.corp.ad.wrs.com ([147.11.57.147]) by ALA-MAIL03.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Thu, 7 Oct 2010 13:35:53 -0700 Received: from localhost.localdomain ([172.25.32.37]) by ala-mail06.corp.ad.wrs.com with Microsoft SMTPSVC(6.0.3790.1830); Thu, 7 Oct 2010 13:35:53 -0700 From: Jason Wessel To: dmitry.torokhov@gmail.com Cc: kgdb-bugreport@lists.sourceforge.net, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Jason Wessel , Greg Kroah-Hartman Subject: [PATCH 3/3] sysrq, keyboard: properly deal with alt-sysrq in sysrq input filter Date: Thu, 7 Oct 2010 15:35:48 -0500 Message-Id: <1286483748-1171-4-git-send-email-jason.wessel@windriver.com> X-Mailer: git-send-email 1.6.4.rc1 In-Reply-To: <1286483748-1171-1-git-send-email-jason.wessel@windriver.com> References: <1286483748-1171-1-git-send-email-jason.wessel@windriver.com> X-OriginalArrivalTime: 07 Oct 2010 20:35:53.0908 (UTC) FILETIME=[3CDAA740:01CB665F] Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 07 Oct 2010 20:36:56 +0000 (UTC) diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index ef31bb8..b1fad74 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -566,6 +566,57 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] = static bool sysrq_down; static int sysrq_alt_use; static int sysrq_alt; +static bool sysrq_kbd_triggered; + +/* + * This function was a copy of input_pass_event but modified to allow + * by-passing a specific filter, to allow for injected events without + * filter recursion. + */ +static void input_pass_event_ignore(struct input_dev *dev, + unsigned int type, unsigned int code, int value, + struct input_handle *ignore_handle) +{ + struct input_handler *handler; + struct input_handle *handle; + + rcu_read_lock(); + + handle = rcu_dereference(dev->grab); + if (handle) + handle->handler->event(handle, type, code, value); + else { + bool filtered = false; + + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { + if (!handle->open || handle == ignore_handle) + continue; + handler = handle->handler; + if (!handler->filter) { + if (filtered) + break; + + handler->event(handle, type, code, value); + + } else if (handler->filter(handle, type, code, value)) + filtered = true; + } + } + + rcu_read_unlock(); +} + +/* + * Pass along alt-print_screen, if there was no sysrq processing by + * sending a key press down and then passing the key up event. + */ +static void simulate_alt_sysrq(struct input_handle *handle) +{ + input_pass_event_ignore(handle->dev, EV_KEY, KEY_SYSRQ, 1, handle); + input_pass_event_ignore(handle->dev, EV_SYN, SYN_REPORT, 0, handle); + input_pass_event_ignore(handle->dev, EV_KEY, KEY_SYSRQ, 0, handle); + input_pass_event_ignore(handle->dev, EV_SYN, SYN_REPORT, 0, handle); +} static bool sysrq_filter(struct input_handle *handle, unsigned int type, unsigned int code, int value) @@ -580,9 +631,11 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type, if (value) sysrq_alt = code; else { - if (sysrq_down && code == sysrq_alt_use) + if (sysrq_down && code == sysrq_alt_use) { sysrq_down = false; - + if (!sysrq_kbd_triggered) + simulate_alt_sysrq(handle); + } sysrq_alt = 0; } break; @@ -590,13 +643,18 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type, case KEY_SYSRQ: if (value == 1 && sysrq_alt) { sysrq_down = true; + sysrq_kbd_triggered = false; sysrq_alt_use = sysrq_alt; } break; default: - if (sysrq_down && value && value != 2) + if (sysrq_down && value && value != 2 && !sysrq_kbd_triggered) { + sysrq_kbd_triggered = true; __handle_sysrq(sysrq_xlate[code], true); + /* Clear handled keys from being flagged as a repeated stroke */ + __clear_bit(code, handle->dev->key); + } break; }