151 lines
4.2 KiB
C
151 lines
4.2 KiB
C
/*
|
|
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
|
* RWTH Aachen University
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* This file is part of MetalSVM.
|
|
*/
|
|
|
|
#include <metalsvm/stdlib.h>
|
|
#include <metalsvm/stdio.h>
|
|
#include <metalsvm/string.h>
|
|
#include <metalsvm/tasks.h>
|
|
#include <asm/kb.h>
|
|
#include <asm/irq.h>
|
|
|
|
#ifdef CONFIG_KEYBOARD
|
|
|
|
kb_buffer_t kb_buffer = {NULL, 0, 0, 0 };
|
|
|
|
void kb_init(size_t size, tid_t tid) {
|
|
kb_buffer.buffer = kmalloc(size * sizeof(char));
|
|
kb_buffer.size = 0;
|
|
kb_buffer.maxsize = size;
|
|
kb_buffer.tid = tid;
|
|
return;
|
|
}
|
|
|
|
void kb_finish(void) {
|
|
kfree(kb_buffer.buffer, (kb_buffer.maxsize * sizeof(char)));
|
|
kb_buffer.buffer = NULL;
|
|
kb_buffer.size = 0;
|
|
kb_buffer.maxsize = 0;
|
|
kb_buffer.tid = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* KBDUS means US Keyboard Layout. This is a scancode table
|
|
* used to layout a standard US keyboard. I have left some
|
|
* comments in to give you an idea of what key is what, even
|
|
* though I set it's array index to 0. You can change that to
|
|
* whatever you want using a macro, if you wish!
|
|
*/
|
|
static const unsigned char kbdus[128] = { 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
|
'9', '0', '-', '=', '\b', /* Backspace */
|
|
'\t', /* Tab */
|
|
'q', 'w', 'e', 'r', /* 19 */
|
|
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
|
0, /* 29 - Control */
|
|
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
|
'\'', '`', 0, /* Left shift */
|
|
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
|
'm', ',', '.', '/', 0, /* Right shift */
|
|
'*', 0, /* Alt */
|
|
' ', /* 57 - Space bar */
|
|
0, /* 58 - Caps lock */
|
|
0, /* 59 - F1 key ... > */
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, /* < ... F10 */
|
|
0, /* 69 - Num lock */
|
|
0, /* Scroll Lock */
|
|
0, /* Home key */
|
|
0, /* Up Arrow */
|
|
0, /* Page Up */
|
|
'-', 0, /* Left Arrow */
|
|
0, 0, /* Right Arrow */
|
|
'+', 0, /* 79 - End key */
|
|
0, /* Down Arrow */
|
|
0, /* Page Down */
|
|
0, /* Insert Key */
|
|
0, /* Delete Key */
|
|
0, 0, 0, 0, /* F11 Key */
|
|
0, /* F12 Key */
|
|
0, /* All other keys are undefined */
|
|
};
|
|
|
|
/* Handles the keyboard interrupt */
|
|
static void keyboard_handler(struct state *r)
|
|
{
|
|
unsigned char scancode;
|
|
|
|
/* Read from the keyboard's data buffer */
|
|
scancode = inportb(0x60);
|
|
|
|
/*
|
|
* If the top bit of the byte we read from the keyboard is
|
|
* set, that means that a key has just been released
|
|
*/
|
|
if (scancode & 0x80) {
|
|
|
|
/*
|
|
* You can use this one to see if the user released the
|
|
* shift, alt, or control keys...
|
|
*/
|
|
} else {
|
|
|
|
/*
|
|
* Here, a key was just pressed. Please note that if you
|
|
* hold a key down, you will get repeated key press
|
|
* interrupts.
|
|
*/
|
|
|
|
/* Just to show you how this works, we simply translate
|
|
* the keyboard scancode into an ASCII value, and then
|
|
* display it to the screen. You can get creative and
|
|
* use some flags to see if a shift is pressed and use a
|
|
* different layout, or you can add another 128 entries
|
|
* to the above layout to correspond to 'shift' being
|
|
* held. If shift is held using the larger lookup table,
|
|
* you would add 128 to the scancode when you look for it
|
|
*/
|
|
if (kb_buffer.size <= kb_buffer.maxsize && kb_buffer.buffer != NULL) {
|
|
if (scancode == 14) {
|
|
if (kb_buffer.size != 0) {
|
|
kb_buffer.size--;
|
|
kputchar(kbdus[scancode]);
|
|
kputchar(kbdus[57]);
|
|
kputchar(kbdus[scancode]);
|
|
}
|
|
}
|
|
else {
|
|
kputchar(kbdus[scancode]);
|
|
memcpy(kb_buffer.buffer + kb_buffer.size, &kbdus[scancode], 1);
|
|
kb_buffer.size++;
|
|
}
|
|
if (scancode == 28 || scancode == 15 || kb_buffer.size >= kb_buffer.maxsize) {
|
|
kputchar(kbdus[scancode]);
|
|
wakeup_task(kb_buffer.tid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Installs the keyboard handler into IRQ1 */
|
|
void keyboard_init(void)
|
|
{
|
|
irq_install_handler(1+32, keyboard_handler);
|
|
}
|
|
|
|
#endif
|