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