From 45d3c4ec1468b8373e27e6f95216b3281c7a6ff9 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Thu, 13 Apr 2006 14:57:16 +0000 Subject: [PATCH] Implemented hotplug support conforming to the active multiplexing specification. Works with my notebook, but kernel support for unpublishing devices is broken. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17123 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/bus_managers/ps2/ps2_common.c | 15 ++++++++- src/add-ons/kernel/bus_managers/ps2/ps2_dev.c | 33 +++++++++++-------- src/add-ons/kernel/bus_managers/ps2/ps2_dev.h | 5 +-- .../kernel/bus_managers/ps2/ps2_keyboard.c | 7 +--- .../kernel/bus_managers/ps2/ps2_mouse.c | 4 +-- 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_common.c b/src/add-ons/kernel/bus_managers/ps2/ps2_common.c index d8c4694325..93cdd58ea5 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_common.c +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_common.c @@ -242,6 +242,7 @@ ps2_interrupt(void* cookie) { uint8 ctrl; uint8 data; + bool error; ps2_dev *dev; ctrl = ps2_read_ctrl(); @@ -259,18 +260,30 @@ ps2_interrupt(void* cookie) uint8 idx; if (gActiveMultiplexingEnabled) { idx = ctrl >> 6; + error = (ctrl & 0x04) != 0; TRACE(("ps2_interrupt: ctrl 0x%02x, data 0x%02x (mouse %d)\n", ctrl, data, idx)); } else { idx = 0; + error = (ctrl & 0xC0) != 0; TRACE(("ps2_interrupt: ctrl 0x%02x, data 0x%02x (aux)\n", ctrl, data)); } dev = &ps2_device[PS2_DEVICE_MOUSE + idx]; } else { TRACE(("ps2_interrupt: ctrl 0x%02x, data 0x%02x (keyb)\n", ctrl, data)); dev = &ps2_device[PS2_DEVICE_KEYB]; + error = (ctrl & 0xC0) != 0; + + // TODO: remove me again; let us drop into the kernel debugger with F12 + if (data == 88) + panic("keyboard requested halt.\n"); } - return ps2_dev_handle_int(dev, data); + dev->history[1] = dev->history[0]; + dev->history[0].time = system_time(); + dev->history[0].data = data; + dev->history[0].error = error; + + return ps2_dev_handle_int(dev); } diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c index 4072421d7d..81fc7ab27a 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.c @@ -90,8 +90,9 @@ ps2_dev_unpublish(ps2_dev *dev) int32 -ps2_dev_handle_int(ps2_dev *dev, uint8 data) +ps2_dev_handle_int(ps2_dev *dev) { + const uint8 data = dev->history[0].data; uint32 flags; flags = atomic_get(&dev->flags); @@ -142,27 +143,33 @@ ps2_dev_handle_int(ps2_dev *dev, uint8 data) pass_to_handler: + if ((flags & PS2_FLAG_KEYB) == 0) { + if (dev->history[0].error && data == 0xfd) { + dprintf("ps2: hot removal of %s\n", dev->name); + ps2_service_notify_device_removed(dev); + return B_INVOKE_SCHEDULER; + } + if (data == 0x00 && dev->history[1].data == 0xaa && (dev->history[0].time - dev->history[1].time) < 50000) { + dprintf("ps2: hot plugin of %s\n", dev->name); + ps2_service_notify_device_added(dev); + return B_INVOKE_SCHEDULER; + } + } + if (!dev->active) { - ps2_service_notify_device_added(dev); dprintf("ps2: %s not active, data 0x%02x dropped\n", dev->name, data); + if (data != 0x00 && data != 0xaa) { + dprintf("ps2: possibly a hot plugin of %s\n", dev->name); + ps2_service_notify_device_added(dev); + return B_INVOKE_SCHEDULER; + } return B_HANDLED_INTERRUPT; } if ((flags & PS2_FLAG_ENABLED) == 0) { dprintf("ps2: %s not enabled, data 0x%02x dropped\n", dev->name, data); - // TODO: remove me again; let us drop into the kernel debugger with F12 - if ((flags & PS2_FLAG_KEYB) != 0 && data == 88) - panic("keyboard requested halt.\n"); - return B_HANDLED_INTERRUPT; } - - dev->history[4] = dev->history[3]; - dev->history[3] = dev->history[2]; - dev->history[2] = dev->history[1]; - dev->history[1] = dev->history[0]; - dev->history[0].time = system_time(); - dev->history[0].data = data; return dev->handle_int(dev); } diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h index 46cc6cbe8c..e25652fe39 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.h @@ -19,6 +19,7 @@ typedef struct { bigtime_t time; uint8 data; + bool error; } data_history; struct ps2_dev @@ -32,7 +33,7 @@ struct ps2_dev int result_buf_idx; int result_buf_cnt; void * cookie; - data_history history[5]; + data_history history[2]; // functions void (*disconnect)(ps2_dev *); @@ -63,6 +64,6 @@ status_t ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_coun void ps2_dev_publish(ps2_dev *dev); void ps2_dev_unpublish(ps2_dev *dev); -int32 ps2_dev_handle_int(ps2_dev *dev, uint8 data); +int32 ps2_dev_handle_int(ps2_dev *dev); #endif diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c index 865fd19d0d..4cac1001c9 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c @@ -108,14 +108,9 @@ keyboard_handle_int(ps2_dev *dev) TRACE(("scancode: %x\n", scancode)); - // For now, F12 enters the kernel debugger - // ToDo: remove me later :-) - if (scancode == 88) - panic("keyboard requested halt.\n"); - if (scancode & 0x80) { keyInfo.is_keydown = false; - scancode -= 0x80; + scancode &= 0x7f; } else keyInfo.is_keydown = true; diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_mouse.c b/src/add-ons/kernel/bus_managers/ps2/ps2_mouse.c index 563b26f018..a40037c956 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_mouse.c +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_mouse.c @@ -222,8 +222,8 @@ static int32 mouse_handle_int(ps2_dev *dev) { mouse_cookie *cookie = dev->cookie; - uint8 data = dev->history[0].data; - + const uint8 data = dev->history[0].data; + if (cookie->packet_index == 0 && !(data & 8)) { TRACE(("bad mouse data, trying resync\n")); return B_HANDLED_INTERRUPT;