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>
31 #define KEYBOARD_IRQ 0x01
32 #define KEYBOARD_PORT_DATA 0x60
33 #define KEYBOARD_PORT_STATUS 0x64
34 #define KEYBUF_SIZE 128
36 /// @todo later "/etc/..." should work (symlink)
37 #define KEYBOARD_DEFAULT_LAYOUT "/boot/etc/keyboard_layouts/de"
39 #define IS_SHIFT(scancode) (scancode==0x2A || scancode==0x36)
40 #define IS_ALTCAP(scancode) (scancode==0xB8)
51 unsigned int width
; // Num of attributes
52 unsigned int height
; // Num of keys
57 static int keyboard_layout_load(const char *filename
) {
58 int fh
= open(filename
,O_RDONLY
);
60 read(fh
,&(keyboard
.layout
.has_shift
),1);
61 read(fh
,&(keyboard
.layout
.has_altcap
),1);
62 keyboard
.layout
.width
= 1+(keyboard
.layout
.has_shift
?1:0)+(keyboard
.layout
.has_altcap
?1:0);
63 read(fh
,&(keyboard
.layout
.height
),4);
64 keyboard
.layout
.table
= calloc(keyboard
.layout
.width
*keyboard
.layout
.height
,sizeof(wchar_t));
65 read(fh
,keyboard
.layout
.table
,keyboard
.layout
.width
*keyboard
.layout
.height
*sizeof(wchar_t));
66 DEBUG("keyboard: Layout loaded: %s (width=%d; height=%d; shift=%s; altcap=%s)\n",filename
,keyboard
.layout
.width
,keyboard
.layout
.height
,keyboard
.layout
.has_shift
?"yes":"no",keyboard
.layout
.has_altcap
?"yes":"no");
71 DEBUG("keyboard: %s: %s\n",strerror(errno
),filename
);
76 /*static void keyboard_layout_unload() {
77 free(keyboard.layout.table);
78 memset(&keyboard.layout,0,sizeof(keyboard.layout));
81 static wchar_t scancode2wchr(int scancode
) {
82 if (keyboard
.layout
.table
==NULL
) return 0;
83 // find right column in table
85 if (keyboard
.shift
&& keyboard
.layout
.has_shift
) col
= 1;
86 else if (keyboard
.altcap
&& keyboard
.layout
.has_altcap
) col
= 2;
87 //if (col>=keyboard.layout.width) col = keyboard.layout.width-1;
88 // find right row in table
90 if (row
>=keyboard
.layout
.height
) row
= keyboard
.layout
.height
-1;
92 return keyboard
.layout
.table
[row
*keyboard
.layout
.width
+col
];
96 * Gets keys from keyboard and parses it to characters
97 * @param buffer Buffer for read chars
98 * @param count How many chars to read
99 * @param dev Device to read from
100 * @return How many bytes read
102 ssize_t
onread(devfs_dev_t
*dev
,void *buffer
,size_t count
,off_t offset
) {
103 return ringbuf_read(keyboard
.buffer
,buffer
,count
);
107 * Handles Keyboard IRQ
111 static void keyboard_irq(void *null
) {
112 int released
,scancode
;
114 while (inb(KEYBOARD_PORT_STATUS
)&1) {
116 scancode
= inb(KEYBOARD_PORT_DATA
);
117 if (scancode
!=0xE0) {
118 released
= scancode
&0x80;
122 // check for escaped key
123 if (keyboard
.escape
) {
127 if (scancode
==0xE0) {
132 // if shift is pressed/released
133 if (IS_SHIFT(scancode
)) keyboard
.shift
= !released
;
134 // if alternative capital is pressed/released
135 else if (IS_ALTCAP(scancode
)) keyboard
.altcap
= !released
;
137 // write key into buffer
138 else if (!released
) {
139 wchar_t chr
= scancode2wchr(scancode
);
140 if (chr
>0x7F) DEBUG("TODO: Wide characters (%s %d)\n",__FILE__
,__LINE__
);
142 //DEBUG("keyboard: Read character: '%c' (0x%02x)\n",chr,chr);
143 ringbuf_write(keyboard
.buffer
,&chr
,1);
150 * Initializes keyboard driver
151 * @return 0=success; -1=failure
153 int init_keyboard() {
154 if (ioport_reg(KEYBOARD_PORT_DATA
)==-1) return -1;
155 if (ioport_reg(KEYBOARD_PORT_STATUS
)==-1) return -1;
156 irq_reghandler(KEYBOARD_IRQ
,keyboard_irq
,NULL
,0);
158 memset(&keyboard
,0,sizeof(keyboard
));
159 keyboard
.buffer
= ringbuf_create(KEYBUF_SIZE
);
160 keyboard_layout_load(KEYBOARD_DEFAULT_LAYOUT
);