combined mouse and keyboard interrupt handler, work in progress...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15931 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,29 +1,13 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers input ps2_hid ;
|
SubDir HAIKU_TOP src add-ons kernel drivers input ps2_hid_new ;
|
||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
UsePrivateHeaders input ;
|
UsePrivateHeaders input ;
|
||||||
UsePrivateHeaders kernel ;
|
UsePrivateHeaders kernel ;
|
||||||
|
|
||||||
if ! $(HAIKU_COMPATIBLE) {
|
KernelAddon ps2_hid_new : kernel drivers bin :
|
||||||
SubDirCcFlags -DCOMPILE_FOR_R5 ;
|
|
||||||
|
|
||||||
KernelAddon ps2_hid : kernel drivers bin :
|
|
||||||
common.c
|
|
||||||
keyboard.c
|
|
||||||
mouse.c
|
|
||||||
;
|
|
||||||
} else {
|
|
||||||
KernelAddon ps2_hid : kernel drivers bin :
|
|
||||||
common.c
|
common.c
|
||||||
keyboard.c
|
keyboard.c
|
||||||
mouse.c
|
mouse.c
|
||||||
packet_buffer.cpp
|
packet_buffer.cpp
|
||||||
;
|
;
|
||||||
}
|
|
||||||
|
|
||||||
Package haiku-inputkit-cvs :
|
|
||||||
ps2_hid :
|
|
||||||
boot home config add-ons kernel drivers bin ;
|
|
||||||
|
|
||||||
PackageDriverSymLink haiku-inputkit-cvs : input ps2_hid ;
|
|
||||||
|
|||||||
@@ -62,6 +62,35 @@ static uint8 *sResultBuffer;
|
|||||||
static int32 sResultBytes;
|
static int32 sResultBytes;
|
||||||
|
|
||||||
|
|
||||||
|
inline uint8
|
||||||
|
ps2_read_ctrl()
|
||||||
|
{
|
||||||
|
return gIsa->read_io_8(PS2_PORT_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint8
|
||||||
|
ps2_read_data()
|
||||||
|
{
|
||||||
|
return gIsa->read_io_8(PS2_PORT_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ps2_write_ctrl(uint8 ctrl)
|
||||||
|
{
|
||||||
|
gIsa->write_io_8(PS2_PORT_CTRL, ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ps2_write_data(uint8 data)
|
||||||
|
{
|
||||||
|
gIsa->write_io_8(PS2_PORT_DATA, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Wait until the specified status bits are cleared or set, depending on the
|
/** Wait until the specified status bits are cleared or set, depending on the
|
||||||
* second parameter.
|
* second parameter.
|
||||||
* This currently busy waits, but should nonetheless be avoided in interrupt
|
* This currently busy waits, but should nonetheless be avoided in interrupt
|
||||||
@@ -248,42 +277,27 @@ ps2_wait_for_result(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static int32
|
||||||
ps2_common_uninitialize(void)
|
ps2_interrupt(void* cookie)
|
||||||
{
|
{
|
||||||
// do we still need the resources?
|
uint8 ctrl;
|
||||||
if (atomic_add(&sInitialized, -1) > 1)
|
uint8 data;
|
||||||
return;
|
|
||||||
|
ctrl = ps2_read_ctrl();
|
||||||
|
if (!(ctrl & PS2_STATUS_OUTPUT_BUFFER_FULL))
|
||||||
|
return B_UNHANDLED_INTERRUPT;
|
||||||
|
|
||||||
|
data = ps2_read_data();
|
||||||
|
|
||||||
delete_sem(sResultSemaphore);
|
TRACE(("ps2_interrupt: ctrl 0x%02x, data 0x%02x (%s)\n", ctrl, data, (ctrl & PS2_STATUS_MOUSE_DATA) ? "mouse" : "keyb"));
|
||||||
delete_sem(sResultOwnerSemaphore);
|
|
||||||
|
if (ctrl & PS2_STATUS_MOUSE_DATA)
|
||||||
|
return mouse_handle_int(data);
|
||||||
|
else
|
||||||
|
return keyboard_handle_int(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ps2_common_initialize(void)
|
|
||||||
{
|
|
||||||
if (atomic_add(&sInitialized, 1) > 0) {
|
|
||||||
// we're already initialized
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
sResultSemaphore = create_sem(0, "ps/2 result");
|
|
||||||
if (sResultSemaphore < B_OK)
|
|
||||||
return sResultSemaphore;
|
|
||||||
|
|
||||||
sResultOwnerSemaphore = create_sem(1, "ps/2 result owner");
|
|
||||||
if (sResultOwnerSemaphore < B_OK) {
|
|
||||||
delete_sem(sResultSemaphore);
|
|
||||||
return sResultOwnerSemaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
sResultBytes = 0;
|
|
||||||
sResultBuffer = NULL;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
// driver interface
|
// driver interface
|
||||||
@@ -302,10 +316,8 @@ publish_devices(void)
|
|||||||
static char *kDevices[3];
|
static char *kDevices[3];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
if (sMouseDetected)
|
|
||||||
kDevices[index++] = DEVICE_MOUSE_NAME;
|
kDevices[index++] = DEVICE_MOUSE_NAME;
|
||||||
|
|
||||||
if (sKeyboardDetected)
|
|
||||||
kDevices[index++] = DEVICE_KEYBOARD_NAME;
|
kDevices[index++] = DEVICE_KEYBOARD_NAME;
|
||||||
|
|
||||||
kDevices[index++] = NULL;
|
kDevices[index++] = NULL;
|
||||||
@@ -332,45 +344,46 @@ init_driver(void)
|
|||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
status = get_module(B_ISA_MODULE_NAME, (module_info **)&gIsa);
|
status = get_module(B_ISA_MODULE_NAME, (module_info **)&gIsa);
|
||||||
if (status < B_OK) {
|
if (status < B_OK)
|
||||||
TRACE(("Failed getting isa module: %s\n", strerror(status)));
|
goto err_1;
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to probe for the mouse first, as this can hang the keyboard if no
|
|
||||||
// mouse is found.
|
|
||||||
// Probing the mouse first and initializing the keyboard later appearantly
|
|
||||||
// clears the keyboard stall.
|
|
||||||
|
|
||||||
if (probe_mouse(NULL) == B_OK)
|
|
||||||
sMouseDetected = true;
|
|
||||||
else
|
|
||||||
dprintf("ps2_hid: no mouse detected!\n");
|
|
||||||
|
|
||||||
if (probe_keyboard() == B_OK)
|
|
||||||
sKeyboardDetected = true;
|
|
||||||
else
|
|
||||||
dprintf("ps2_hid: no keyboard detected!\n");
|
|
||||||
|
|
||||||
// If there is no keyboard or mouse, we don't need to publish ourselves
|
|
||||||
if (!sKeyboardDetected && !sMouseDetected) {
|
|
||||||
put_module(B_ISA_MODULE_NAME);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A semaphore to synchronize open keyboard and mouse devices
|
|
||||||
|
|
||||||
gDeviceOpenSemaphore = create_sem(1, "ps/2 open");
|
gDeviceOpenSemaphore = create_sem(1, "ps/2 open");
|
||||||
if (gDeviceOpenSemaphore < B_OK)
|
if (gDeviceOpenSemaphore < B_OK)
|
||||||
return gDeviceOpenSemaphore;
|
goto err_2;
|
||||||
|
|
||||||
return get_command_byte(&sCommandByte);
|
status = install_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL, 0);
|
||||||
|
if (status)
|
||||||
|
goto err_3;
|
||||||
|
|
||||||
|
status = install_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL, 0);
|
||||||
|
if (status)
|
||||||
|
goto err_4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//goto err_5;
|
||||||
|
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err_5:
|
||||||
|
remove_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL);
|
||||||
|
err_4:
|
||||||
|
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL);
|
||||||
|
err_3:
|
||||||
|
delete_sem(gDeviceOpenSemaphore);
|
||||||
|
err_2:
|
||||||
|
put_module(B_ISA_MODULE_NAME);
|
||||||
|
err_1:
|
||||||
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
uninit_driver(void)
|
uninit_driver(void)
|
||||||
{
|
{
|
||||||
|
remove_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL);
|
||||||
|
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL);
|
||||||
delete_sem(gDeviceOpenSemaphore);
|
delete_sem(gDeviceOpenSemaphore);
|
||||||
put_module(B_ISA_MODULE_NAME);
|
put_module(B_ISA_MODULE_NAME);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ extern status_t ps2_common_initialize(void);
|
|||||||
extern status_t probe_keyboard(void);
|
extern status_t probe_keyboard(void);
|
||||||
extern status_t probe_mouse(size_t *probed_packet_size);
|
extern status_t probe_mouse(size_t *probed_packet_size);
|
||||||
|
|
||||||
|
extern int32 mouse_handle_int(uint8 data);
|
||||||
|
extern int32 keyboard_handle_int(uint8 data);
|
||||||
|
|
||||||
|
|
||||||
extern status_t keyboard_open(const char *name, uint32 flags, void **cookie);
|
extern status_t keyboard_open(const char *name, uint32 flags, void **cookie);
|
||||||
extern status_t keyboard_close(void *cookie);
|
extern status_t keyboard_close(void *cookie);
|
||||||
extern status_t keyboard_freecookie(void *cookie);
|
extern status_t keyboard_freecookie(void *cookie);
|
||||||
|
|||||||
@@ -146,31 +146,24 @@ set_leds(led_info *ledInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
int32 keyboard_handle_int(uint8 data)
|
||||||
handle_keyboard_interrupt(void *data)
|
|
||||||
{
|
{
|
||||||
uint8 read = gIsa->read_io_8(PS2_PORT_CTRL);
|
if (atomic_and(&sKeyboardOpenMask, 1) == 0)
|
||||||
TRACE(("handle_keyboard_interrupt: read = 0x%x\n", read));
|
return B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
|
|
||||||
if (read & PS2_STATUS_OUTPUT_BUFFER_FULL) {
|
|
||||||
at_kbd_io keyInfo;
|
at_kbd_io keyInfo;
|
||||||
uint8 scancode;
|
uint8 scancode;
|
||||||
|
|
||||||
read = gIsa->read_io_8(PS2_PORT_DATA);
|
|
||||||
|
|
||||||
// someone else might wait for a result from the keyboard controller
|
|
||||||
if (ps2_handle_result(read))
|
|
||||||
return B_INVOKE_SCHEDULER;
|
|
||||||
|
|
||||||
// TODO: Handle braindead "pause" key special case
|
// TODO: Handle braindead "pause" key special case
|
||||||
|
|
||||||
if (read == EXTENDED_KEY) {
|
if (data == EXTENDED_KEY) {
|
||||||
sIsExtended = true;
|
sIsExtended = true;
|
||||||
TRACE(("Extended key\n"));
|
TRACE(("Extended key\n"));
|
||||||
return B_HANDLED_INTERRUPT;
|
return B_HANDLED_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
scancode = read;
|
scancode = data;
|
||||||
|
|
||||||
TRACE(("scancode: %x\n", scancode));
|
TRACE(("scancode: %x\n", scancode));
|
||||||
|
|
||||||
@@ -200,11 +193,6 @@ handle_keyboard_interrupt(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
|
release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
} else {
|
|
||||||
// ToDo: the buffer is not yet available, we should come back soon...
|
|
||||||
// (depending on how often we see the message below... :-)
|
|
||||||
dprintf("ps2_hid: keyboard: buffer not available!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_INVOKE_SCHEDULER;
|
return B_INVOKE_SCHEDULER;
|
||||||
}
|
}
|
||||||
@@ -309,10 +297,6 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
|
|
||||||
acquire_sem(gDeviceOpenSemaphore);
|
acquire_sem(gDeviceOpenSemaphore);
|
||||||
|
|
||||||
status = ps2_common_initialize();
|
|
||||||
if (status != B_OK)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
sKeyboardSem = create_sem(0, "keyboard_sem");
|
sKeyboardSem = create_sem(0, "keyboard_sem");
|
||||||
if (sKeyboardSem < 0) {
|
if (sKeyboardSem < 0) {
|
||||||
status = sKeyboardSem;
|
status = sKeyboardSem;
|
||||||
@@ -337,12 +321,6 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
goto err4;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = install_io_interrupt_handler(INT_PS2_KEYBOARD,
|
|
||||||
&handle_keyboard_interrupt, NULL, 0);
|
|
||||||
if (status < B_OK)
|
|
||||||
goto err4;
|
|
||||||
|
|
||||||
sInterruptHandlerInstalled = true;
|
|
||||||
release_sem(gDeviceOpenSemaphore);
|
release_sem(gDeviceOpenSemaphore);
|
||||||
|
|
||||||
*_cookie = NULL;
|
*_cookie = NULL;
|
||||||
@@ -355,7 +333,6 @@ err4:
|
|||||||
err3:
|
err3:
|
||||||
delete_sem(sKeyboardSem);
|
delete_sem(sKeyboardSem);
|
||||||
err2:
|
err2:
|
||||||
ps2_common_uninitialize();
|
|
||||||
err1:
|
err1:
|
||||||
atomic_and(&sKeyboardOpenMask, 0);
|
atomic_and(&sKeyboardOpenMask, 0);
|
||||||
release_sem(gDeviceOpenSemaphore);
|
release_sem(gDeviceOpenSemaphore);
|
||||||
@@ -369,13 +346,10 @@ keyboard_close(void *cookie)
|
|||||||
{
|
{
|
||||||
TRACE(("keyboard_close()\n"));
|
TRACE(("keyboard_close()\n"));
|
||||||
|
|
||||||
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &handle_keyboard_interrupt, NULL);
|
|
||||||
sInterruptHandlerInstalled = false;
|
|
||||||
|
|
||||||
delete_packet_buffer(sKeyBuffer);
|
delete_packet_buffer(sKeyBuffer);
|
||||||
delete_sem(sKeyboardSem);
|
delete_sem(sKeyboardSem);
|
||||||
|
|
||||||
ps2_common_uninitialize();
|
|
||||||
atomic_and(&sKeyboardOpenMask, 0);
|
atomic_and(&sKeyboardOpenMask, 0);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -249,17 +249,10 @@ set_mouse_enabled(bool enable)
|
|||||||
* calls to the handler, each holds a different byte on the data port.
|
* calls to the handler, each holds a different byte on the data port.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int32
|
int32 mouse_handle_int(uint8 data)
|
||||||
handle_mouse_interrupt(void* cookie)
|
|
||||||
{
|
{
|
||||||
uint8 data = gIsa->read_io_8(PS2_PORT_CTRL);
|
if (atomic_and(&sMouseOpenMask, 1) == 0)
|
||||||
if (!(data & PS2_STATUS_OUTPUT_BUFFER_FULL)) {
|
return B_HANDLED_INTERRUPT;
|
||||||
TRACE(("no ps2 mouse data available\n"));
|
|
||||||
return B_UNHANDLED_INTERRUPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = gIsa->read_io_8(PS2_PORT_DATA);
|
|
||||||
TRACE(("mouse interrupt: %d byte: 0x%02x\n", sPacketIndex, data));
|
|
||||||
|
|
||||||
if (sPacketIndex == 0 && !(data & 8)) {
|
if (sPacketIndex == 0 && !(data & 8)) {
|
||||||
TRACE(("bad mouse data, trying resync\n"));
|
TRACE(("bad mouse data, trying resync\n"));
|
||||||
|
|||||||
Reference in New Issue
Block a user