Commit 77606ab3 authored by Vojtech Pavlik's avatar Vojtech Pavlik

input: Explicit variable access rules for psmouse.c, using bitops.

parent 7d2a5db9
...@@ -435,7 +435,7 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command) ...@@ -435,7 +435,7 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
atkbd->cmdcnt = receive; atkbd->cmdcnt = receive;
if (command == ATKBD_CMD_RESET_BAT) if (command == ATKBD_CMD_RESET_BAT)
timeout = 2000000; /* 2 sec */ timeout = 4000000; /* 4 sec */
if (receive && param) if (receive && param)
for (i = 0; i < receive; i++) for (i = 0; i < receive; i++)
......
...@@ -142,34 +142,45 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -142,34 +142,45 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_TIMEOUT ? " timeout" : "",
flags & SERIO_PARITY ? " bad parity" : ""); flags & SERIO_PARITY ? " bad parity" : "");
if (psmouse->acking) { psmouse->nak = 1;
psmouse->ack = -1; clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
psmouse->acking = 0; clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
}
psmouse->pktcnt = 0;
goto out; goto out;
} }
if (psmouse->acking) { if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags))
switch (data) { switch (data) {
case PSMOUSE_RET_ACK: case PSMOUSE_RET_ACK:
psmouse->ack = 1; psmouse->nak = 0;
clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
goto out;
break; break;
case PSMOUSE_RET_NAK: case PSMOUSE_RET_NAK:
psmouse->ack = -1; psmouse->nak = 1;
break; clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
goto out;
default: default:
psmouse->ack = 1; /* Workaround for mice which don't ACK the Get ID command */ psmouse->nak = 0; /* Workaround for mice which don't ACK the Get ID command */
if (psmouse->cmdcnt) clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
psmouse->cmdbuf[--psmouse->cmdcnt] = data; if (!test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags))
break; goto out;
} }
psmouse->acking = 0;
goto out;
}
if (psmouse->cmdcnt) { if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) {
psmouse->cmdbuf[--psmouse->cmdcnt] = data;
psmouse->cmdcnt--;
psmouse->cmdbuf[psmouse->cmdcnt] = data;
if (psmouse->cmdcnt == 1) {
if (data != 0xab && data != 0xac)
clear_bit(PSMOUSE_FLAG_ID, &psmouse->flags);
clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
}
if (!psmouse->cmdcnt)
clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
goto out; goto out;
} }
...@@ -242,18 +253,15 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -242,18 +253,15 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte) static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
{ {
int timeout = 10000; /* 100 msec */ int timeout = 200000; /* 200 msec */
psmouse->ack = 0;
psmouse->acking = 1;
if (serio_write(psmouse->serio, byte)) { set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
psmouse->acking = 0; if (serio_write(psmouse->serio, byte))
return -1; return -1;
} while (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags) && timeout--) udelay(1);
clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
while (!psmouse->ack && timeout--) udelay(10);
return -(psmouse->ack <= 0); return -psmouse->nak;
} }
/* /*
...@@ -271,46 +279,62 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -271,46 +279,62 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
psmouse->cmdcnt = receive; psmouse->cmdcnt = receive;
if (command == PSMOUSE_CMD_RESET_BAT) if (command == PSMOUSE_CMD_RESET_BAT)
timeout = 4000000; /* 4 sec */ timeout = 4000000; /* 4 sec */
/* initialize cmdbuf with preset values from param */ if (receive && param)
if (receive) for (i = 0; i < receive; i++)
for (i = 0; i < receive; i++) psmouse->cmdbuf[(receive - 1) - i] = param[i];
psmouse->cmdbuf[(receive - 1) - i] = param[i];
if (receive) {
set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
set_bit(PSMOUSE_FLAG_ID, &psmouse->flags);
}
if (command & 0xff) if (command & 0xff)
if (psmouse_sendbyte(psmouse, command & 0xff)) if (psmouse_sendbyte(psmouse, command & 0xff)) {
return (psmouse->cmdcnt = 0) - 1; clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
return -1;
}
for (i = 0; i < send; i++) for (i = 0; i < send; i++)
if (psmouse_sendbyte(psmouse, param[i])) if (psmouse_sendbyte(psmouse, param[i])) {
return (psmouse->cmdcnt = 0) - 1; clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
return -1;
}
while (psmouse->cmdcnt && timeout--) { while (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags) && timeout--) {
if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT && if (!test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags)) {
timeout > 100000) /* do not run in a endless loop */
timeout = 100000; /* 1 sec */ if (command == PSMOUSE_CMD_RESET_BAT && timeout > 100000)
timeout = 100000;
if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_GETID && if (command == PSMOUSE_CMD_GETID && !test_bit(PSMOUSE_FLAG_ID, &psmouse->flags)) {
psmouse->cmdbuf[1] != 0xab && psmouse->cmdbuf[1] != 0xac) { clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
psmouse->cmdcnt = 0; psmouse->cmdcnt = 0;
break; break;
}
} }
udelay(1); udelay(1);
} }
for (i = 0; i < receive; i++) clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
param[i] = psmouse->cmdbuf[(receive - 1) - i];
if (param)
for (i = 0; i < receive; i++)
param[i] = psmouse->cmdbuf[(receive - 1) - i];
if (command == PSMOUSE_CMD_RESET_BAT && psmouse->cmdcnt == 1)
return 0;
if (psmouse->cmdcnt) if (psmouse->cmdcnt)
return (psmouse->cmdcnt = 0) - 1; return -1;
return 0; return 0;
} }
/* /*
* psmouse_sliced_command() sends an extended PS/2 command to the mouse * psmouse_sliced_command() sends an extended PS/2 command to the mouse
* using sliced syntax, understood by advanced devices, such as Logitech * using sliced syntax, understood by advanced devices, such as Logitech
...@@ -735,7 +759,12 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -735,7 +759,12 @@ static int psmouse_reconnect(struct serio *serio)
} }
psmouse->state = PSMOUSE_CMD_MODE; psmouse->state = PSMOUSE_CMD_MODE;
psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
psmouse->pktcnt = psmouse->out_of_sync = 0;
if (psmouse->reconnect) { if (psmouse->reconnect) {
if (psmouse->reconnect(psmouse)) if (psmouse->reconnect(psmouse))
return -1; return -1;
......
...@@ -22,6 +22,11 @@ ...@@ -22,6 +22,11 @@
#define PSMOUSE_ACTIVATED 1 #define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2 #define PSMOUSE_IGNORE 2
#define PSMOUSE_FLAG_ACK 0 /* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_CMD 1 /* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD1 2 /* First byte of command response */
#define PSMOUSE_FLAG_ID 3 /* First byte is not keyboard ID */
/* psmouse protocol handler return codes */ /* psmouse protocol handler return codes */
typedef enum { typedef enum {
PSMOUSE_BAD_DATA, PSMOUSE_BAD_DATA,
...@@ -54,11 +59,11 @@ struct psmouse { ...@@ -54,11 +59,11 @@ struct psmouse {
unsigned long last; unsigned long last;
unsigned long out_of_sync; unsigned long out_of_sync;
unsigned char state; unsigned char state;
char acking; unsigned char nak;
volatile char ack;
char error; char error;
char devname[64]; char devname[64];
char phys[32]; char phys[32];
unsigned long flags;
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
int (*reconnect)(struct psmouse *psmouse); int (*reconnect)(struct psmouse *psmouse);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment