From 897ca37d5225d71cfd750dc4c74c7977b13005c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 14 Apr 2010 12:30:23 +0000 Subject: [PATCH] * Introduced a new debugger access to the keyboard drivers, and implemented that in the PS/2 driver for now. The basic idea is to allow everyone to open the device, but only allow one key reader (as usual). However, once someone registers itself as a debugger, the original reader is blocked, and the debugger can read the key presses instead. * Renamed ps2_keyboard.c to .cpp. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36256 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/input/kb_mouse_driver.h | 5 +- src/add-ons/kernel/bus_managers/ps2/Jamfile | 4 +- .../ps2/{ps2_keyboard.c => ps2_keyboard.cpp} | 167 ++++++++++++------ 3 files changed, 115 insertions(+), 61 deletions(-) rename src/add-ons/kernel/bus_managers/ps2/{ps2_keyboard.c => ps2_keyboard.cpp} (75%) diff --git a/headers/private/input/kb_mouse_driver.h b/headers/private/input/kb_mouse_driver.h index f7ef6dd8b3..f059513f61 100644 --- a/headers/private/input/kb_mouse_driver.h +++ b/headers/private/input/kb_mouse_driver.h @@ -4,9 +4,11 @@ #ifndef _KB_MOUSE_DRIVER_H #define _KB_MOUSE_DRIVER_H + #include #include + #ifdef __cplusplus extern "C" { #endif @@ -50,7 +52,8 @@ enum { KB_RESERVED_1, KB_CANCEL_CONTROL_ALT_DEL, KB_DELAY_CONTROL_ALT_DEL, - + KB_SET_DEBUG_READER, + MS_READ = B_DEVICE_OP_CODES_END + 100, MS_NUM_EVENTS, MS_GET_ACCEL, diff --git a/src/add-ons/kernel/bus_managers/ps2/Jamfile b/src/add-ons/kernel/bus_managers/ps2/Jamfile index b8db612e17..7063057ccf 100644 --- a/src/add-ons/kernel/bus_managers/ps2/Jamfile +++ b/src/add-ons/kernel/bus_managers/ps2/Jamfile @@ -1,13 +1,13 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers ps2 ; UsePrivateHeaders input ; -UsePrivateHeaders kernel ; +UsePrivateKernelHeaders ; KernelAddon ps2 : packet_buffer.cpp ps2_common.c ps2_dev.c - ps2_keyboard.c + ps2_keyboard.cpp ps2_module.c ps2_standard_mouse.c ps2_synaptics.c diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp similarity index 75% rename from src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c rename to src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp index 75c92fcaab..f39e0a7f57 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.c +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Haiku, Inc. + * Copyright 2004-2010 Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors (in chronological order): @@ -8,13 +8,18 @@ * Marcus Overhagen */ + /*! PS/2 keyboard device driver */ #include +#include + #include #include +#include +#include #include "ps2_service.h" #include "kb_mouse_driver.h" @@ -39,7 +44,16 @@ enum { }; -static int32 sKeyboardOpenMask; +struct keyboard_cookie { + bool is_reader; + bool is_debugger; +}; + + +static mutex sInitializeLock = MUTEX_INITIALIZER("keyboard init"); +static int32 sKeyboardOpenCount = 0; +static bool sHasKeyboardReader = false; +static bool sHasDebugReader = false; static sem_id sKeyboardSem; static struct packet_buffer *sKeyBuffer; static bool sIsExtended = false; @@ -112,7 +126,7 @@ keyboard_handle_int(ps2_dev *dev) at_kbd_io keyInfo; uint8 scancode = dev->history[0].data; - if (atomic_and(&sKeyboardOpenMask, 1) == 0) + if (atomic_get(&sKeyboardOpenCount) == 0) return B_HANDLED_INTERRUPT; // TODO: Handle braindead "pause" key special case @@ -154,7 +168,6 @@ keyboard_handle_int(ps2_dev *dev) } else if (emergencyKeyStatus > EMERGENCY_SYS_REQ && debug_emergency_key_pressed(kUnshiftedKeymap[scancode])) { static const int kKeys[] = {LEFT_ALT_KEY, RIGHT_ALT_KEY, SYS_REQ_KEY}; - int i; // we probably have lost some keys, so reset our key states emergencyKeyStatus = 0; @@ -162,7 +175,7 @@ keyboard_handle_int(ps2_dev *dev) // send key ups for alt-sysreq keyInfo.timestamp = system_time(); keyInfo.is_keydown = false; - for (i = 0; i < sizeof(kKeys) / sizeof(kKeys[0]); i++) { + for (size_t i = 0; i < sizeof(kKeys) / sizeof(kKeys[0]); i++) { keyInfo.scancode = kKeys[i]; if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo, sizeof(keyInfo)) != 0) @@ -190,19 +203,28 @@ keyboard_handle_int(ps2_dev *dev) static status_t -read_keyboard_packet(at_kbd_io *packet) +read_keyboard_packet(at_kbd_io *packet, bool isDebugger) { status_t status; TRACE("ps2: read_keyboard_packet: enter\n"); - status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0); - if (status < B_OK) - return status; + while (true) { + status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0); + if (status != B_OK) + return status; - if (!ps2_device[PS2_DEVICE_KEYB].active) { - TRACE("ps2: read_keyboard_packet, Error device no longer active\n"); - return B_ERROR; + if (!ps2_device[PS2_DEVICE_KEYB].active) { + TRACE("ps2: read_keyboard_packet, Error device no longer active\n"); + return B_ERROR; + } + + if (isDebugger || !sHasDebugReader) + break; + + // Give the debugger a chance to read this packet + release_sem(sKeyboardSem); + snooze(100000); } if (packet_buffer_read(sKeyBuffer, (uint8 *)packet, sizeof(*packet)) == 0) { @@ -223,10 +245,11 @@ ps2_keyboard_disconnect(ps2_dev *dev) { // the keyboard might not be opened at this point INFO("ps2: ps2_keyboard_disconnect %s\n", dev->name); - if (sKeyboardOpenMask) + if (atomic_get(&sKeyboardOpenCount) != 0) release_sem(sKeyboardSem); } + // #pragma mark - @@ -275,64 +298,73 @@ probe_keyboard(void) static status_t keyboard_open(const char *name, uint32 flags, void **_cookie) { - status_t status; - TRACE("ps2: keyboard_open %s\n", name); - if (atomic_or(&sKeyboardOpenMask, 1) != 0) - return B_BUSY; + keyboard_cookie* cookie = new(std::nothrow) keyboard_cookie(); + if (cookie == NULL) + return B_NO_MEMORY; - status = probe_keyboard(); - if (status != B_OK) { - INFO("ps2: keyboard probing failed\n"); - ps2_service_notify_device_removed(&ps2_device[PS2_DEVICE_KEYB]); - goto err1; + cookie->is_reader = false; + cookie->is_debugger = false; + + MutexLocker locker(sInitializeLock); + + if (atomic_get(&sKeyboardOpenCount) == 0) { + status_t status = probe_keyboard(); + if (status != B_OK) { + INFO("ps2: keyboard probing failed\n"); + ps2_service_notify_device_removed(&ps2_device[PS2_DEVICE_KEYB]); + delete cookie; + return status; + } + + INFO("ps2: keyboard found\n"); + + sKeyboardSem = create_sem(0, "keyboard_sem"); + if (sKeyboardSem < 0) { + delete cookie; + return sKeyboardSem; + } + + sKeyBuffer = create_packet_buffer(KEY_BUFFER_SIZE * sizeof(at_kbd_io)); + if (sKeyBuffer == NULL) { + delete_sem(sKeyboardSem); + delete cookie; + return B_NO_MEMORY; + } + + ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect; + ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int; + + atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED); } - INFO("ps2: keyboard found\n"); - - sKeyboardSem = create_sem(0, "keyboard_sem"); - if (sKeyboardSem < 0) { - status = sKeyboardSem; - goto err1; - } - - sKeyBuffer = create_packet_buffer(KEY_BUFFER_SIZE * sizeof(at_kbd_io)); - if (sKeyBuffer == NULL) { - status = B_NO_MEMORY; - goto err2; - } - - *_cookie = NULL; - ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect; - ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int; - - atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED); + atomic_add(&sKeyboardOpenCount, 1); + *_cookie = cookie; TRACE("ps2: keyboard_open %s success\n", name); return B_OK; - -err2: - delete_sem(sKeyboardSem); -err1: - atomic_and(&sKeyboardOpenMask, 0); - - TRACE("ps2: keyboard_open %s failed\n", name); - return status; } static status_t -keyboard_close(void *cookie) +keyboard_close(void *_cookie) { + keyboard_cookie *cookie = (keyboard_cookie *)_cookie; + TRACE("ps2: keyboard_close enter\n"); - delete_packet_buffer(sKeyBuffer); - delete_sem(sKeyboardSem); + if (atomic_add(&sKeyboardOpenCount, -1) == 1) { + delete_packet_buffer(sKeyBuffer); + delete_sem(sKeyboardSem); - atomic_and(&ps2_device[PS2_DEVICE_KEYB].flags, ~PS2_FLAG_ENABLED); + atomic_and(&ps2_device[PS2_DEVICE_KEYB].flags, ~PS2_FLAG_ENABLED); - atomic_and(&sKeyboardOpenMask, 0); + if (cookie->is_reader) + sHasKeyboardReader = false; + if (cookie->is_debugger) + sHasDebugReader = false; + } TRACE("ps2: keyboard_close done\n"); return B_OK; @@ -342,6 +374,7 @@ keyboard_close(void *cookie) static status_t keyboard_freecookie(void *cookie) { + delete (keyboard_cookie*)cookie; return B_OK; } @@ -365,16 +398,26 @@ keyboard_write(void *cookie, off_t pos, const void *buffer, size_t *_length) static status_t -keyboard_ioctl(void *cookie, uint32 op, void *buffer, size_t length) +keyboard_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) { + keyboard_cookie *cookie = (keyboard_cookie *)_cookie; + switch (op) { case KB_READ: { + if (!sHasKeyboardReader && !cookie->is_debugger) { + cookie->is_reader = true; + sHasKeyboardReader = true; + } else if (!cookie->is_debugger && !cookie->is_reader) + return B_BUSY; + at_kbd_io packet; - status_t status; - TRACE("ps2: ioctl KB_READ\n"); - if ((status = read_keyboard_packet(&packet)) < B_OK) + status_t status = read_keyboard_packet(&packet, + cookie->is_debugger); + TRACE("ps2: ioctl KB_READ: %s\n", strerror(status)); + if (status != B_OK) return status; + return user_memcpy(buffer, &packet, sizeof(packet)); } @@ -453,6 +496,14 @@ keyboard_ioctl(void *cookie, uint32 op, void *buffer, size_t length) INFO("ps2: ioctl 0x%lx not implemented yet, returning B_OK\n", op); return B_OK; + case KB_SET_DEBUG_READER: + if (sHasDebugReader) + return B_BUSY; + + cookie->is_debugger = true; + sHasDebugReader = true; + return B_OK; + default: INFO("ps2: invalid ioctl 0x%lx\n", op); return EINVAL;