001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/types.h>
020 #include <sos/errno.h>
021 #include <sos/assert.h>
022 #include <hwcore/irq.h>
023 #include <hwcore/ioports.h>
024
025 #include "tty.h"
026
027
028
029
030
031
032
033
034 #define KBD_DATA_PORT 0x60
035
036 #define KBD_BREAKCODE_LIMIT 0x80
037 #define KBD_EXTENDED_SCANCODE 0xE0
038
039 #define KBD_IS_MAKECODE(c) ((c) < KBD_BREAKCODE_LIMIT)
040 #define KBD_IS_BREAKCODE(c) ((c) >= KBD_BREAKCODE_LIMIT)
041 #define KBD_BREAKCODE_2_MAKECODE(c) ((c) ^ KBD_BREAKCODE_LIMIT)
042
043 #define KBD_LEFTSHIFT_SCANCODE 0x2a
044 #define KBD_RIGHTSHIFT_SCANCODE 0x36
045
046 typedef sos_ui8_t scancode_t;
047
048 extern const char *kbd_regular_translate_table [];
049 extern const char *kbd_shift_translate_table [];
050
051 static const char **kbd_current_translate_table = kbd_regular_translate_table;
052 static int is_ext = FALSE;
053
054 static struct tty_device *tty;
055
056 static void kbd_irq_handler (int irq_level)
057 {
058 scancode_t scancode;
059 const char *key = NULL;
060
061 scancode = inb (KBD_DATA_PORT);
062
063
064 if (scancode == KBD_EXTENDED_SCANCODE)
065 {
066 is_ext = TRUE;
067 }
068
069
070 else if (is_ext)
071 {
072 is_ext = FALSE;
073 }
074
075
076 else
077 {
078
079 if (KBD_IS_MAKECODE(scancode))
080 {
081
082 if ((scancode == KBD_LEFTSHIFT_SCANCODE) ||
083 (scancode == KBD_RIGHTSHIFT_SCANCODE))
084 kbd_current_translate_table = kbd_shift_translate_table;
085
086
087
088 else if (kbd_current_translate_table[scancode])
089 {
090 key = kbd_current_translate_table[scancode];
091 }
092 }
093
094
095 else
096 {
097 scancode_t makecode = KBD_BREAKCODE_2_MAKECODE(scancode);
098
099 if ((makecode == KBD_LEFTSHIFT_SCANCODE) ||
100 (makecode == KBD_RIGHTSHIFT_SCANCODE))
101 kbd_current_translate_table = kbd_regular_translate_table;
102 }
103 }
104
105 if (key)
106 tty_add_chars (tty, key);
107 }
108
109
110 sos_ret_t sos_kbd_subsystem_setup(struct tty_device *t)
111 {
112 tty = t;
113
114 sos_irq_set_routine (SOS_IRQ_KEYBOARD, kbd_irq_handler);
115
116 return SOS_OK;
117 }
118