IBNOS
keyboard.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <hardware/keyboard.h>
29 #include <hardware/pic.h>
30 #include <interrupt/interrupt.h>
31 #include <process/object.h>
32 #include <console/console.h>
33 #include <util/util.h>
34 #include <io/io.h>
35 
44 uint32_t keyboardLEDFlags = 0;
48 uint8_t standardKeyCodes[128] =
49 {
50  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
51  20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
52  40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
53  60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
54  80, 81, 82, 84, 00, 00, 86, 87, 88, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
55  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
56  00, 00, 00, 00, 00, 00, 00, 00
57 };
58 
62 uint8_t extendedKeyCodes[128] =
63 {
64  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
65  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 96, 97, 00, 00,
66  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
67  00, 00, 00, 00, 00, 99, 00, 00, 100, 00, 00, 00, 00, 00, 00, 00,
68  00, 00, 00, 00, 00, 00, 00, 102, 103, 104, 00, 105, 00, 106, 00, 107,
69  108, 109, 110, 111, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
70  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
71  00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
72 };
73 
74 static struct object *keyboardStdin;
75 
76 int keyMapIndex = 0;
77 extern const struct keyMap keyMapDE;
78 
82 const struct keyMap *keyMaps =
83 {
84  &keyMapDE
85 };
86 
87 struct keyModifier modifiers = {0, 0, 0, 0, 0};
88 
100 void processScancode(int extended, uint8_t scanCode, bool keyUp)
101 {
102  uint8_t mappedCode = 0;
103  uint8_t charCode;
104  uint16_t *decodeMap = NULL;
105 
106  struct keyEvent keyEv;
107  keyEv.pressed = !keyUp;
108  keyEv.keyCode = 0;
109  keyEv.modifiers = modifiers;
110 
111  if (extended == 0)
112  mappedCode = standardKeyCodes[scanCode];
113  else if (extended == 1)
114  mappedCode = extendedKeyCodes[scanCode];
115 
116  if (!mappedCode)
117  return;
118 
119  /* TODO: solve this better ?*/
120  if (modifiers.shift || modifiers.shiftLocked)
121  {
122  if (modifiers.ctrl)
123  decodeMap = keyMaps[keyMapIndex].keyMaps.shift_ctrl_map;
124  else if(modifiers.alt)
125  decodeMap = keyMaps[keyMapIndex].keyMaps.shift_alt_map;
126  else
127  decodeMap = keyMaps[keyMapIndex].keyMaps.shift_map;
128  }
129  else if (modifiers.ctrl)
130  {
131  if(modifiers.altgr)
132  decodeMap = keyMaps[keyMapIndex].keyMaps.altgr_ctrl_map;
133  else
134  decodeMap = keyMaps[keyMapIndex].keyMaps.ctrl_map;
135  }
136  else if (modifiers.altgr)
137  {
138  if (modifiers.alt)
139  decodeMap = keyMaps[keyMapIndex].keyMaps.altgr_alt_map;
140  else
141  decodeMap = keyMaps[keyMapIndex].keyMaps.altgr_map;
142  }
143  else if (modifiers.alt)
144  {
145  decodeMap = keyMaps[keyMapIndex].keyMaps.alt_map;
146  }
147  else
148  {
149  decodeMap = keyMaps[keyMapIndex].keyMaps.plain_map;
150  }
151  keyEv.keyCode = decodeMap[mappedCode] & 0x0FFF;
152 
153  if (!keyEv.keyCode)
154  return;
155 
156  /* TODO: pass the keyEv struct to applications to allow reaction on raw input */
157 
158  /* set modifieres */
159  if (KEY_TYPE(keyEv.keyCode) == KEY_TYPE_SHIFT)
160  {
161  switch (KEY_VALUE(keyEv.keyCode))
162  {
163  case KEY_MODIFIER_SHIFT:
164  case KEY_MODIFIER_SHIFTL:
165  case KEY_MODIFIER_SHIFTR:
166  keyEv.modifiers.shift = keyEv.pressed;
167  break;
168 
169  case KEY_MODIFIER_CTRL:
170  case KEY_MODIFIER_CTRLL:
171  case KEY_MODIFIER_CTRLR:
172  keyEv.modifiers.ctrl = keyEv.pressed;
173  break;
174 
175  case KEY_MODIFIER_ALT:
176  keyEv.modifiers.alt = keyEv.pressed;
177  break;
178 
179  case KEY_MODIFIER_ALTGR:
180  keyEv.modifiers.altgr = keyEv.pressed;
181  break;
182 
183  default:
184  break;
185  }
186  }
187  else if (KEY_TYPE(keyEv.keyCode) == KEY_TYPE_SPEC)
188  {
189  if (keyEv.keyCode == KEY_CODE_CAPS && keyEv.pressed)
190  {
192  }
193  }
194 
195  modifiers = keyEv.modifiers;
196 
197  if (!keyEv.pressed)
198  return;
199 
200  if (KEY_TYPE(keyEv.keyCode) == KEY_TYPE_LATIN || KEY_TYPE(keyEv.keyCode) == KEY_TYPE_ASCII ||
201  KEY_TYPE(keyEv.keyCode) == KEY_TYPE_LETTER || keyEv.keyCode == KEY_CODE_ENTER)
202  {
203  if (keyEv.keyCode == KEY_CODE_ENTER)
204  charCode = '\n';
205  else
206  charCode = KEY_VALUE(keyEv.keyCode);
207 
208  consoleEchoChar(charCode);
209 
210  if (keyboardStdin)
211  __objectWrite(keyboardStdin, &charCode, sizeof(charCode));
212  }
213  return;
214 }
215 
216 static bool ext1Code = 0;
217 static int ext2Code = 0;
218 static uint16_t e1_prev = 0;
219 
229 static uint32_t keyboard_irq(UNUSED uint32_t irq)
230 {
231  uint8_t scanCode = 0;
232  bool keyUp = false;
233 
234  //while (inb(KEYBOARD_STATUS_PORT) & 0x1)
235  //{
236  scanCode = inb(KEYBOARD_BUFFER_PORT);
237 
238  /* check if this is a key up event */
239  if ((scanCode & 0x80) && (ext2Code || (scanCode != 0xE1)) && (ext1Code || (scanCode != 0xE0)))
240  {
241  scanCode &= ~0x80;
242  keyUp = true;
243  }
244 
245  if (ext1Code)
246  {
247  /* check for fake shifts */
248  if ((scanCode == 0x2A) || (scanCode == 0x36)) {
249  ext1Code = false;
251  }
252  processScancode(1, scanCode, keyUp);
253  ext1Code = false;
254  }
255  else if (ext2Code == 2)
256  {
257  e1_prev |= ((uint16_t) scanCode << 8);
258  processScancode(2, e1_prev, keyUp);
259  ext2Code = 0;
260  }
261  else if (ext2Code == 1)
262  {
263  e1_prev = scanCode;
264  ext2Code++;
265  }
266  else if (scanCode == 0xE0)
267  ext1Code = true;
268  else if (scanCode == 0xE1)
269  ext2Code = 1;
270  else
271  processScancode(0, scanCode, keyUp);
272  //}
273 
275 }
276 
282 void keyboardInit(struct object *obj)
283 {
284  keyboardStdin = obj;
285 
286  /* must be set as first to prevent race conditions when clearing the buffer */
287  picReserveIRQ(IRQ_KEYBOARD, keyboard_irq);
288 
289  /* clear buffer */
290  while (inb(KEYBOARD_STATUS_PORT) & 0x1)
292 
293  /* enable keyboard */
295 
296  /* Disable all LEDs */
298 }
299 
307 void keyboardSend(uint8_t cmd)
308 {
309  /* Wait till the command buffer is empty */
310  while ((inb(KEYBOARD_STATUS_PORT) & 0x2))
311  {
312  /* do nothing */
313  }
315 }
322 void keyboardSetLEDFlags(uint32_t flags)
323 {
324  keyboardLEDFlags = flags & 7;
327 }
328 
334 {
335  return keyboardLEDFlags;
336 }
#define KEY_MODIFIER_CTRLR
Definition: keyboard.h:46
uint8_t extendedKeyCodes[128]
Definition: keyboard.c:62
const struct keyMap * keyMaps
Supported keymaps.
Definition: keyboard.c:82
uint8_t standardKeyCodes[128]
Definition: keyboard.c:48
#define KEY_MODIFIER_ALT
Definition: keyboard.h:41
#define KEY_MODIFIER_CTRLL
Definition: keyboard.h:45
#define KEY_TYPE_SHIFT
Definition: keyboard.h:56
uint16_t * shift_alt_map
Definition: keyboard.h:528
#define IRQ_KEYBOARD
Definition: pic.h:66
void processScancode(int extended, uint8_t scanCode, bool keyUp)
Handles key presses after the scancode was decoded.
Definition: keyboard.c:100
const struct keyMap keyMapDE
Definition: keymap_de.c:380
#define UNUSED
Definition: util.h:39
#define KEY_TYPE_ASCII
Definition: keyboard.h:58
#define KEYBOARD_STATUS_PORT
Definition: keyboard.h:486
#define KEY_TYPE_SPEC
Definition: keyboard.h:51
void outb(uint16_t port, uint8_t val)
Definition: io.h:35
uint16_t * altgr_alt_map
Definition: keyboard.h:529
#define KEY_VALUE(x)
Definition: keyboard.h:36
#define KEY_MODIFIER_CTRL
Definition: keyboard.h:40
uint32_t keyboardLEDFlags
Definition: keyboard.c:44
uint8_t inb(uint16_t port)
Definition: io.h:50
bool picReserveIRQ(uint32_t irq, irq_callback callback)
Assign a callback function to an IRQ.
Definition: pic.c:151
Definition: object.h:69
uint32_t keyboardGetLEDFlags()
Return the current active LED flags.
Definition: keyboard.c:333
uint8_t shiftLocked
Definition: keyboard.h:456
uint16_t * altgr_ctrl_map
Definition: keyboard.h:527
void keyboardSetLEDFlags(uint32_t flags)
Set LED Flags.
Definition: keyboard.c:322
uint16_t * alt_map
Definition: keyboard.h:524
struct keyModifier modifiers
Definition: keyboard.c:87
#define KEYBOARD_CMD_ENABLE
Definition: keyboard.h:511
struct keyModifier modifiers
Definition: keyboard.h:465
uint16_t * shift_ctrl_map
Definition: keyboard.h:526
#define KEY_TYPE(x)
Definition: keyboard.h:35
#define KEYBOARD_BUFFER_PORT
Definition: keyboard.h:485
void keyboardInit(struct object *obj)
Initializes the keyboard.
Definition: keyboard.c:282
#define KEY_MODIFIER_SHIFTR
Definition: keyboard.h:44
uint16_t * altgr_map
Definition: keyboard.h:523
uint8_t altgr
Definition: keyboard.h:459
struct keyMapInfo keyMaps
Definition: keyboard.h:536
void keyboardSend(uint8_t cmd)
Send a command to the keyboard controller.
Definition: keyboard.c:307
#define KEY_TYPE_LETTER
Definition: keyboard.h:60
#define KEY_TYPE_LATIN
Definition: keyboard.h:49
#define KEY_MODIFIER_ALTGR
Definition: keyboard.h:39
#define KEYBOARD_CMD_LED
Definition: keyboard.h:506
uint8_t alt
Definition: keyboard.h:458
#define INTERRUPT_CONTINUE_EXECUTION
Definition: interrupt.h:48
uint8_t shift
Definition: keyboard.h:455
uint8_t ctrl
Definition: keyboard.h:457
bool pressed
Definition: keyboard.h:464
int keyMapIndex
Definition: keyboard.c:76
uint16_t * shift_map
Definition: keyboard.h:522
void consoleEchoChar(char chr)
Echo keyboard input on the console.
Definition: console.c:193
uint16_t * ctrl_map
Definition: keyboard.h:525
#define KEY_MODIFIER_SHIFT
Definition: keyboard.h:38
#define KEY_CODE_ENTER
Definition: keyboard.h:323
#define KEY_CODE_CAPS
Definition: keyboard.h:329
uint16_t keyCode
Definition: keyboard.h:466
#define KEY_MODIFIER_SHIFTL
Definition: keyboard.h:42
uint16_t * plain_map
Definition: keyboard.h:521