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:
parent
682db4a4c5
commit
74708d31ce
@ -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()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user