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>
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
);
53 static __inline__
wchar_t *vt_keyboard_load_layout(const char *path
) {
54 FILE *fd
= fopen(path
,"r");
58 if (memcmp(sig
,"meinOS-KL",9)==0) {
59 void *buf
= malloc(0x400*sizeof(wchar_t));
60 fread(buf
,sizeof(wchar_t),0x400,fd
);
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;
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
;
88 scancode
= inb(VT_KEYBOARD_IOPORT_DATA
);
89 //DEBUG("scancode: 0x%x\n",scancode);
91 released
= scancode
&0x80;
95 // check for escaped key
96 if (keyboard
->escape
) {
100 if (scancode
==0xE0) {
101 keyboard
->escape
= 1;
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
;
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
);
123 //DEBUG("keyboard: Read character: '%c' (0x%02x)\n",chr,chr);
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;
136 ringbuf_write(keyboard
->buffer
,&chr
,1);