improved ps2_dev_command ACK handling, also added workaround for mice not ACKing a get device id command

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16051 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2006-01-23 21:17:32 +00:00
parent da68da3e1b
commit a9e8a72a70
2 changed files with 60 additions and 35 deletions

View File

@ -93,8 +93,21 @@ ps2_dev_handle_int(ps2_dev *dev, uint8 data)
if (flags & PS2_FLAG_CMD) {
if ((flags & (PS2_FLAG_ACK | PS2_FLAG_NACK)) == 0) {
atomic_or(&dev->flags, data == 0xfa ? PS2_FLAG_ACK : PS2_FLAG_NACK);
release_sem_etc(dev->result_sem, 1, B_DO_NOT_RESCHEDULE);
int cnt = 1;
if ((flags & PS2_FLAG_GETID) && (data == 0 || data == 3 || data == 4)) {
dprintf("ps2_dev_handle_int stupid mouse!\n");
atomic_or(&dev->flags, PS2_FLAG_ACK);
if (dev->result_buf_cnt) {
dev->result_buf[dev->result_buf_idx] = data;
dev->result_buf_idx++;
dev->result_buf_cnt--;
if (dev->result_buf_cnt == 0)
cnt++;
}
} else {
atomic_or(&dev->flags, data == 0xfa ? PS2_FLAG_ACK : PS2_FLAG_NACK);
}
release_sem_etc(dev->result_sem, cnt, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER;
} else if (dev->result_buf_cnt) {
dev->result_buf[dev->result_buf_idx] = data;
@ -132,23 +145,35 @@ ps2_dev_handle_int(ps2_dev *dev, uint8 data)
status_t
ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
status_t res = B_OK;
status_t res;
bigtime_t start;
int i, count;
int32 sem_count;
dprintf("ps2_dev_command %02x, %d out, in %d, dev %s\n", cmd, out_count, in_count, dev->name);
res = get_sem_count(dev->result_sem, &sem_count);
if (res == B_OK && sem_count != 0) {
dprintf("ps2_dev_command: sem_count %ld, fixing!\n", sem_count);
if (sem_count > 0)
acquire_sem_etc(dev->result_sem, sem_count, 0, 0);
else
release_sem_etc(dev->result_sem, -sem_count, 0);
}
dev->flags |= PS2_FLAG_CMD;
dev->flags &= ~(PS2_FLAG_ACK | PS2_FLAG_NACK);
dev->result_buf_cnt = in_count;
dev->result_buf_idx = 0;
dev->result_buf = in;
start = system_time();
res = B_OK;
for (i = -1; res == B_OK && i < out_count; i++) {
dev->flags &= ~(PS2_FLAG_ACK | PS2_FLAG_NACK | PS2_FLAG_GETID);
if (i == -1 && cmd == PS2_CMD_GET_DEVICE_ID)
dev->flags |= PS2_FLAG_GETID;
if (!(dev->flags & PS2_FLAG_KEYB)) {
uint8 prefix_cmd;
if (gMultiplexingActive)
@ -164,41 +189,36 @@ ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8
if (res == B_OK) {
ps2_write_data(i == -1 ? cmd : out[i]);
}
}
dprintf("ps2_dev_command send-time %Ld\n", system_time() - start);
start = system_time();
res = acquire_sem_etc(dev->result_sem, 1, B_RELATIVE_TIMEOUT, 4000000);
dprintf("ps2_dev_command wait for ack res %08x, wait-time %Ld\n", res, system_time() - start);
if (dev->flags & PS2_FLAG_ACK) {
dprintf("ps2_dev_command got ACK\n");
}
if (dev->flags & PS2_FLAG_NACK) {
dev->flags &= ~PS2_FLAG_CMD;
dprintf("ps2_dev_command got NACK\n");
return B_ERROR;
}
if (res != B_OK) {
dprintf("ps2_dev_command send failed\n");
}
if (in_count != 0) {
dprintf("ps2_dev_command waiting for result\n");
start = system_time();
res = acquire_sem_etc(dev->result_sem, 1, B_RELATIVE_TIMEOUT, 4000000);
dprintf("ps2_dev_command wait for ack res %08x, wait-time %Ld\n", res, system_time() - start);
if (res != B_OK)
break;
if (dev->flags & PS2_FLAG_ACK) {
dprintf("ps2_dev_command got ACK\n");
}
if (dev->flags & PS2_FLAG_NACK) {
dprintf("ps2_dev_command got NACK\n");
res = B_ERROR;
break;
}
}
if (res == B_OK && in_count != 0) {
dprintf("ps2_dev_command waiting input data\n");
start = system_time();
res = acquire_sem_etc(dev->result_sem, 1, B_RELATIVE_TIMEOUT, 4000000);
count = in_count - dev->result_buf_cnt;
dev->result_buf_cnt = 0;
dprintf("ps2_dev_command res %08x, in %d, wait-time %Ld\n", res, count, system_time() - start);
dprintf("ps2_dev_command wait for input res %08x, in %d, wait-time %Ld\n", res, count, system_time() - start);
for (i = 0; i < count; i++)
dprintf("ps2_dev_command data %02x\n", in[i]);
@ -206,6 +226,10 @@ ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8
dev->flags &= ~PS2_FLAG_CMD;
if (res != B_OK) {
dprintf("ps2_dev_command send failed\n");
}
return res;
}

View File

@ -42,6 +42,7 @@ extern ps2_dev ps2_device[PS2_DEVICE_COUNT];
#define PS2_FLAG_CMD (1<<3)
#define PS2_FLAG_ACK (1<<4)
#define PS2_FLAG_NACK (1<<5)
#define PS2_FLAG_GETID (1<<6)
status_t ps2_dev_init(void);
void ps2_dev_exit(void);