Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 177077
b: refs/heads/master
c: 967c9ef
h: refs/heads/master
i:
  177075: a42f57f
v: v3
  • Loading branch information
Matthew Garrett authored and Dmitry Torokhov committed Dec 12, 2009
1 parent 47aa623 commit 353393a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4e8d340daac46cec8a0f8b3b0f228274fac913ba
refs/heads/master: 967c9ef9b8c3bdec1bd3a380edac19e0b9fbeadc
58 changes: 55 additions & 3 deletions trunk/drivers/input/serio/i8042.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ static unsigned char i8042_suppress_kbd_ack;
static struct platform_device *i8042_platform_device;

static irqreturn_t i8042_interrupt(int irq, void *dev_id);
static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
struct serio *serio);

void i8042_lock_chip(void)
{
Expand All @@ -139,6 +141,48 @@ void i8042_unlock_chip(void)
}
EXPORT_SYMBOL(i8042_unlock_chip);

int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
unsigned long flags;
int ret = 0;

spin_lock_irqsave(&i8042_lock, flags);

if (i8042_platform_filter) {
ret = -EBUSY;
goto out;
}

i8042_platform_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_platform_filter != filter) {
ret = -EINVAL;
goto out;
}

i8042_platform_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.
Expand Down Expand Up @@ -373,7 +417,8 @@ static void i8042_stop(struct serio *serio)
* It is called from i8042_interrupt and thus is running with interrupts
* off and i8042_lock held.
*/
static bool i8042_filter(unsigned char data, unsigned char str)
static bool i8042_filter(unsigned char data, unsigned char str,
struct serio *serio)
{
if (unlikely(i8042_suppress_kbd_ack)) {
if ((~str & I8042_STR_AUXDATA) &&
Expand All @@ -384,6 +429,11 @@ static bool i8042_filter(unsigned char data, unsigned char str)
}
}

if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) {
dbg("Filtered out by platfrom filter\n");
return true;
}

return false;
}

Expand All @@ -396,6 +446,7 @@ static bool i8042_filter(unsigned char data, unsigned char str)
static irqreturn_t i8042_interrupt(int irq, void *dev_id)
{
struct i8042_port *port;
struct serio *serio;
unsigned long flags;
unsigned char str, data;
unsigned int dfl;
Expand Down Expand Up @@ -462,18 +513,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
}

port = &i8042_ports[port_no];
serio = port->exists ? port->serio : NULL;

dbg("%02x <- i8042 (interrupt, %d, %d%s%s)",
data, port_no, irq,
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");

filtered = i8042_filter(data, str);
filtered = i8042_filter(data, str, serio);

spin_unlock_irqrestore(&i8042_lock, flags);

if (likely(port->exists && !filtered))
serio_interrupt(port->serio, data, dfl);
serio_interrupt(serio, data, dfl);

out:
return IRQ_RETVAL(ret);
Expand Down
18 changes: 17 additions & 1 deletion trunk/include/linux/i8042.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *serio));
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio));

#else

Expand All @@ -52,14 +56,26 @@ void i8042_unlock_chip(void)

int i8042_command(unsigned char *param, int command)
{
return -ENOSYS;
return -ENODEV;
}

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 *serio))
{
return -ENODEV;
}

int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
return -ENODEV;
}

#endif

#endif

0 comments on commit 353393a

Please sign in to comment.