stdlibc: ~several fixes
[meinos.git] / apps / vterm / keyboard.c
blob4241818e1d8292d66d2b7df1d6608a7dc990282d
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <llist.h>
21 #include <irq.h>
22 #include <ioport.h>
23 #include <wchar.h>
25 #include "vterm.h"
27 #define VT_KEYBOARD_IRQ 1
28 #define VT_KEYBOARD_IOPORT_DATA 0x60
29 #define VT_KEYBOARD_IOPORT_STATUS 0x64
30 #define VT_KEYBOARD_BUFSZ 128
31 #define VT_KEYBOARD_DEFAULT_LAYOUT "/boot/etc/keyboard_layouts/de"
33 #define VT_KEYBOARD_IS_SHIFT(scancode) ((scancode)==0x2A || (scancode)==0x36)
34 #define VT_KEYBOARD_IS_ALTGR(scancode) ((scancode)==0xB8)
35 #define VT_KEYBOARD_IS_CTRL(scancode) ((scancode)==0x1D || (scancode)==0x9D)
36 #define VT_KEYBOARD_IS_ALT(scancode) ((scancode)==0x38 || (scancode)==0xBD)
37 #define VT_KEYBOARD_IS_FXX(scancode) (((scancode)>=0x3B && (scancode)<0x45) || (scancode)==0x54 || (scancode)==0x55)
39 static __inline__ wchar_t *vt_keyboard_load_layout(const char *path);
40 static void vt_keyboard_irqhandler(vt_keyboard_t *keyboard);
42 int vt_keyboard_init() {
43 if (ioport_reg(VT_KEYBOARD_IOPORT_DATA)==-1) return -1;
44 if (ioport_reg(VT_KEYBOARD_IOPORT_STATUS)==-1) return -1;
45 irq_reghandler(VT_KEYBOARD_IRQ,vt_keyboard_irqhandler,&vt_keyboard,0);
46 vt_keyboard.buffer = ringbuf_create(VT_KEYBOARD_BUFSZ);
47 vt_keyboard.layout = vt_keyboard_load_layout(VT_KEYBOARD_DEFAULT_LAYOUT);
48 vt_keyboard_irqhandler(&vt_keyboard);
50 return 0;
53 static __inline__ wchar_t *vt_keyboard_load_layout(const char *path) {
54 FILE *fd = fopen(path,"r");
55 if (fd!=NULL) {
56 char sig[19];
57 fread(sig,1,19,fd);
58 if (memcmp(sig,"meinOS-KL",9)==0) {
59 void *buf = malloc(0x400*sizeof(wchar_t));
60 fread(buf,sizeof(wchar_t),0x400,fd);
61 fclose(fd);
62 return buf;
64 fclose(fd);
66 return NULL;
69 static int vt_keyboard_get_fxx(int scancode) {
70 if (scancode>=0x3B && scancode<0x45) return scancode-0x3A;
71 else if (scancode==0x54) return 11;
72 else if (scancode==0x55) return 12;
73 else return 0;
76 static wchar_t vt_keyboard_scancode_to_wchar(vt_keyboard_t *keyboard,int scancode) {
77 if (keyboard->layout==NULL) return 0;
79 int modifier = (keyboard->modifiers.shift?1:0)|(keyboard->modifiers.altgr?2:0);
80 return keyboard->layout[scancode*4+modifier];
83 static void vt_keyboard_irqhandler(vt_keyboard_t *keyboard) {
84 while (inb(VT_KEYBOARD_IOPORT_STATUS)&1) {
85 int released,scancode;
87 // get scancode
88 scancode = inb(VT_KEYBOARD_IOPORT_DATA);
89 //DEBUG("scancode: 0x%x\n",scancode);
90 if (scancode!=0xE0) {
91 released = scancode&0x80;
92 scancode &= 0x7F;
95 // check for escaped key
96 if (keyboard->escape) {
97 scancode |= 0x80;
98 keyboard->escape = 0;
100 if (scancode==0xE0) {
101 keyboard->escape = 1;
102 continue;
105 // if shift is pressed/released
106 if (VT_KEYBOARD_IS_SHIFT(scancode)) keyboard->modifiers.shift = !released;
107 // if AltGr is pressed/released
108 else if (VT_KEYBOARD_IS_ALTGR(scancode)) keyboard->modifiers.altgr = !released;
109 // if Shift is pressed/released
110 else if (VT_KEYBOARD_IS_ALTGR(scancode)) keyboard->modifiers.altgr = !released;
111 // if Alt is pressed/released
112 else if (VT_KEYBOARD_IS_ALT(scancode)) keyboard->modifiers.alt = !released;
113 // if Fxx is pressed
114 else if (VT_KEYBOARD_IS_FXX(scancode) && keyboard->modifiers.ctrl && keyboard->modifiers.alt) {
115 int fxx = vt_keyboard_get_fxx(scancode);
116 if (vt_shortcuts[fxx]>0) vt_term_activate(vt_shortcuts[fxx-1]);
118 // normal key pressed
119 else if (!released) {
120 wchar_t chr = vt_keyboard_scancode_to_wchar(keyboard,scancode);
121 if (chr>0x7F) DEBUG("TODO: Wide characters (%s:%d): 0x%x\n",__FILE__,__LINE__,chr);
122 else if (chr!=0) {
123 //DEBUG("keyboard: Read character: '%c' (0x%02x)\n",chr,chr);
124 // escape sequence
125 if (keyboard->modifiers.ctrl) {
126 if (chr=='@') chr = 0x00;
127 else if (chr>='A' && chr<='Z') chr = chr-'A'+1;
128 else if (chr=='[') chr = 0x1B;
129 else if (chr=='\\') chr = 0x1C;
130 else if (chr==']') chr = 0x1D;
131 else if (chr=='^') chr = 0x1E;
132 else if (chr=='_') chr = 0x1F;
134 // normal character
135 else {
136 ringbuf_write(keyboard->buffer,&chr,1);
137 dbgmsg("%c",chr);