toaruos/kernel/core/kbd.c

300 lines
5.6 KiB
C
Raw Normal View History

/*
* Low-level keyboard interrupt driver.
*
2011-04-15 06:02:44 +04:00
* Part of the ToAruOS Kernel
* (C) 2011 Kevin Lange
*
2011-04-15 06:02:44 +04:00
* TODO: Move this to a server.
*/
2011-01-16 21:45:51 +03:00
#include <system.h>
2011-10-23 04:32:03 +04:00
#define KEY_UP_MASK 0x80
#define KEY_CODE_MASK 0x7F
#define KEY_CTRL_MASK 0x40
#define KEY_DEVICE 0x60
#define KEY_PENDING 0x64
#define KEYBOARD_NOTICES 0
2011-04-15 06:02:44 +04:00
/* A bit-map to store the keyboard states */
2011-01-22 06:48:17 +03:00
struct keyboard_states {
uint32_t shift : 1;
uint32_t alt : 1;
uint32_t ctrl : 1;
} keyboard_state;
typedef void (*keyboard_handler_t)(int scancode);
2011-01-16 21:45:51 +03:00
char kbd_us[128] = {
0, 27,
'1','2','3','4','5','6','7','8','9','0',
'-','=','\b',
'\t', /* tab */
'q','w','e','r','t','y','u','i','o','p','[',']','\n',
0, /* control */
'a','s','d','f','g','h','j','k','l',';','\'', '`',
0, /* left shift */
'\\','z','x','c','v','b','n','m',',','.','/',
0, /* right shift */
'*',
0, /* alt */
' ', /* space */
0, /* caps lock */
0, /* F1 [59] */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* ... F10 */
0, /* 69 num lock */
0, /* scroll lock */
0, /* home */
0, /* up */
0, /* page up */
'-',
0, /* left arrow */
0,
0, /* right arrow */
'+',
0, /* 79 end */
0, /* down */
0, /* page down */
0, /* insert */
0, /* delete */
0, 0, 0,
0, /* F11 */
0, /* F12 */
0, /* everything else */
};
2011-01-22 06:48:17 +03:00
char kbd_us_l2[128] = {
0, 27,
'!','@','#','$','%','^','&','*','(',')',
'_','+','\b',
'\t', /* tab */
'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',
0, /* control */
'A','S','D','F','G','H','J','K','L',':','"', '~',
0, /* left shift */
'|','Z','X','C','V','B','N','M','<','>','?',
0, /* right shift */
'*',
0, /* alt */
' ', /* space */
0, /* caps lock */
0, /* F1 [59] */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* ... F10 */
0, /* 69 num lock */
0, /* scroll lock */
0, /* home */
0, /* up */
0, /* page up */
'-',
0, /* left arrow */
0,
0, /* right arrow */
'+',
0, /* 79 end */
0, /* down */
0, /* page down */
0, /* insert */
0, /* delete */
0, 0, 0,
0, /* F11 */
0, /* F12 */
0, /* everything else */
};
2011-10-23 04:32:03 +04:00
/*
* "Normal" key handler
* Used for visible text keys and handles
* application of shift/alt/control
*
* Shells out to putch() to do most of the work.
*/
2011-01-22 06:48:17 +03:00
void norm(int scancode) {
2011-10-23 04:32:03 +04:00
if (scancode & KEY_UP_MASK) {
2011-01-22 06:48:17 +03:00
return;
}
if (!kbd_us[scancode]) {
return;
}
if (keyboard_state.shift) {
putch(kbd_us_l2[scancode]);
} else if (keyboard_state.ctrl) {
2011-10-23 04:32:03 +04:00
int out = (int)(kbd_us_l2[scancode] - KEY_CTRL_MASK);
2011-02-08 03:22:03 +03:00
if (out < 0 || out > 0x1F) {
putch(kbd_us[scancode]);
} else {
putch((char)out);
}
2011-01-22 06:48:17 +03:00
} else {
putch(kbd_us[scancode]);
}
}
2011-10-23 04:32:03 +04:00
/*
* Toggle Shift
*/
2011-01-22 06:48:17 +03:00
void shft(int scancode) {
2011-10-31 10:48:03 +04:00
keyboard_state.shift = !((scancode & KEY_UP_MASK) == KEY_UP_MASK);
2011-01-22 06:48:17 +03:00
}
2011-10-23 04:32:03 +04:00
/*
* Toggle Alt
*/
2011-01-22 06:48:17 +03:00
void altk(int scancode) {
2011-10-31 10:48:03 +04:00
keyboard_state.alt = !((scancode & KEY_UP_MASK) == KEY_UP_MASK);
2011-01-22 06:48:17 +03:00
}
2011-10-23 04:32:03 +04:00
/*
* Toggle Control
*/
2011-01-22 06:48:17 +03:00
void ctlk(int scancode) {
2011-10-31 10:48:03 +04:00
keyboard_state.ctrl = !((scancode & KEY_UP_MASK) == KEY_UP_MASK);
2011-01-22 06:48:17 +03:00
}
2011-10-23 04:32:03 +04:00
/*
* Function keys
*/
2011-01-22 06:48:17 +03:00
void func(int scancode) {
2011-10-23 04:32:03 +04:00
if (scancode & KEY_UP_MASK) {
2011-04-19 03:12:37 +04:00
return;
}
#if KEYBOARD_NOTICES
2011-03-25 08:09:23 +03:00
kprintf("[NOTICE] Function key %d pressed\n", scancode);
#endif
2011-03-25 08:09:23 +03:00
}
2011-10-23 04:32:03 +04:00
/*
* "Special" keys
* Extra keys on your keyboard will produce these
* sorts of key presses.
*/
2011-03-25 08:09:23 +03:00
void spec(int scancode) {
2011-10-23 04:32:03 +04:00
if (scancode & KEY_UP_MASK) {
2011-03-25 08:09:23 +03:00
return;
}
2011-04-19 03:12:37 +04:00
switch (scancode) {
case 75:
putch('\033');
putch('[');
putch('D');
break;
case 72:
putch('\033');
putch('[');
putch('A');
break;
case 77:
putch('\033');
putch('[');
putch('C');
break;
case 80:
putch('\033');
putch('[');
putch('B');
break;
case 1:
putch('\033');
default:
#if KEYBOARD_NOTICES
2011-04-19 03:12:37 +04:00
kprintf("[NOTICE] Special key %d pressed\n", scancode);
#endif
2011-04-19 03:12:37 +04:00
break;
}
2011-01-22 06:48:17 +03:00
}
keyboard_handler_t key_method[] = {
2011-03-25 08:09:23 +03:00
/* 00 */ NULL, spec, norm, norm, norm, norm, norm, norm,
2011-01-22 06:48:17 +03:00
/* 08 */ norm, norm, norm, norm, norm, norm, norm, norm,
/* 10 */ norm, norm, norm, norm, norm, norm, norm, norm,
/* 18 */ norm, norm, norm, norm, norm, ctlk, norm, norm,
/* 20 */ norm, norm, norm, norm, norm, norm, norm, norm,
/* 28 */ norm, norm, shft, norm, norm, norm, norm, norm,
/* 30 */ norm, norm, norm, norm, norm, norm, shft, norm,
2011-03-25 08:09:23 +03:00
/* 38 */ altk, norm, spec, func, func, func, func, func,
/* 40 */ func, func, func, func, func, spec, spec, spec,
/* 48 */ spec, spec, spec, spec, spec, spec, spec, spec,
/* 50 */ spec, spec, spec, spec, spec, spec, spec, func,
/* 58 */ func, spec, spec, spec, spec, spec, spec, spec,
/* 60 */ spec, spec, spec, spec, spec, spec, spec, spec,
/* 68 */ spec, spec, spec, spec, spec, spec, spec, spec,
/* 70 */ spec, spec, spec, spec, spec, spec, spec, spec,
/* 78 */ spec, spec, spec, spec, spec, spec, spec, spec,
2011-01-22 06:48:17 +03:00
};
2011-10-31 10:48:03 +04:00
extern uint8_t mouse_cycle;
2011-01-16 21:45:51 +03:00
void
keyboard_handler(
struct regs *r
) {
2011-12-08 06:58:25 +04:00
IRQ_OFF;
2011-01-16 21:45:51 +03:00
unsigned char scancode;
keyboard_wait();
2011-10-23 04:32:03 +04:00
scancode = inportb(KEY_DEVICE);
2011-12-08 06:58:25 +04:00
IRQ_ON;
if (keyboard_direct_handler) {
2011-05-01 10:51:48 +04:00
keyboard_direct_handler(scancode);
return;
}
2011-01-22 06:48:17 +03:00
keyboard_handler_t handler;
2011-10-31 10:48:03 +04:00
2011-10-23 04:32:03 +04:00
handler = key_method[(int)scancode & KEY_CODE_MASK];
2011-01-22 06:48:17 +03:00
if (handler) {
handler(scancode);
2011-01-16 21:45:51 +03:00
}
}
void
keyboard_install() {
/* IRQ installer */
keyboard_buffer_handler = NULL;
keyboard_direct_handler = NULL;
2011-12-08 01:01:31 +04:00
irq_install_handler(1, keyboard_handler);
2011-01-16 21:45:51 +03:00
}
void
keyboard_wait() {
2011-10-23 04:32:03 +04:00
while(inportb(KEY_PENDING) & 2);
2011-01-16 21:45:51 +03:00
}
/*
* putch
*/
void
putch(
unsigned char c
) {
if (keyboard_buffer_handler) {
keyboard_buffer_handler(c);
} else {
2011-10-23 04:32:03 +04:00
if (c == 3 /* ^L */) {
return;
}
}
}
/*
* Externally Set Keyboard States
*/
void
set_kbd(
int shift,
int alt,
int ctrl
) {
keyboard_state.shift = shift;
keyboard_state.alt = alt;
keyboard_state.ctrl = ctrl;
}
2011-04-15 06:02:44 +04:00
/*
* vim:tabstop=4
* vim:noexpandtab
*/