Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / drivers / char / kbd / kbd.c
blob4209b88e100fc34ac4068201969c7d9dde3583ef
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <build.h>
23 #include <system.h>
24 #include <arch/io.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <config.h>
28 #include <console.h>
29 #include <proc.h>
30 #include "kbd.h"
33 unsigned char scancode = 0;
34 unsigned modes = 0;
35 bool upped = 0;
37 kbd_quaue kbd_q;
39 char kbdmap[3];
41 #ifndef ARCH_i386
42 void keyboard_handler ();
43 #endif
45 unsigned keyboard_setlayout (char *layout)
47 if (!strcmp (layout, "us")) {
48 kbd_layout[0] = (unsigned char *) &kbdus;
49 kbd_layout[1] = (unsigned char *) &kbdus_shift;
51 strcpy (kbdmap, "us");
53 return 1;
56 if (!strcmp (layout, "cz")) {
57 kbd_layout[0] = (unsigned char *) &kbdcz;
58 kbd_layout[1] = (unsigned char *) &kbdcz_shift;
60 strcpy (kbdmap, "cz");
62 return 1;
65 return 0;
68 unsigned keyboard_getlayout (char *layout)
70 if (!strcmp (kbdmap, layout))
71 return 1;
73 return 0;
76 char getkey ()
78 #ifdef ARCH_arm
79 char k = rs232_read ();
81 if (!k)
82 return 0;
84 if ((k >= '0' && k <= '9') || (k >= 'A' && k <= 'Z') || (k >= 'a' && k <= 'z')) {
85 kbd_q.key[0] = k;
86 kbd_q.p = 1;
87 } else if (k == 13) {
88 kbd_q.key[0] = '\n';
89 kbd_q.p = 1;
90 } else if (k == 32) {
91 kbd_q.key[0] = ' ';
92 kbd_q.p = 1;
93 } else if (k == 127) {
94 kbd_q.key[0] = '\b';
95 kbd_q.p = 1;
98 keyboard_handler ();
99 #endif
100 char s[KBD_MAX_QUAUE];
102 if (!kbd_q.p)
103 return 0;
105 char key = kbd_q.key[0];
107 kbd_q.p --;
109 memcpy (s, kbd_q.key+1, kbd_q.p);
111 memcpy (kbd_q.key, s, kbd_q.p);
113 return key;
116 void setkey (char key)
118 char s[KBD_MAX_QUAUE];
120 if (kbd_q.p >= KBD_MAX_QUAUE)
121 return;
123 kbd_q.p ++;
125 memcpy (s+1, kbd_q.key, kbd_q.p);
127 s[0] = key;
129 memcpy (kbd_q.key, s, kbd_q.p);
132 unsigned key_pressed (int keycode)
134 if (scancode == keycode)
135 return 1;
137 if (scancode == keycode+128)
138 return 2;
139 else
140 return 0;
143 #ifdef ARCH_i386
144 void keyboard_handler (struct regs *r)
145 #endif
146 #ifdef ARCH_arm
147 void keyboard_handler ()
148 #endif
150 int i, setsignal = 0;
152 /* Read from the keyboard's data buffer */
153 #ifdef ARCH_i386
154 scancode = inb (0x60);
156 outb (0x20, 0x20);
157 #endif
158 #ifdef ARCH_arm
159 if (!armbd_kbd_data ())
160 return;
162 scancode = armbd_kbd_scancode ();
164 armbd_kbd_ack ();
165 #endif
166 /* If the top bit of the byte we read from the keyboard is
167 * set, that means that a key has just been released */
168 if (scancode & 0x80) {
169 /* If the user released the shift, alt, or control keys... */
170 //DPRINT ("key up: %d", scancode);
172 //kbd_q.state[0] = 2; // up
174 if (key_pressed (CTRL) == 2)
175 modes &= ~0x1;
176 if (key_pressed (ALT) == 2)
177 modes &= ~0x2;
178 if (key_pressed (DEL) == 2)
179 modes &= ~0x4;
180 if (key_pressed (SHIFTL) == 2 || key_pressed (SHIFTR) == 2)
181 modes &= ~0x8;
182 } else {
184 /* Here, a key was just pressed. Please note that if you
185 * hold a key down, you will get repeated key press
186 * interrupts. */
188 /* Just to show you how this works, we simply translate
189 * the keyboard scancode into an ASCII value, and then
190 * display it to the screen. You can get creative and
191 * use some flags to see if a shift is pressed and use a
192 * different layout, or you can add another 128 entries
193 * to the above layout to correspond to 'shift' being
194 * held. If shift is held using the larger lookup table,
195 * you would add 128 to the scancode when you look for it */
197 //DPRINT ("key down: %d", scancode);
199 /* CTRL+ALT+DEL - magic keys */
200 if (key_pressed (CTRL))
201 modes |= 0x1;
202 if (key_pressed (ALT))
203 modes |= 0x2;
204 if (key_pressed (DEL))
205 modes |= 0x4;
207 /* big letters */
208 if (key_pressed (SHIFTL) || key_pressed (SHIFTR))
209 modes |= 0x8;
211 /* TTY changing - alt+F1-F4*/
212 if (modes & 0x2) {
213 if (key_pressed (F1))
214 tty_change ((tty_t *) tty_find ("tty0"));
215 else if (key_pressed (F2))
216 tty_change ((tty_t *) tty_find ("tty1"));
217 else if (key_pressed (F3))
218 tty_change ((tty_t *) tty_find ("tty2"));
219 else if (key_pressed (F4))
220 tty_change ((tty_t *) tty_find ("tty3"));
221 else if (key_pressed (PAGEUP))
222 tty_switch ('+');
223 else if (key_pressed (PAGEDOWN))
224 tty_switch ('-');
227 if (key_pressed (ARROWUP))
228 consolelog_prev ();
229 if (key_pressed (ARROWDOWN))
230 consolelog_next ();
232 /* reboot pc, when are pressed ctrl+alt+del */
233 if (modes & 0x1 && modes & 0x2) {
234 if (modes & 0x4) {
235 kprintf ("\nRebooting ..");
237 arch_cpu_reset ();
238 while (1);
242 /* CTRL + C - sigterm */
243 if (modes & 0x1) {
244 if (key_pressed (KB_C)) {
245 setsignal = 1;
246 scancode = 0;
250 /* SHIFT - BIG LETTERS */
251 if (modes & 0x8)
252 setkey (kbd_layout[1][scancode]);
253 else
254 setkey (kbd_layout[0][scancode]);
258 /* CTRL + C was pressed - send sigterm to app */
259 if (setsignal) {
260 if (!signal (SIGTERM, (sighandler_t) SIG_IGN))
261 DPRINT (DBG_DRIVER, "signal () - error\n");
265 unsigned int init_keyboard ()
267 #ifdef CONFIG_DRV_KEYBOARD
268 /* set default kbd layout - US */
269 kbd_layout[0] = (unsigned char *) &kbdus;
270 kbd_layout[1] = (unsigned char *) &kbdus_shift;
272 strcpy (kbdmap, CONFIG_UI_KBD_LAYOUT);
274 if (!strcmp (kbdmap, "us")) {
275 keyboard_setlayout ("us");
277 kprintf ("Loaded en_US keyboard layout\n");
280 if (!strcmp (kbdmap, "cz")) {
281 keyboard_setlayout ("cz");
283 kprintf ("Loaded cs_CZ keyboard layout\n");
286 int i;
287 for (i = 0; i < 20; i ++)
288 currtty->shell[i] = '\0';
290 for (i = 0; i < KBD_MAX_QUAUE; i ++)
291 kbd_q.key[i] = '\0';
293 kbd_q.p = 0;
295 #ifdef ARCH_i386
296 irq_install_handler (1, keyboard_handler);
297 #endif
298 #ifdef ARCH_arm
299 armbd_kbd_init ();
300 #endif
301 #endif
302 return 1;