Added "new" keyboard driver, which implements the "correct" keyboard api. Not tested or anything. Not yet added to the build as I even did some last minute changes.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9070 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2004-09-27 08:44:02 +00:00
parent d4c31885aa
commit 1ce76bfd47
1 changed files with 260 additions and 0 deletions

View File

@ -0,0 +1,260 @@
/*
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <KernelExport.h>
#include <Drivers.h>
#include <OS.h>
#include <ISA.h>
#include <cbuf.h>
#include <string.h>
#include <lock.h>
#include <kb_mouse_driver.h>
#define DEVICE_NAME "input/keyboard/at/0"
#define TRACE_KEYBOARD 0
#if TRACE_KEYBOARD
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
#define LED_SCROLL 1
#define LED_NUM 2
#define LED_CAPS 4
int32 api_version = B_CUR_DRIVER_API_VERSION;
static sem_id keyboard_sem;
static mutex keyboard_read_mutex;
static cbuf *keyboard_buf;
static isa_module_info *sIsa;
static at_kbd_io sKeyInfo;
static int32 sOpenMask;
static void
wait_for_output(void)
{
while (sIsa->read_io_8(0x64) & 0x2)
;
}
static void
set_leds(led_info *ledInfo)
{
int leds = 0;
if (ledInfo->scroll_lock)
leds |= LED_SCROLL;
if (ledInfo->num_lock)
leds |= LED_NUM;
if (ledInfo->caps_lock)
leds |= LED_CAPS;
wait_for_output();
sIsa->write_io_8(0x60, 0xed);
wait_for_output();
sIsa->write_io_8(0x60, leds);
}
static int32
handle_keyboard_interrupt(void *data)
{
unsigned char key;
key = sIsa->read_io_8(0x60);
TRACE(("handle_keyboard_interrupt: key = 0x%x\n", key));
if (key == 0xE0) {
// Extended key. Handle it in some way
return B_HANDLED_INTERRUPT;
}
if (key == 0xF0) {
sKeyInfo.is_keydown = false;
return B_HANDLED_INTERRUPT;
}
sKeyInfo.timestamp = system_time();
sKeyInfo.scancode = key;
// TODO: Check return value
cbuf_memcpy_to_chain(keyboard_buf, 0, &sKeyInfo, sizeof(sKeyInfo));
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
// Reset this so the next event defaults to keydown
sKeyInfo.is_keydown = true;
return B_INVOKE_SCHEDULER;
}
static status_t
read_keyboard_packet(at_kbd_io *buffer)
{
status_t status;
status = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0);
if (status < B_OK)
return status;
status = cbuf_memcpy_from_chain(buffer, keyboard_buf, 0, sizeof(at_kbd_io));
if (status < B_OK)
TRACE(("read_keyboard_packet(): error reading packet: %s\n", strerror(status)));
return status;
}
// #pragma mark -
static status_t
keyboard_open(const char *name, uint32 flags, void **cookie)
{
if (atomic_or(&sOpenMask, 1) != 0)
return B_BUSY;
*cookie = NULL;
return B_OK;
}
static status_t
keyboard_close(void *cookie)
{
atomic_and(&sOpenMask);
return B_OK;
}
static status_t
keyboard_freecookie(void *cookie)
{
return B_OK;
}
static status_t
keyboard_read(void *cookie, off_t pos, void *buffer, size_t *_length)
{
*_length = 0;
return EROFS;
}
static status_t
keyboard_write(void *cookie, off_t pos, const void *buf, size_t *len)
{
*len = 0;
return EROFS;
}
static status_t
keyboard_ioctl(void *cookie, uint32 op, void *buf, size_t len)
{
switch (op) {
case KB_READ:
return read_keyboard_packet((at_kbd_io *)buf);
case KB_SET_LEDS:
set_leds((led_info *)buf);
return B_OK;
default:
return EINVAL;
}
}
device_hooks keyboard_hooks = {
&keyboard_open,
&keyboard_close,
&keyboard_freecookie,
&keyboard_ioctl,
&keyboard_read,
&keyboard_write,
NULL,
NULL,
NULL,
NULL
};
// #pragma mark -
/***** driver hooks *****/
status_t
init_hardware()
{
return B_OK;
}
const char **
publish_devices(void)
{
static const char *devices[] = {
DEVICE_NAME,
NULL
};
return devices;
}
device_hooks *
find_device(const char *name)
{
if (!strcmp(name, DEVICE_NAME))
return &keyboard_hooks;
return NULL;
}
status_t
init_driver()
{
if (get_module(B_ISA_MODULE_NAME, (module_info **)&sIsa) < B_OK)
panic("could not get ISA module\n");
keyboard_sem = create_sem(0, "keyboard_sem");
if (keyboard_sem < 0)
panic("could not create keyboard sem!\n");
if (mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0)
panic("could not create keyboard read mutex!\n");
keyboard_buf = cbuf_get_chain(1024);
if (keyboard_buf == NULL)
panic("could not create keyboard cbuf chain!\n");
install_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL, 0);
sKeyInfo.is_keydown = true;
sOpenMask = 0;
return B_OK;
}
void
uninit_driver()
{
remove_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL);
cbuf_free_chain(keyboard_buf);
delete_sem(keyboard_sem);
mutex_destroy(&keyboard_read_mutex);
put_module(B_ISA_MODULE_NAME);
}