@@ -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);
@@ -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