HelenOS sources
This source file includes following definitions.
- key_released
- key_pressed
- kkbrd
- kbrd_init
- kbrd_wire
- is_lock_key
#include <assert.h>
#include <genarch/kbrd/kbrd.h>
#include <genarch/kbrd/scanc.h>
#include <genarch/kbrd/scanc_at.h>
#include <synch/spinlock.h>
#include <console/chardev.h>
#include <console/console.h>
#include <proc/thread.h>
#include <arch.h>
#include <macros.h>
#include <stdlib.h>
#define PRESSED_SHIFT (1 << 0)
#define PRESSED_CAPSLOCK (1 << 1)
#define LOCKED_CAPSLOCK (1 << 0)
#define AT_KEY_RELEASE 0xF0
#define AT_ESC_KEY 0xE0
#define AT_CAPS_SCAN_CODE 0x58
#define AT_NUM_SCAN_CODE 0x77
#define AT_SCROLL_SCAN_CODE 0x7E
static bool is_lock_key(char32_t);
static indev_operations_t kbrd_raw_ops = {
.poll = NULL
};
static void key_released(kbrd_instance_t *instance, char32_t sc)
{
spinlock_lock(&instance->keylock);
switch (sc) {
case SC_LSHIFT:
case SC_RSHIFT:
instance->keyflags &= ~PRESSED_SHIFT;
break;
case SC_CAPSLOCK:
instance->keyflags &= ~PRESSED_CAPSLOCK;
if (instance->lockflags & LOCKED_CAPSLOCK)
instance->lockflags &= ~LOCKED_CAPSLOCK;
else
instance->lockflags |= LOCKED_CAPSLOCK;
break;
default:
break;
}
spinlock_unlock(&instance->keylock);
}
static void key_pressed(kbrd_instance_t *instance, char32_t sc)
{
bool letter;
bool shift;
bool capslock;
spinlock_lock(&instance->keylock);
switch (sc) {
case SC_LSHIFT:
case SC_RSHIFT:
instance->keyflags |= PRESSED_SHIFT;
break;
case SC_CAPSLOCK:
instance->keyflags |= PRESSED_CAPSLOCK;
break;
case SC_SCAN_ESCAPE:
break;
default:
letter = islower(sc_primary_map[sc]);
shift = instance->keyflags & PRESSED_SHIFT;
capslock = (instance->keyflags & PRESSED_CAPSLOCK) ||
(instance->lockflags & LOCKED_CAPSLOCK);
if ((letter) && (capslock))
shift = !shift;
if (shift)
indev_push_character(instance->sink, sc_secondary_map[sc]);
else
indev_push_character(instance->sink, sc_primary_map[sc]);
break;
}
spinlock_unlock(&instance->keylock);
}
static void kkbrd(void *arg)
{
static int key_released_flag = 0;
static int is_locked = 0;
kbrd_instance_t *instance = (kbrd_instance_t *) arg;
while (true) {
char32_t sc = indev_pop_character(&instance->raw);
if (sc == AT_KEY_RELEASE) {
key_released_flag = 1;
} else {
if (key_released_flag) {
key_released_flag = 0;
if (is_lock_key(sc)) {
if (!is_locked) {
is_locked = 1;
} else {
is_locked = 0;
continue;
}
}
key_released(instance, sc);
} else {
if (is_lock_key(sc) && is_locked)
continue;
key_pressed(instance, sc);
}
}
}
}
kbrd_instance_t *kbrd_init(void)
{
kbrd_instance_t *instance;
instance = malloc(sizeof(kbrd_instance_t));
if (instance) {
instance->thread = thread_create(kkbrd, (void *) instance, TASK, 0,
"kkbrd");
if (!instance->thread) {
free(instance);
return NULL;
}
instance->sink = NULL;
indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops);
spinlock_initialize(&instance->keylock, "kbrd_at.instance.keylock");
instance->keyflags = 0;
instance->lockflags = 0;
}
return instance;
}
indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink)
{
assert(instance);
assert(sink);
instance->sink = sink;
thread_start(instance->thread);
return &instance->raw;
}
static bool is_lock_key(char32_t sc)
{
return ((sc == AT_CAPS_SCAN_CODE) || (sc == AT_NUM_SCAN_CODE) ||
(sc == AT_SCROLL_SCAN_CODE));
}
HelenOS homepage, sources at GitHub