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:
@@ -18,26 +18,44 @@
|
|||||||
|
|
||||||
#define DEVICE_NAME "keyboard"
|
#define DEVICE_NAME "keyboard"
|
||||||
|
|
||||||
#define LSHIFT 42
|
#define TRACE_KEYBOARD 0
|
||||||
#define RSHIFT 54
|
#if TRACE_KEYBOARD
|
||||||
#define SCRLOCK 70
|
# define TRACE(x) dprintf x
|
||||||
#define NUMLOCK 69
|
#else
|
||||||
#define CAPS 58
|
# define TRACE(x) ;
|
||||||
#define SYSREQ 55
|
#endif
|
||||||
#define F11 87
|
|
||||||
#define F12 88
|
|
||||||
|
|
||||||
#define LED_SCROLL 1
|
|
||||||
#define LED_NUM 2
|
enum keycodes {
|
||||||
#define LED_CAPS 4
|
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 bool shift;
|
||||||
static int leds;
|
static int leds;
|
||||||
static sem_id keyboard_sem;
|
static sem_id keyboard_sem;
|
||||||
static mutex keyboard_read_mutex;
|
static mutex keyboard_read_mutex;
|
||||||
static char keyboard_buf[1024];
|
static char keyboard_buf[1024];
|
||||||
static unsigned int head, tail;
|
static unsigned int head, tail;
|
||||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
|
||||||
|
|
||||||
// stolen from nujeffos
|
// stolen from nujeffos
|
||||||
const char unshifted_keymap[128] = {
|
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
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wait_for_output(void)
|
wait_for_output(void)
|
||||||
{
|
{
|
||||||
while(in8(0x64) & 0x2)
|
while (in8(0x64) & 0x2)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_leds(void)
|
set_leds(void)
|
||||||
{
|
{
|
||||||
@@ -89,59 +109,6 @@ set_leds(void)
|
|||||||
out8(leds, 0x60);
|
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
|
static void
|
||||||
insert_in_buf(char c)
|
insert_in_buf(char c)
|
||||||
@@ -151,7 +118,7 @@ insert_in_buf(char c)
|
|||||||
// see if the next char will collide with the head
|
// see if the next char will collide with the head
|
||||||
temp_tail++;
|
temp_tail++;
|
||||||
temp_tail %= sizeof(keyboard_buf);
|
temp_tail %= sizeof(keyboard_buf);
|
||||||
if(temp_tail == head) {
|
if (temp_tail == head) {
|
||||||
// buffer overflow, ditch this char
|
// buffer overflow, ditch this char
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -160,127 +127,197 @@ insert_in_buf(char c)
|
|||||||
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
|
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
handle_keyboard_interrupt(void* data)
|
handle_keyboard_interrupt(void *data)
|
||||||
{
|
{
|
||||||
unsigned char key;
|
unsigned char key;
|
||||||
int32 retval = B_HANDLED_INTERRUPT;
|
int32 retval = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
key = in8(0x60);
|
key = in8(0x60);
|
||||||
// dprintf("handle_keyboard_interrupt: key = 0x%x\n", key);
|
TRACE(("handle_keyboard_interrupt: key = 0x%x\n", key));
|
||||||
|
|
||||||
if(key & 0x80) {
|
if (key & 0x80) {
|
||||||
// keyup
|
// key up
|
||||||
if(key == LSHIFT + 0x80 || key == RSHIFT + 0x80)
|
if (key == LSHIFT + 0x80 || key == RSHIFT + 0x80)
|
||||||
shift = false;
|
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)
|
return B_HANDLED_INTERRUPT;
|
||||||
ascii = shifted_keymap[key];
|
}
|
||||||
else
|
|
||||||
if (leds & LED_CAPS)
|
|
||||||
ascii = caps_keymap[key];
|
|
||||||
else
|
|
||||||
ascii = unshifted_keymap[key];
|
|
||||||
|
|
||||||
// dprintf("ascii = 0x%x, '%c'\n", ascii, ascii);
|
switch (key) {
|
||||||
if(ascii != 0) {
|
case LSHIFT:
|
||||||
insert_in_buf(ascii);
|
case RSHIFT:
|
||||||
retval = B_INVOKE_SCHEDULER;
|
shift = true;
|
||||||
} else {
|
break;
|
||||||
// dprintf("keyboard: unknown scan-code 0x%x\n",key);
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
keyboard_open(const char *name, uint32 flags, void * *cookie)
|
keyboard_open(const char *name, uint32 flags, void **cookie)
|
||||||
{
|
{
|
||||||
*cookie = NULL;
|
*cookie = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static status_t
|
|
||||||
keyboard_close(void * cookie)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
keyboard_freecookie(void * cookie)
|
keyboard_close(void *cookie)
|
||||||
{
|
{
|
||||||
return 0;
|
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);
|
static status_t
|
||||||
if (rv < 0)
|
keyboard_freecookie(void *cookie)
|
||||||
return rv;
|
{
|
||||||
*len = rv;
|
|
||||||
return 0;
|
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;
|
return EROFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
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;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device_hooks keyboard_hooks = {
|
device_hooks keyboard_hooks = {
|
||||||
&keyboard_open,
|
&keyboard_open,
|
||||||
&keyboard_close,
|
&keyboard_close,
|
||||||
@@ -294,37 +331,35 @@ device_hooks keyboard_hooks = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
setup_keyboard(void)
|
/***** driver hooks *****/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
init_hardware()
|
||||||
{
|
{
|
||||||
keyboard_sem = create_sem(0, "keyboard_sem");
|
keyboard_sem = create_sem(0, "keyboard_sem");
|
||||||
if(keyboard_sem < 0)
|
if (keyboard_sem < 0)
|
||||||
panic("could not create keyboard sem!\n");
|
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");
|
panic("could not create keyboard read mutex!\n");
|
||||||
|
|
||||||
shift = 0;
|
shift = 0;
|
||||||
leds = 0;
|
leds = 0;
|
||||||
|
|
||||||
// have the scroll lock reflect the state of serial debugging
|
// have the scroll lock reflect the state of serial debugging
|
||||||
if(dbg_get_serial_debug())
|
if (dbg_get_serial_debug())
|
||||||
leds |= LED_SCROLL;
|
leds |= LED_SCROLL;
|
||||||
set_leds();
|
set_leds();
|
||||||
|
|
||||||
head = tail = 0;
|
head = tail = 0;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t
|
|
||||||
init_hardware()
|
|
||||||
{
|
|
||||||
setup_keyboard();
|
|
||||||
install_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL, 0);
|
install_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char **
|
const char **
|
||||||
publish_devices(void)
|
publish_devices(void)
|
||||||
{
|
{
|
||||||
@@ -336,6 +371,7 @@ publish_devices(void)
|
|||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device_hooks *
|
device_hooks *
|
||||||
find_device(const char *name)
|
find_device(const char *name)
|
||||||
{
|
{
|
||||||
@@ -345,12 +381,14 @@ find_device(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
init_driver()
|
init_driver()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
uninit_driver()
|
uninit_driver()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user