* 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
#define _KB_MOUSE_DRIVER_H
#include <SupportDefs.h>
#include <Drivers.h>
#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,

View File

@ -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

View File

@ -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 <marcus@overhagen.de>
*/
/*! PS/2 keyboard device driver */
#include <string.h>
#include <new>
#include <debug.h>
#include <debugger_keymaps.h>
#include <lock.h>
#include <util/AutoLock.h>
#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;