From patchwork Thu Dec 10 23:25:32 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 66369 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nBANQ2OV015871 for ; Thu, 10 Dec 2009 23:26:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755457AbZLJXZy (ORCPT ); Thu, 10 Dec 2009 18:25:54 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1758370AbZLJXZy (ORCPT ); Thu, 10 Dec 2009 18:25:54 -0500 Received: from cavan.codon.org.uk ([93.93.128.6]:48521 "EHLO cavan.codon.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755457AbZLJXZx (ORCPT ); Thu, 10 Dec 2009 18:25:53 -0500 Received: from 209-6-34-250.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.34.250] helo=localhost.localdomain) by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1NIsOO-0004FX-3w; Thu, 10 Dec 2009 23:25:52 +0000 From: Matthew Garrett To: dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org, linux-acpi@vger.kernel.org, lenb@kernel.org, Matthew Garrett Subject: [PATCH 1/2] input: Allow filtering of i8042 events Date: Thu, 10 Dec 2009 18:25:32 -0500 Message-Id: <1260487533-4960-1-git-send-email-mjg@redhat.com> X-Mailer: git-send-email 1.6.5.2 In-Reply-To: <20091209203939.GC10138@core.coreip.homeip.net> References: <20091209203939.GC10138@core.coreip.homeip.net> X-SA-Do-Not-Run: Yes X-SA-Exim-Connect-IP: 209.6.34.250 X-SA-Exim-Mail-From: mjg@redhat.com X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 1df02d2..a16d813 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -110,9 +110,9 @@ struct i8042_port { signed char mux; }; -#define I8042_KBD_PORT_NO 0 -#define I8042_AUX_PORT_NO 1 -#define I8042_MUX_PORT_NO 2 +#define I8042_KBD_PORT_NO 0 +#define I8042_AUX_PORT_NO 1 +#define I8042_MUX_PORT_NO 2 #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) static struct i8042_port i8042_ports[I8042_NUM_PORTS]; @@ -127,6 +127,9 @@ static struct platform_device *i8042_platform_device; static irqreturn_t i8042_interrupt(int irq, void *dev_id); +static bool (*i8042_filter)(unsigned char data, unsigned char str, + struct serio *port); + void i8042_lock_chip(void) { mutex_lock(&i8042_mutex); @@ -139,6 +142,46 @@ void i8042_unlock_chip(void) } EXPORT_SYMBOL(i8042_unlock_chip); +int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i8042_lock, flags); + + if (i8042_filter) { + ret = -EBUSY; + goto out; + } + + i8042_filter = filter; +out: + spin_unlock_irqrestore(&i8042_lock, flags); + return ret; +} +EXPORT_SYMBOL(i8042_install_filter); + +int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i8042_lock, flags); + + if (!i8042_filter || i8042_filter != filter) { + ret = -EBUSY; + goto out; + } + + i8042_filter = NULL; +out: + spin_unlock_irqrestore(&i8042_lock, flags); + return ret; +} +EXPORT_SYMBOL(i8042_remove_filter); + /* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * be ready for reading values from it / writing values to it. @@ -454,8 +497,12 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) goto out; } - if (likely(port->exists)) - serio_interrupt(port->serio, data, dfl); + if (likely(port->exists)) { + if (i8042_filter && i8042_filter(data, str, port->serio)) + goto out; + else + serio_interrupt(port->serio, data, dfl); + } out: return IRQ_RETVAL(ret); diff --git a/include/linux/i8042.h b/include/linux/i8042.h index 60c3360..bf2ccaf 100644 --- a/include/linux/i8042.h +++ b/include/linux/i8042.h @@ -39,6 +39,10 @@ void i8042_lock_chip(void); void i8042_unlock_chip(void); int i8042_command(unsigned char *param, int command); bool i8042_check_port_owner(const struct serio *); +int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)); +int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)); #else @@ -60,6 +64,18 @@ bool i8042_check_port_owner(const struct serio *serio) return false; } +int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)) +{ + return -ENODEV; +} + +int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)) +{ + return -ENODEV; +} + #endif #endif