Cleaned up the code, merged _keyboard_read() and keyboard_read(), and

merged setup_keyboard() and init_driver().
Added TRACE_KEYBOARD define to easily enable debug output from the keyboard driver.
Also made the escape key dropping into KDL - all special keys (like the
F-keys, etc.) aren't working in BeBochs, so that's a simple work-around
for that problem.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1302 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2002-09-30 01:43:28 +00:00
parent 682db4a4c5
commit 74708d31ce
1 changed files with 198 additions and 160 deletions

View File

@ -18,26 +18,44 @@
#define DEVICE_NAME "keyboard"
#define LSHIFT 42
#define RSHIFT 54
#define SCRLOCK 70
#define NUMLOCK 69
#define CAPS 58
#define SYSREQ 55
#define F11 87
#define F12 88
#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
enum keycodes {
ESCAPE = 1,
LSHIFT = 42,
RSHIFT = 54,
CAPS_LOCK = 58,
NUM_LOCK = 69,
SCR_LOCK = 70,
SYS_REQ = 55,
F1 = 0x3b,
F2, F3, F4, F5, F6,
F7, F8, F9, F10,
F11 = 87,
F12 = 88,
};
#define LED_SCROLL 1
#define LED_NUM 2
#define LED_CAPS 4
int32 api_version = B_CUR_DRIVER_API_VERSION;
static bool shift;
static int leds;
static int leds;
static sem_id keyboard_sem;
static mutex keyboard_read_mutex;
static char keyboard_buf[1024];
static unsigned int head, tail;
int32 api_version = B_CUR_DRIVER_API_VERSION;
// stolen from nujeffos
const char unshifted_keymap[128] = {
@ -73,13 +91,15 @@ const char caps_keymap[128] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void
wait_for_output(void)
{
while(in8(0x64) & 0x2)
while (in8(0x64) & 0x2)
;
}
static void
set_leds(void)
{
@ -89,59 +109,6 @@ set_leds(void)
out8(leds, 0x60);
}
static ssize_t
_keyboard_read(void *_buf, size_t len)
{
unsigned int saved_tail;
char *buf = _buf;
size_t copied_bytes = 0;
size_t copy_len;
int rc;
if(len > sizeof(keyboard_buf) - 1)
len = sizeof(keyboard_buf) - 1;
retry:
// block here until data is ready
rc = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0);
if(rc == EINTR) {
return 0;
}
// critical section
mutex_lock(&keyboard_read_mutex);
saved_tail = tail;
if(head == saved_tail) {
mutex_unlock(&keyboard_read_mutex);
goto retry;
} else {
// copy out of the buffer
if(head < saved_tail)
copy_len = min(len, saved_tail - head);
else
copy_len = min(len, sizeof(keyboard_buf) - head);
memcpy(buf, &keyboard_buf[head], copy_len);
copied_bytes = copy_len;
head = (head + copy_len) % sizeof(keyboard_buf);
if(head == 0 && saved_tail > 0 && copied_bytes < len) {
// we wrapped around and have more bytes to read
// copy the first part of the buffer
copy_len = min(saved_tail, len - copied_bytes);
memcpy(&buf[len], &keyboard_buf[0], copy_len);
copied_bytes += copy_len;
head = copy_len;
}
}
if(head != saved_tail) {
// we did not empty the keyboard queue
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
}
mutex_unlock(&keyboard_read_mutex);
return copied_bytes;
}
static void
insert_in_buf(char c)
@ -151,7 +118,7 @@ insert_in_buf(char c)
// see if the next char will collide with the head
temp_tail++;
temp_tail %= sizeof(keyboard_buf);
if(temp_tail == head) {
if (temp_tail == head) {
// buffer overflow, ditch this char
return;
}
@ -160,127 +127,197 @@ insert_in_buf(char c)
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
}
static int32
handle_keyboard_interrupt(void* data)
handle_keyboard_interrupt(void *data)
{
unsigned char key;
int32 retval = B_HANDLED_INTERRUPT;
key = in8(0x60);
// dprintf("handle_keyboard_interrupt: key = 0x%x\n", key);
TRACE(("handle_keyboard_interrupt: key = 0x%x\n", key));
if(key & 0x80) {
// keyup
if(key == LSHIFT + 0x80 || key == RSHIFT + 0x80)
if (key & 0x80) {
// key up
if (key == LSHIFT + 0x80 || key == RSHIFT + 0x80)
shift = false;
} else {
switch(key) {
case LSHIFT:
case RSHIFT:
shift = true;
break;
case CAPS:
if(leds & LED_CAPS)
leds &= ~LED_CAPS;
else
leds |= LED_CAPS;
set_leds();
break;
case SCRLOCK:
if(leds & LED_SCROLL) {
leds &= ~LED_SCROLL;
dbg_set_serial_debug(false);
} else {
leds |= LED_SCROLL;
dbg_set_serial_debug(true);
}
set_leds();
break;
case NUMLOCK:
if(leds & LED_NUM)
leds &= ~LED_NUM;
else
leds |= LED_NUM;
set_leds();
break;
case SYSREQ:
panic("Keyboard Requested Halt\n");
break;
case F11:
dbg_set_serial_debug(dbg_get_serial_debug()?false:true);
break;
case F12:
reboot();
break;
default: {
char ascii;
if(shift)
ascii = shifted_keymap[key];
else
if (leds & LED_CAPS)
ascii = caps_keymap[key];
else
ascii = unshifted_keymap[key];
return B_HANDLED_INTERRUPT;
}
// dprintf("ascii = 0x%x, '%c'\n", ascii, ascii);
if(ascii != 0) {
insert_in_buf(ascii);
retval = B_INVOKE_SCHEDULER;
} else {
// dprintf("keyboard: unknown scan-code 0x%x\n",key);
}
switch (key) {
case LSHIFT:
case RSHIFT:
shift = true;
break;
case CAPS_LOCK:
if (leds & LED_CAPS)
leds &= ~LED_CAPS;
else
leds |= LED_CAPS;
set_leds();
break;
case SCR_LOCK:
if (leds & LED_SCROLL) {
leds &= ~LED_SCROLL;
dbg_set_serial_debug(false);
} else {
leds |= LED_SCROLL;
dbg_set_serial_debug(true);
}
set_leds();
break;
case NUM_LOCK:
if (leds & LED_NUM)
leds &= ~LED_NUM;
else
leds |= LED_NUM;
set_leds();
break;
/* the following code has two possibilities because of issues
* with BeBochs & BeOS (all special keys don't map to anything
* useful, and SYS_REQ does a screen dump in BeOS).
* ToDo: remove these key functions some day...
*/
case ESCAPE:
case SYS_REQ:
panic("Keyboard Requested Halt\n");
break;
case F11:
dbg_set_serial_debug(dbg_get_serial_debug() ? false : true);
break;
case F12:
reboot();
break;
default: {
char ascii;
if (shift)
ascii = shifted_keymap[key];
else {
if (leds & LED_CAPS)
ascii = caps_keymap[key];
else
ascii = unshifted_keymap[key];
}
TRACE(("ascii = 0x%x, '%c'\n", ascii, ascii));
if (ascii != 0) {
insert_in_buf(ascii);
retval = B_INVOKE_SCHEDULER;
} else
TRACE(("keyboard: unknown scan-code 0x%x\n", key));
}
}
return retval;
}
static status_t
keyboard_open(const char *name, uint32 flags, void * *cookie)
keyboard_open(const char *name, uint32 flags, void **cookie)
{
*cookie = NULL;
return 0;
}
static status_t
keyboard_close(void * cookie)
{
return 0;
}
static status_t
keyboard_freecookie(void * cookie)
keyboard_close(void *cookie)
{
return 0;
}
static ssize_t
keyboard_read(void * cookie, off_t pos, void *buf, size_t *len)
{
int rv;
if (*len < 0)
return 0;
rv = _keyboard_read(buf, *len);
if (rv < 0)
return rv;
*len = rv;
static status_t
keyboard_freecookie(void *cookie)
{
return 0;
}
static ssize_t
keyboard_write(void * cookie, off_t pos, const void *buf, size_t *len)
static status_t
keyboard_read(void *cookie, off_t pos, void *buffer, size_t *_length)
{
unsigned int savedTail;
size_t length = *_length;
size_t copiedBytes = 0;
int status;
if (length < 0) {
*_length = 0;
return B_OK;
}
if (length > sizeof(keyboard_buf) - 1)
length = sizeof(keyboard_buf) - 1;
retry:
// block here until data is ready
status = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0);
if (status == B_INTERRUPTED) {
*_length = 0;
return B_OK;
}
// critical section
mutex_lock(&keyboard_read_mutex);
savedTail = tail;
if (head == savedTail) {
// buffer queue is empty
mutex_unlock(&keyboard_read_mutex);
goto retry;
} else {
size_t copyLength;
// copy out of the buffer
if (head < savedTail)
copyLength = min(length, savedTail - head);
else
copyLength = min(length, sizeof(keyboard_buf) - head);
memcpy(buffer, &keyboard_buf[head], copyLength);
copiedBytes = copyLength;
head = (head + copyLength) % sizeof(keyboard_buf);
if (head == 0 && savedTail > 0 && copiedBytes < length) {
// we wrapped around and have more bytes to read
// copy the first part of the buffer
copyLength = min(savedTail, length - copiedBytes);
memcpy((uint8 *)buffer + length, keyboard_buf, copyLength);
copiedBytes += copyLength;
head = copyLength;
}
}
if (head != savedTail) {
// we did not empty the keyboard queue
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
}
mutex_unlock(&keyboard_read_mutex);
*_length = copiedBytes;
return B_OK;
}
static status_t
keyboard_write(void *cookie, off_t pos, const void *buf, size_t *len)
{
return EROFS;
}
static status_t
keyboard_ioctl(void * cookie, uint32 op, void *buf, size_t len)
keyboard_ioctl(void *cookie, uint32 op, void *buf, size_t len)
{
return EINVAL;
}
device_hooks keyboard_hooks = {
&keyboard_open,
&keyboard_close,
@ -294,37 +331,35 @@ device_hooks keyboard_hooks = {
NULL
};
static int
setup_keyboard(void)
/***** driver hooks *****/
status_t
init_hardware()
{
keyboard_sem = create_sem(0, "keyboard_sem");
if(keyboard_sem < 0)
if (keyboard_sem < 0)
panic("could not create keyboard sem!\n");
if(mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0)
if (mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0)
panic("could not create keyboard read mutex!\n");
shift = 0;
leds = 0;
// have the scroll lock reflect the state of serial debugging
if(dbg_get_serial_debug())
if (dbg_get_serial_debug())
leds |= LED_SCROLL;
set_leds();
head = tail = 0;
return 0;
}
status_t
init_hardware()
{
setup_keyboard();
install_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL, 0);
return 0;
}
const char **
publish_devices(void)
{
@ -336,6 +371,7 @@ publish_devices(void)
return devices;
}
device_hooks *
find_device(const char *name)
{
@ -345,12 +381,14 @@ find_device(const char *name)
return NULL;
}
status_t
init_driver()
{
return 0;
}
void
uninit_driver()
{