static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) { switch (command) { case PS2_CMD_RESET_BAT: /* * Device has sent the first response byte after * reset command, reset is thus done, so we can * shorten the timeout. * The next byte will come soon (keyboard) or not * at all (mouse). */ if (timeout > msecs_to_jiffies(100)) timeout = msecs_to_jiffies(100); break; case PS2_CMD_GETID: /* * If device behind the port is not a keyboard there * won't be 2nd byte of ID response. */ if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { serio_pause_rx(ps2dev->serio); ps2dev->flags = ps2dev->cmdcnt = 0; serio_continue_rx(ps2dev->serio); timeout = 0; } break; default: break; } return timeout; }
static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) { switch (command) { case PS2_CMD_RESET_BAT: /* * Device has sent the first response byte after * reset command, reset is thus done, so we can * shorten the timeout. * The next byte will come soon (keyboard) or not * at all (mouse). */ if (timeout > msecs_to_jiffies(100)) timeout = msecs_to_jiffies(100); break; case PS2_CMD_GETID: /* * Microsoft Natural Elite keyboard responds to * the GET ID command as it were a mouse, with * a single byte. Fail the command so atkbd will * use alternative probe to detect it. */ if (ps2dev->cmdbuf[1] == 0xaa) { serio_pause_rx(ps2dev->serio); ps2dev->flags = 0; serio_continue_rx(ps2dev->serio); timeout = 0; } /* * If device behind the port is not a keyboard there * won't be 2nd byte of ID response. */ if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { serio_pause_rx(ps2dev->serio); ps2dev->flags = ps2dev->cmdcnt = 0; serio_continue_rx(ps2dev->serio); timeout = 0; } break; default: break; } return timeout; }
int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) { serio_pause_rx(ps2dev->serio); ps2dev->nak = 1; ps2dev->flags |= PS2_FLAG_ACK; serio_continue_rx(ps2dev->serio); if (serio_write(ps2dev->serio, byte) == 0) wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_ACK), msecs_to_jiffies(timeout)); serio_pause_rx(ps2dev->serio); ps2dev->flags &= ~PS2_FLAG_ACK; serio_continue_rx(ps2dev->serio); return -ps2dev->nak; }
void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) { if (maxbytes > sizeof(ps2dev->cmdbuf)) { WARN_ON(1); maxbytes = sizeof(ps2dev->cmdbuf); } down(&ps2dev->cmd_sem); serio_pause_rx(ps2dev->serio); ps2dev->flags = PS2_FLAG_CMD; ps2dev->cmdcnt = maxbytes; serio_continue_rx(ps2dev->serio); wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), msecs_to_jiffies(timeout)); up(&ps2dev->cmd_sem); }
static int elo_command_10(struct elo *elo, unsigned char *packet) { int rc = -1; int i; unsigned char csum = 0xaa + ELO10_LEAD_BYTE; mutex_lock(&elo->cmd_mutex); serio_pause_rx(elo->serio); elo->expected_packet = toupper(packet[0]); init_completion(&elo->cmd_done); serio_continue_rx(elo->serio); if (serio_write(elo->serio, ELO10_LEAD_BYTE)) goto out; for (i = 0; i < ELO10_PACKET_LEN; i++) { csum += packet[i]; if (serio_write(elo->serio, packet[i])) goto out; } if (serio_write(elo->serio, csum)) goto out; wait_for_completion_timeout(&elo->cmd_done, HZ); if (elo->expected_packet == ELO10_TOUCH_PACKET) { /* We are back in reporting mode, the command was ACKed */ memcpy(packet, elo->response, ELO10_PACKET_LEN); rc = 0; } out: mutex_unlock(&elo->cmd_mutex); return rc; }
int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) { int timeout; int send = (command >> 12) & 0xf; int receive = (command >> 8) & 0xf; int rc = -1; int i; if (receive > sizeof(ps2dev->cmdbuf)) { WARN_ON(1); return -1; } if (send && !param) { WARN_ON(1); return -1; } serio_pause_rx(ps2dev->serio); ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; ps2dev->cmdcnt = receive; if (receive && param) for (i = 0; i < receive; i++) ps2dev->cmdbuf[(receive - 1) - i] = param[i]; serio_continue_rx(ps2dev->serio); /* * Some devices (Synaptics) peform the reset before * ACKing the reset command, and so it can take a long * time before the ACK arrrives. */ if (ps2_sendbyte(ps2dev, command & 0xff, command == PS2_CMD_RESET_BAT ? 1000 : 200)) goto out; for (i = 0; i < send; i++) if (ps2_sendbyte(ps2dev, param[i], 200)) goto out; /* * The reset command takes a long time to execute. */ timeout = msecs_to_jiffies(command == PS2_CMD_RESET_BAT ? 4000 : 500); timeout = wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD1), timeout); if (ps2dev->cmdcnt && !(ps2dev->flags & PS2_FLAG_CMD1)) { timeout = ps2_adjust_timeout(ps2dev, command, timeout); wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), timeout); } if (param) for (i = 0; i < receive; i++) param[i] = ps2dev->cmdbuf[(receive - 1) - i]; if (ps2dev->cmdcnt && (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1)) goto out; rc = 0; out: serio_pause_rx(ps2dev->serio); ps2dev->flags = 0; serio_continue_rx(ps2dev->serio); return rc; }
static void sunkbd_enable(struct sunkbd *sunkbd, int enable) { serio_pause_rx(sunkbd->serio); sunkbd->enabled = enable; serio_continue_rx(sunkbd->serio); }