* 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:
parent
3856867b03
commit
897ca37d52
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
Loading…
Reference in New Issue
Block a user