* 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
This commit is contained in:
Axel Dörfler 2010-04-14 12:30:23 +00:00
parent 3856867b03
commit 897ca37d52
3 changed files with 115 additions and 61 deletions

View File

@ -4,9 +4,11 @@
#ifndef _KB_MOUSE_DRIVER_H #ifndef _KB_MOUSE_DRIVER_H
#define _KB_MOUSE_DRIVER_H #define _KB_MOUSE_DRIVER_H
#include <SupportDefs.h> #include <SupportDefs.h>
#include <Drivers.h> #include <Drivers.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -50,6 +52,7 @@ enum {
KB_RESERVED_1, KB_RESERVED_1,
KB_CANCEL_CONTROL_ALT_DEL, KB_CANCEL_CONTROL_ALT_DEL,
KB_DELAY_CONTROL_ALT_DEL, KB_DELAY_CONTROL_ALT_DEL,
KB_SET_DEBUG_READER,
MS_READ = B_DEVICE_OP_CODES_END + 100, MS_READ = B_DEVICE_OP_CODES_END + 100,
MS_NUM_EVENTS, MS_NUM_EVENTS,

View File

@ -1,13 +1,13 @@
SubDir HAIKU_TOP src add-ons kernel bus_managers ps2 ; SubDir HAIKU_TOP src add-ons kernel bus_managers ps2 ;
UsePrivateHeaders input ; UsePrivateHeaders input ;
UsePrivateHeaders kernel ; UsePrivateKernelHeaders ;
KernelAddon ps2 : KernelAddon ps2 :
packet_buffer.cpp packet_buffer.cpp
ps2_common.c ps2_common.c
ps2_dev.c ps2_dev.c
ps2_keyboard.c ps2_keyboard.cpp
ps2_module.c ps2_module.c
ps2_standard_mouse.c ps2_standard_mouse.c
ps2_synaptics.c ps2_synaptics.c

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2009 Haiku, Inc. * Copyright 2004-2010 Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors (in chronological order): * Authors (in chronological order):
@ -8,13 +8,18 @@
* Marcus Overhagen <marcus@overhagen.de> * Marcus Overhagen <marcus@overhagen.de>
*/ */
/*! PS/2 keyboard device driver */ /*! PS/2 keyboard device driver */
#include <string.h> #include <string.h>
#include <new>
#include <debug.h> #include <debug.h>
#include <debugger_keymaps.h> #include <debugger_keymaps.h>
#include <lock.h>
#include <util/AutoLock.h>
#include "ps2_service.h" #include "ps2_service.h"
#include "kb_mouse_driver.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 sem_id sKeyboardSem;
static struct packet_buffer *sKeyBuffer; static struct packet_buffer *sKeyBuffer;
static bool sIsExtended = false; static bool sIsExtended = false;
@ -112,7 +126,7 @@ keyboard_handle_int(ps2_dev *dev)
at_kbd_io keyInfo; at_kbd_io keyInfo;
uint8 scancode = dev->history[0].data; uint8 scancode = dev->history[0].data;
if (atomic_and(&sKeyboardOpenMask, 1) == 0) if (atomic_get(&sKeyboardOpenCount) == 0)
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
// TODO: Handle braindead "pause" key special case // TODO: Handle braindead "pause" key special case
@ -154,7 +168,6 @@ keyboard_handle_int(ps2_dev *dev)
} else if (emergencyKeyStatus > EMERGENCY_SYS_REQ } else if (emergencyKeyStatus > EMERGENCY_SYS_REQ
&& debug_emergency_key_pressed(kUnshiftedKeymap[scancode])) { && debug_emergency_key_pressed(kUnshiftedKeymap[scancode])) {
static const int kKeys[] = {LEFT_ALT_KEY, RIGHT_ALT_KEY, SYS_REQ_KEY}; 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 // we probably have lost some keys, so reset our key states
emergencyKeyStatus = 0; emergencyKeyStatus = 0;
@ -162,7 +175,7 @@ keyboard_handle_int(ps2_dev *dev)
// send key ups for alt-sysreq // send key ups for alt-sysreq
keyInfo.timestamp = system_time(); keyInfo.timestamp = system_time();
keyInfo.is_keydown = false; 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]; keyInfo.scancode = kKeys[i];
if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo, if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo,
sizeof(keyInfo)) != 0) sizeof(keyInfo)) != 0)
@ -190,14 +203,15 @@ keyboard_handle_int(ps2_dev *dev)
static status_t static status_t
read_keyboard_packet(at_kbd_io *packet) read_keyboard_packet(at_kbd_io *packet, bool isDebugger)
{ {
status_t status; status_t status;
TRACE("ps2: read_keyboard_packet: enter\n"); TRACE("ps2: read_keyboard_packet: enter\n");
while (true) {
status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0); status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0);
if (status < B_OK) if (status != B_OK)
return status; return status;
if (!ps2_device[PS2_DEVICE_KEYB].active) { if (!ps2_device[PS2_DEVICE_KEYB].active) {
@ -205,6 +219,14 @@ read_keyboard_packet(at_kbd_io *packet)
return B_ERROR; 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) { if (packet_buffer_read(sKeyBuffer, (uint8 *)packet, sizeof(*packet)) == 0) {
TRACE("ps2: read_keyboard_packet, Error reading packet: %s\n", TRACE("ps2: read_keyboard_packet, Error reading packet: %s\n",
strerror(status)); strerror(status));
@ -223,10 +245,11 @@ ps2_keyboard_disconnect(ps2_dev *dev)
{ {
// the keyboard might not be opened at this point // the keyboard might not be opened at this point
INFO("ps2: ps2_keyboard_disconnect %s\n", dev->name); INFO("ps2: ps2_keyboard_disconnect %s\n", dev->name);
if (sKeyboardOpenMask) if (atomic_get(&sKeyboardOpenCount) != 0)
release_sem(sKeyboardSem); release_sem(sKeyboardSem);
} }
// #pragma mark - // #pragma mark -
@ -275,64 +298,73 @@ probe_keyboard(void)
static status_t static status_t
keyboard_open(const char *name, uint32 flags, void **_cookie) keyboard_open(const char *name, uint32 flags, void **_cookie)
{ {
status_t status;
TRACE("ps2: keyboard_open %s\n", name); TRACE("ps2: keyboard_open %s\n", name);
if (atomic_or(&sKeyboardOpenMask, 1) != 0) keyboard_cookie* cookie = new(std::nothrow) keyboard_cookie();
return B_BUSY; if (cookie == NULL)
return B_NO_MEMORY;
status = probe_keyboard(); 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) { if (status != B_OK) {
INFO("ps2: keyboard probing failed\n"); INFO("ps2: keyboard probing failed\n");
ps2_service_notify_device_removed(&ps2_device[PS2_DEVICE_KEYB]); ps2_service_notify_device_removed(&ps2_device[PS2_DEVICE_KEYB]);
goto err1; delete cookie;
return status;
} }
INFO("ps2: keyboard found\n"); INFO("ps2: keyboard found\n");
sKeyboardSem = create_sem(0, "keyboard_sem"); sKeyboardSem = create_sem(0, "keyboard_sem");
if (sKeyboardSem < 0) { if (sKeyboardSem < 0) {
status = sKeyboardSem; delete cookie;
goto err1; return sKeyboardSem;
} }
sKeyBuffer = create_packet_buffer(KEY_BUFFER_SIZE * sizeof(at_kbd_io)); sKeyBuffer = create_packet_buffer(KEY_BUFFER_SIZE * sizeof(at_kbd_io));
if (sKeyBuffer == NULL) { if (sKeyBuffer == NULL) {
status = B_NO_MEMORY; delete_sem(sKeyboardSem);
goto err2; delete cookie;
return B_NO_MEMORY;
} }
*_cookie = NULL;
ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect; ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect;
ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int; ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int;
atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED); 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); TRACE("ps2: keyboard_open %s success\n", name);
return B_OK; 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 static status_t
keyboard_close(void *cookie) keyboard_close(void *_cookie)
{ {
keyboard_cookie *cookie = (keyboard_cookie *)_cookie;
TRACE("ps2: keyboard_close enter\n"); TRACE("ps2: keyboard_close enter\n");
if (atomic_add(&sKeyboardOpenCount, -1) == 1) {
delete_packet_buffer(sKeyBuffer); delete_packet_buffer(sKeyBuffer);
delete_sem(sKeyboardSem); 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"); TRACE("ps2: keyboard_close done\n");
return B_OK; return B_OK;
@ -342,6 +374,7 @@ keyboard_close(void *cookie)
static status_t static status_t
keyboard_freecookie(void *cookie) keyboard_freecookie(void *cookie)
{ {
delete (keyboard_cookie*)cookie;
return B_OK; return B_OK;
} }
@ -365,16 +398,26 @@ keyboard_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
static status_t 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) { switch (op) {
case KB_READ: 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; at_kbd_io packet;
status_t status; status_t status = read_keyboard_packet(&packet,
TRACE("ps2: ioctl KB_READ\n"); cookie->is_debugger);
if ((status = read_keyboard_packet(&packet)) < B_OK) TRACE("ps2: ioctl KB_READ: %s\n", strerror(status));
if (status != B_OK)
return status; return status;
return user_memcpy(buffer, &packet, sizeof(packet)); 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); INFO("ps2: ioctl 0x%lx not implemented yet, returning B_OK\n", op);
return B_OK; return B_OK;
case KB_SET_DEBUG_READER:
if (sHasDebugReader)
return B_BUSY;
cookie->is_debugger = true;
sHasDebugReader = true;
return B_OK;
default: default:
INFO("ps2: invalid ioctl 0x%lx\n", op); INFO("ps2: invalid ioctl 0x%lx\n", op);
return EINVAL; return EINVAL;