Serenity Operating System
at portability 625 lines 12 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 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" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/Assertions.h> 28#include <AK/ByteBuffer.h> 29#include <AK/Types.h> 30#include <Kernel/Arch/i386/CPU.h> 31#include <Kernel/Devices/KeyboardDevice.h> 32#include <Kernel/TTY/VirtualConsole.h> 33#include <LibBareMetal/IO.h> 34 35//#define KEYBOARD_DEBUG 36 37namespace Kernel { 38 39#define IRQ_KEYBOARD 1 40#define I8042_BUFFER 0x60 41#define I8042_STATUS 0x64 42#define I8042_ACK 0xFA 43#define I8042_BUFFER_FULL 0x01 44#define I8042_WHICH_BUFFER 0x20 45#define I8042_MOUSE_BUFFER 0x20 46#define I8042_KEYBOARD_BUFFER 0x00 47 48char* map; 49char* shift_map; 50char* alt_map; 51char* altgr_map; 52 53static const char en_map[0x80] = { 54 0, 55 '\033', 56 '1', 57 '2', 58 '3', 59 '4', 60 '5', 61 '6', 62 '7', 63 '8', 64 '9', 65 '0', 66 '-', 67 '=', 68 0x08, 69 '\t', 70 'q', 71 'w', 72 'e', 73 'r', 74 't', 75 'y', 76 'u', 77 'i', 78 'o', 79 'p', 80 '[', 81 ']', 82 '\n', 83 0, 84 'a', 85 's', 86 'd', 87 'f', 88 'g', 89 'h', 90 'j', 91 'k', 92 'l', 93 ';', 94 '\'', 95 '`', 96 0, 97 '\\', 98 'z', 99 'x', 100 'c', 101 'v', 102 'b', 103 'n', 104 'm', 105 ',', 106 '.', 107 '/', 108 0, 109 '*', 110 0, 111 ' ', 112 0, 113 0, 114 //60 115 0, 116 0, 117 0, 118 0, 119 0, 120 0, 121 0, 122 0, 123 0, 124 0, 125 //70 126 0, 127 0, 128 0, 129 0, 130 '-', 131 0, 132 0, 133 0, 134 '+', 135 0, 136 //80 137 0, 138 0, 139 0, 140 0, 141 0, 142 0, 143 '\\', 144 0, 145 0, 146 0, 147}; 148 149static const char en_shift_map[0x80] = { 150 0, 151 '\033', 152 '!', 153 '@', 154 '#', 155 '$', 156 '%', 157 '^', 158 '&', 159 '*', 160 '(', 161 ')', 162 '_', 163 '+', 164 0x08, 165 '\t', 166 'Q', 167 'W', 168 'E', 169 'R', 170 'T', 171 'Y', 172 'U', 173 'I', 174 'O', 175 'P', 176 '{', 177 '}', 178 '\n', 179 0, 180 'A', 181 'S', 182 'D', 183 'F', 184 'G', 185 'H', 186 'J', 187 'K', 188 'L', 189 ':', 190 '"', 191 '~', 192 0, 193 '|', 194 'Z', 195 'X', 196 'C', 197 'V', 198 'B', 199 'N', 200 'M', 201 '<', 202 '>', 203 '?', 204 0, 205 '*', 206 0, 207 ' ', 208 0, 209 0, 210 //60 211 0, 212 0, 213 0, 214 0, 215 0, 216 0, 217 0, 218 0, 219 0, 220 0, 221 //70 222 0, 223 0, 224 0, 225 0, 226 '-', 227 0, 228 0, 229 0, 230 '+', 231 0, 232 //80 233 0, 234 0, 235 0, 236 0, 237 0, 238 0, 239 '|', 240 0, 241 0, 242 0, 243}; 244 245static const char numpad_map[13] = { '7', '8', '9', 0, '4', '5', '6', 0, '1', '2', '3', '0', ',' }; 246 247static const KeyCode unshifted_key_map[0x80] = { 248 Key_Invalid, 249 Key_Escape, 250 Key_1, 251 Key_2, 252 Key_3, 253 Key_4, 254 Key_5, 255 Key_6, 256 Key_7, 257 Key_8, 258 Key_9, 259 Key_0, 260 Key_Minus, 261 Key_Equal, 262 Key_Backspace, 263 Key_Tab, //15 264 Key_Q, 265 Key_W, 266 Key_E, 267 Key_R, 268 Key_T, 269 Key_Y, 270 Key_U, 271 Key_I, 272 Key_O, 273 Key_P, 274 Key_LeftBracket, 275 Key_RightBracket, 276 Key_Return, // 28 277 Key_Control, // 29 278 Key_A, 279 Key_S, 280 Key_D, 281 Key_F, 282 Key_G, 283 Key_H, 284 Key_J, 285 Key_K, 286 Key_L, 287 Key_Semicolon, 288 Key_Apostrophe, 289 Key_Backtick, 290 Key_LeftShift, // 42 291 Key_Backslash, 292 Key_Z, 293 Key_X, 294 Key_C, 295 Key_V, 296 Key_B, 297 Key_N, 298 Key_M, 299 Key_Comma, 300 Key_Period, 301 Key_Slash, 302 Key_RightShift, // 54 303 Key_Asterisk, 304 Key_Alt, // 56 305 Key_Space, // 57 306 Key_CapsLock, // 58 307 Key_F1, 308 Key_F2, 309 Key_F3, 310 Key_F4, 311 Key_F5, 312 Key_F6, 313 Key_F7, 314 Key_F8, 315 Key_F9, 316 Key_F10, 317 Key_NumLock, 318 Key_Invalid, // 70 319 Key_Home, 320 Key_Up, 321 Key_PageUp, 322 Key_Minus, 323 Key_Left, 324 Key_Invalid, 325 Key_Right, // 77 326 Key_Plus, 327 Key_End, 328 Key_Down, // 80 329 Key_PageDown, 330 Key_Invalid, 331 Key_Delete, // 83 332 Key_Invalid, 333 Key_Invalid, 334 Key_Backslash, 335 Key_F11, 336 Key_F12, 337 Key_Invalid, 338 Key_Invalid, 339 Key_Logo, 340}; 341 342static const KeyCode shifted_key_map[0x100] = { 343 Key_Invalid, 344 Key_Escape, 345 Key_ExclamationPoint, 346 Key_AtSign, 347 Key_Hashtag, 348 Key_Dollar, 349 Key_Percent, 350 Key_Circumflex, 351 Key_Ampersand, 352 Key_Asterisk, 353 Key_LeftParen, 354 Key_RightParen, 355 Key_Underscore, 356 Key_Plus, 357 Key_Backspace, 358 Key_Tab, 359 Key_Q, 360 Key_W, 361 Key_E, 362 Key_R, 363 Key_T, 364 Key_Y, 365 Key_U, 366 Key_I, 367 Key_O, 368 Key_P, 369 Key_LeftBrace, 370 Key_RightBrace, 371 Key_Return, 372 Key_Control, 373 Key_A, 374 Key_S, 375 Key_D, 376 Key_F, 377 Key_G, 378 Key_H, 379 Key_J, 380 Key_K, 381 Key_L, 382 Key_Colon, 383 Key_DoubleQuote, 384 Key_Tilde, 385 Key_LeftShift, // 42 386 Key_Pipe, 387 Key_Z, 388 Key_X, 389 Key_C, 390 Key_V, 391 Key_B, 392 Key_N, 393 Key_M, 394 Key_LessThan, 395 Key_GreaterThan, 396 Key_QuestionMark, 397 Key_RightShift, // 54 398 Key_Asterisk, 399 Key_Alt, 400 Key_Space, // 57 401 Key_CapsLock, // 58 402 Key_F1, 403 Key_F2, 404 Key_F3, 405 Key_F4, 406 Key_F5, 407 Key_F6, 408 Key_F7, 409 Key_F8, 410 Key_F9, 411 Key_F10, 412 Key_NumLock, 413 Key_Invalid, // 70 414 Key_Home, 415 Key_Up, 416 Key_PageUp, 417 Key_Minus, 418 Key_Left, 419 Key_Invalid, 420 Key_Right, // 77 421 Key_Plus, 422 Key_End, 423 Key_Down, // 80 424 Key_PageDown, 425 Key_Invalid, 426 Key_Delete, // 83 427 Key_Invalid, 428 Key_Invalid, 429 Key_Pipe, 430 Key_F11, 431 Key_F12, 432 Key_Invalid, 433 Key_Invalid, 434 Key_Logo, 435}; 436 437static const KeyCode numpad_key_map[13] = { Key_7, Key_8, Key_9, Key_Invalid, Key_4, Key_5, Key_6, Key_Invalid, Key_1, Key_2, Key_3, Key_0, Key_Comma }; 438 439void KeyboardDevice::key_state_changed(u8 raw, bool pressed) 440{ 441 KeyCode key = (m_modifiers & Mod_Shift) ? shifted_key_map[raw] : unshifted_key_map[raw]; 442 char character = (m_modifiers & Mod_Shift) ? shift_map[raw] : (m_modifiers & Mod_Alt) ? alt_map[raw] : (m_modifiers & Mod_AltGr) ? altgr_map[raw] : map[raw]; 443 444 if (key == Key_NumLock && pressed) 445 m_num_lock_on = !m_num_lock_on; 446 447 if (m_num_lock_on && !m_has_e0_prefix) { 448 if (raw >= 0x47 && raw <= 0x53) { 449 u8 index = raw - 0x47; 450 KeyCode newKey = numpad_key_map[index]; 451 452 if (newKey != Key_Invalid) { 453 key = newKey; 454 character = numpad_map[index]; 455 } 456 } 457 } else { 458 if (m_has_e0_prefix) { 459 if (key == Key_Slash) { 460 character = '/'; // On Turkish-QWERTY Keyboard Key_Slash mapped to '.' char, if e0 prefix is true remap to '/' char 461 } 462 } 463 } 464 465 if (key == Key_CapsLock && pressed) 466 m_caps_lock_on = !m_caps_lock_on; 467 468 if (m_caps_lock_on && (m_modifiers == 0 || m_modifiers == Mod_Shift)) { 469 if (character >= 'a' && character <= 'z') 470 character &= ~0x20; 471 else if (character >= 'A' && character <= 'Z') 472 character |= 0x20; 473 } 474 475 Event event; 476 event.key = key; 477 event.character = static_cast<u8>(character); 478 event.flags = m_modifiers; 479 if (pressed) 480 event.flags |= Is_Press; 481 if (m_client) 482 m_client->on_key_pressed(event); 483 m_queue.enqueue(event); 484 485 m_has_e0_prefix = false; 486} 487 488void KeyboardDevice::handle_irq(RegisterState&) 489{ 490 for (;;) { 491 u8 status = IO::in8(I8042_STATUS); 492 if (!(((status & I8042_WHICH_BUFFER) == I8042_KEYBOARD_BUFFER) && (status & I8042_BUFFER_FULL))) 493 return; 494 u8 raw = IO::in8(I8042_BUFFER); 495 u8 ch = raw & 0x7f; 496 bool pressed = !(raw & 0x80); 497 498 if (raw == 0xe0) { 499 m_has_e0_prefix = true; 500 return; 501 } 502 503#ifdef KEYBOARD_DEBUG 504 dbgprintf("Keyboard::handle_irq: %b %s\n", ch, pressed ? "down" : "up"); 505#endif 506 switch (ch) { 507 case 0x38: 508 if (m_has_e0_prefix) 509 update_modifier(Mod_AltGr, pressed); 510 else 511 update_modifier(Mod_Alt, pressed); 512 break; 513 case 0x1d: 514 update_modifier(Mod_Ctrl, pressed); 515 break; 516 case 0x5b: 517 update_modifier(Mod_Logo, pressed); 518 break; 519 case 0x2a: 520 case 0x36: 521 update_modifier(Mod_Shift, pressed); 522 break; 523 } 524 switch (ch) { 525 case I8042_ACK: 526 break; 527 default: 528 if (m_modifiers & Mod_Alt) { 529 switch (map[ch]) { 530 case '1': 531 case '2': 532 case '3': 533 case '4': 534 VirtualConsole::switch_to(map[ch] - '0' - 1); 535 break; 536 default: 537 key_state_changed(ch, pressed); 538 break; 539 } 540 } else { 541 key_state_changed(ch, pressed); 542 } 543 } 544 } 545} 546 547static KeyboardDevice* s_the; 548 549KeyboardDevice& KeyboardDevice::the() 550{ 551 ASSERT(s_the); 552 return *s_the; 553} 554 555KeyboardDevice::KeyboardDevice() 556 : IRQHandler(IRQ_KEYBOARD) 557 , CharacterDevice(85, 1) 558{ 559 s_the = this; 560 561 KeyboardDevice::set_maps(en_map, en_shift_map, en_map, en_map); 562 563 // Empty the buffer of any pending data. 564 // I don't care what you've been pressing until now! 565 while (IO::in8(I8042_STATUS) & I8042_BUFFER_FULL) 566 IO::in8(I8042_BUFFER); 567 568 enable_irq(); 569} 570 571KeyboardDevice::~KeyboardDevice() 572{ 573} 574 575bool KeyboardDevice::can_read(const FileDescription&) const 576{ 577 return !m_queue.is_empty(); 578} 579 580ssize_t KeyboardDevice::read(FileDescription&, u8* buffer, ssize_t size) 581{ 582 ssize_t nread = 0; 583 while (nread < size) { 584 if (m_queue.is_empty()) 585 break; 586 // Don't return partial data frames. 587 if ((size - nread) < (ssize_t)sizeof(Event)) 588 break; 589 auto event = m_queue.dequeue(); 590 memcpy(buffer, &event, sizeof(Event)); 591 nread += sizeof(Event); 592 } 593 return nread; 594} 595 596ssize_t KeyboardDevice::write(FileDescription&, const u8*, ssize_t) 597{ 598 return 0; 599} 600 601KeyboardClient::~KeyboardClient() 602{ 603} 604 605void KeyboardDevice::set_maps(const char* n_map, const char* n_shift_map, const char* n_alt_map, const char* n_altgr_map) 606{ 607 kfree(map); 608 kfree(shift_map); 609 kfree(alt_map); 610 kfree(altgr_map); 611 612 map = (char*)kmalloc(0x80); 613 shift_map = (char*)kmalloc(0x80); 614 alt_map = (char*)kmalloc(0x80); 615 altgr_map = (char*)kmalloc(0x80); 616 617 for (int i = 0; i < 0x80; i++) { 618 map[i] = n_map[i]; 619 shift_map[i] = n_shift_map[i]; 620 alt_map[i] = n_alt_map[i]; 621 altgr_map[i] = n_altgr_map[i]; 622 } 623} 624 625}