Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 177076
b: refs/heads/master
c: 4e8d340
h: refs/heads/master
v: v3
  • Loading branch information
Dmitry Torokhov committed Dec 12, 2009
1 parent a42f57f commit 47aa623
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 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: 7105d2ea73e1391b681d0e1212c42f561c64d429
refs/heads/master: 4e8d340daac46cec8a0f8b3b0f228274fac913ba
34 changes: 26 additions & 8 deletions trunk/drivers/input/serio/i8042.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,25 @@ static void i8042_stop(struct serio *serio)
port->serio = NULL;
}

/*
* i8042_filter() filters out unwanted bytes from the input data stream.
* 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)
{
if (unlikely(i8042_suppress_kbd_ack)) {
if ((~str & I8042_STR_AUXDATA) &&
(data == 0xfa || data == 0xfe)) {
i8042_suppress_kbd_ack--;
dbg("Extra keyboard ACK - filtered out\n");
return true;
}
}

return false;
}

/*
* i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes
Expand All @@ -381,18 +400,20 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
unsigned char str, data;
unsigned int dfl;
unsigned int port_no;
bool filtered;
int ret = 1;

spin_lock_irqsave(&i8042_lock, flags);

str = i8042_read_status();
if (unlikely(~str & I8042_STR_OBF)) {
spin_unlock_irqrestore(&i8042_lock, flags);
if (irq) dbg("Interrupt %d, without any data", irq);
ret = 0;
goto out;
}

data = i8042_read_data();
spin_unlock_irqrestore(&i8042_lock, flags);

if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
static unsigned long last_transmit;
Expand Down Expand Up @@ -447,14 +468,11 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");

if (unlikely(i8042_suppress_kbd_ack))
if (port_no == I8042_KBD_PORT_NO &&
(data == 0xfa || data == 0xfe)) {
i8042_suppress_kbd_ack--;
goto out;
}
filtered = i8042_filter(data, str);

spin_unlock_irqrestore(&i8042_lock, flags);

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

out:
Expand Down

0 comments on commit 47aa623

Please sign in to comment.