1 /* 2 * Copyright 2004-2006, Jérôme Duval. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "KeyboardInputDevice.h" 8 #include "kb_mouse_driver.h" 9 10 #include <Application.h> 11 #include <Autolock.h> 12 #include <Directory.h> 13 #include <Entry.h> 14 #include <NodeMonitor.h> 15 #include <Path.h> 16 #include <String.h> 17 18 #include <errno.h> 19 #include <new> 20 #include <stdlib.h> 21 #include <unistd.h> 22 23 24 #if DEBUG 25 FILE *KeyboardInputDevice::sLogFile = NULL; 26 #endif 27 28 const static uint32 kKeyboardThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4; 29 const static char *kKeyboardDevicesDirectory = "/dev/input/keyboard"; 30 31 // "/dev/" is automatically prepended by StartMonitoringDevice() 32 const static char *kKeyboardDevicesDirectoryPS2 = "input/keyboard/at"; 33 const static char *kKeyboardDevicesDirectoryUSB = "input/keyboard/usb"; 34 35 const static uint32 kATKeycodeMap[] = { 36 0x1, // Esc 37 0x12, // 1 38 0x13, // 2 39 0x14, // 3 40 0x15, // 4 41 0x16, // 5 42 0x17, // 6 43 0x18, // 7 44 0x19, // 8 45 0x1a, // 9 46 0x1b, // 0 47 0x1c, // - 48 0x1d, // = 49 0x1e, // BACKSPACE 50 0x26, // TAB 51 0x27, // Q 52 0x28, // W 53 0x29, // E 54 0x2a, // R 55 0x2b, // T 56 0x2c, // Y 57 0x2d, // U 58 0x2e, // I 59 0x2f, // O 60 0x30, // P 61 0x31, // [ 62 0x32, // ] 63 0x47, // ENTER 64 0x5c, // Left Control 65 0x3c, // A 66 0x3d, // S 67 0x3e, // D 68 0x3f, // F 69 0x40, // G 70 0x41, // H 71 0x42, // J 72 0x43, // K 73 0x44, // L 74 0x45, // ; 75 0x46, // ' 76 0x11, // ` 77 0x4b, // Left Shift 78 0x33, // \ (backslash -- note: don't remove non-white-space after BS char) 79 0x4c, // Z 80 0x4d, // X 81 0x4e, // C 82 0x4f, // V 83 0x50, // B 84 0x51, // N 85 0x52, // M 86 0x53, // , 87 0x54, // . 88 0x55, // / 89 0x56, // Right Shift 90 0x24, // * 91 0x5d, // Left Alt 92 0x5e, // Space 93 0x3b, // Caps 94 0x02, // F1 95 0x03, // F2 96 0x04, // F3 97 0x05, // F4 98 0x06, // F5 99 0x07, // F6 100 0x08, // F7 101 0x09, // F8 102 0x0a, // F9 103 0x0b, // F10 104 0x22, // Num 105 0x0f, // Scroll 106 0x37, // KP 7 107 0x38, // KP 8 108 0x39, // KP 9 109 0x25, // KP - 110 0x48, // KP 4 111 0x49, // KP 5 112 0x4a, // KP 6 113 0x3a, // KP + 114 0x58, // KP 1 115 0x59, // KP 2 116 0x5a, // KP 3 117 0x64, // KP 0 118 0x65, // KP . 119 0x00, // UNMAPPED 120 0x00, // UNMAPPED 121 0x69, // < 122 0x0c, // F11 123 0x0d, // F12 124 0x00, // UNMAPPED 125 0x00, // UNMAPPED 90 126 0x00, // UNMAPPED 127 0x00, // UNMAPPED 128 0x00, // UNMAPPED 129 0x00, // UNMAPPED 130 0x00, // UNMAPPED 131 0x00, // UNMAPPED 132 0x00, // UNMAPPED 133 0x00, // UNMAPPED 134 0x00, // UNMAPPED 135 0x00, // UNMAPPED 100 136 0x00, // UNMAPPED 137 0x00, // UNMAPPED 138 0x00, // UNMAPPED 139 0x00, // UNMAPPED 140 0x00, // UNMAPPED 141 0x00, // UNMAPPED 142 0x00, // UNMAPPED 143 0x00, // UNMAPPED 144 0x00, // UNMAPPED 145 0x00, // UNMAPPED 110 146 0x00, // UNMAPPED 147 0x6e, // Katakana/Hiragana, second key right to spacebar, japanese 148 0x00, // UNMAPPED 149 0x00, // UNMAPPED 150 0x6b, // Ro (\\ key, japanese) 151 0x00, // UNMAPPED 152 0x00, // UNMAPPED 153 0x00, // UNMAPPED 154 0x00, // UNMAPPED 155 0x00, // UNMAPPED 120 156 0x6d, // Henkan, first key right to spacebar, japanese 157 0x00, // UNMAPPED 158 0x6c, // Muhenkan, key left to spacebar, japanese 159 0x00, // UNMAPPED 160 0x6a, // Yen (macron key, japanese) 161 0x70, // Keypad . on Brazilian ABNT2 162 0x00, // UNMAPPED 163 0x00, // UNMAPPED 164 0x00, // UNMAPPED 165 0x00, // UNMAPPED 130 166 0x00, // UNMAPPED 167 0x00, // UNMAPPED 168 0x00, // UNMAPPED 169 0x00, // UNMAPPED 170 0x00, // UNMAPPED 171 0x00, // UNMAPPED 172 0x00, // UNMAPPED 173 0x00, // UNMAPPED 174 0x00, // UNMAPPED 175 0x00, // UNMAPPED 140 176 0x00, // UNMAPPED 177 0x00, // UNMAPPED 178 0x00, // UNMAPPED 179 0x00, // UNMAPPED 180 0x00, // UNMAPPED 181 0x00, // UNMAPPED 182 0x00, // UNMAPPED 183 0x00, // UNMAPPED 184 0x00, // UNMAPPED 185 0x00, // UNMAPPED 150 186 0x00, // UNMAPPED 187 0x00, // UNMAPPED 188 0x00, // UNMAPPED 189 0x00, // UNMAPPED 190 0x00, // UNMAPPED 191 0x5b, // KP Enter 192 0x60, // Right Control 193 0x00, // UNMAPPED 194 0x00, // UNMAPPED 195 0x00, // UNMAPPED 160 196 0x00, // UNMAPPED 197 0x00, // UNMAPPED 198 0x00, // UNMAPPED 199 0x00, // UNMAPPED 200 0x00, // UNMAPPED 201 0x00, // UNMAPPED 202 0x00, // UNMAPPED 203 0x00, // UNMAPPED 204 0x00, // UNMAPPED 205 0x00, // UNMAPPED 170 206 0x00, // UNMAPPED 207 0x00, // UNMAPPED 208 0x00, // UNMAPPED 209 0x00, // UNMAPPED 210 0x00, // UNMAPPED 211 0x00, // UNMAPPED 212 0x00, // UNMAPPED 213 0x00, // UNMAPPED 214 0x00, // UNMAPPED 215 0x00, // UNMAPPED 180 216 0x23, // KP / 217 0x00, // UNMAPPED 218 0x0e, // Print Screen 219 0x5f, // Right Alt 220 0x00, // UNMAPPED 221 0x00, // UNMAPPED 222 0x00, // UNMAPPED 223 0x00, // UNMAPPED 224 0x00, // UNMAPPED 225 0x00, // UNMAPPED 190 226 0x00, // UNMAPPED 227 0x00, // UNMAPPED 228 0x00, // UNMAPPED 229 0x00, // UNMAPPED 230 0x00, // UNMAPPED 231 0x00, // UNMAPPED 232 0x00, // UNMAPPED 233 0x7f, // Break 234 0x20, // Home 235 0x57, // Up Arrow 200 236 0x21, // Page Up 237 0x00, // UNMAPPED 238 0x61, // Left Arrow 239 0x00, // UNMAPPED 240 0x63, // Right Arrow 241 0x00, // UNMAPPED 242 0x35, // End 243 0x62, // Down Arrow 244 0x36, // Page Down 245 0x1f, // Insert 200 246 0x34, // Delete 247 0x00, // UNMAPPED 248 0x00, // UNMAPPED 249 0x00, // UNMAPPED 250 0x00, // UNMAPPED 251 0x00, // UNMAPPED 252 0x00, // UNMAPPED 253 0x00, // UNMAPPED 254 0x66, // Left Gui 255 0x67, // Right Gui 210 256 0x68, // Menu 257 0x00, // UNMAPPED 258 0x00, // UNMAPPED 259 0x00, // UNMAPPED 260 0x00, // UNMAPPED 261 0x00, // UNMAPPED 262 0x00, // UNMAPPED 263 0x00, // UNMAPPED 264 0x00, // UNMAPPED 265 0x00, // UNMAPPED 220 266 0x00, // UNMAPPED 267 0x00, // UNMAPPED 268 0x00, // UNMAPPED 269 0x00, // UNMAPPED 270 0x00, // UNMAPPED 271 0x00, // UNMAPPED 272 0x00, // UNMAPPED 273 0x00, // UNMAPPED 274 0x00, // UNMAPPED 275 0x00, // UNMAPPED 276 0x00, // UNMAPPED 277 0x00, // UNMAPPED 278 0x00, // UNMAPPED 279 0x00, // UNMAPPED 280 0x00, // UNMAPPED 281 0x00, // UNMAPPED 282 0x00, // UNMAPPED 283 0x00, // UNMAPPED 284 0x00, // UNMAPPED 285 0x00, // UNMAPPED 286 0x00, // UNMAPPED 287 0x00, // UNMAPPED 288 0x00, // UNMAPPED 289 0x00, // UNMAPPED 290 0x00, // UNMAPPED 291 0x00, // UNMAPPED 292 0x00, // UNMAPPED 293 0x00, // UNMAPPED 294 0x00, // UNMAPPED 295 0x00, // UNMAPPED 296 0x00, // UNMAPPED 297 0x00, // UNMAPPED 298 0x00, // UNMAPPED 299 0x00, // UNMAPPED 300 0x00, // UNMAPPED 301 0x00, // UNMAPPED 302 0x00, // UNMAPPED 303 0x00, // UNMAPPED 304 0x00, // UNMAPPED 305 0x00, // UNMAPPED 306 0x00, // UNMAPPED 307 0x00, // UNMAPPED 308 0x00, // UNMAPPED 309 0x00, // UNMAPPED 310 0x00, // UNMAPPED 311 0x00, // UNMAPPED 312 0x00, // UNMAPPED 313 0x00, // UNMAPPED 314 0x00, // UNMAPPED 315 0x00, // UNMAPPED 316 0x00, // UNMAPPED 317 0x00, // UNMAPPED 318 0x00, // UNMAPPED 319 0x00, // UNMAPPED 320 0x00, // UNMAPPED 321 0x00, // UNMAPPED 322 0x00, // UNMAPPED 323 0x00, // UNMAPPED 324 0x00, // UNMAPPED 325 0x00, // UNMAPPED 326 327 }; 328 329 330 extern "C" 331 BInputServerDevice * 332 instantiate_input_device() 333 { 334 return new (std::nothrow) KeyboardInputDevice(); 335 } 336 337 338 static char * 339 get_short_name(const char *longName) 340 { 341 CALLED(); 342 BString string(longName); 343 BString name; 344 345 int32 slash = string.FindLast("/"); 346 string.CopyInto(name, slash + 1, string.Length() - slash); 347 int32 index = atoi(name.String()) + 1; 348 349 int32 previousSlash = string.FindLast("/", slash); 350 string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1); 351 352 // some special handling so that we get "USB" and "AT" instead of "usb"/"at" 353 if (name.Length() < 4) 354 name.ToUpper(); 355 else 356 name.Capitalize(); 357 358 name << " Keyboard " << index; 359 360 return strdup(name.String()); 361 } 362 363 364 // #pragma mark - 365 366 367 KeyboardInputDevice::KeyboardInputDevice() 368 : 369 fTMWindow(NULL), 370 fKeymapLock("keymap lock") 371 { 372 #if DEBUG 373 if (sLogFile == NULL) 374 sLogFile = fopen("/var/log/keyboard_device_log.log", "a"); 375 #endif 376 CALLED(); 377 } 378 379 380 KeyboardInputDevice::~KeyboardInputDevice() 381 { 382 CALLED(); 383 StopMonitoringDevice(kKeyboardDevicesDirectoryUSB); 384 StopMonitoringDevice(kKeyboardDevicesDirectoryPS2); 385 386 int count = fDevices.CountItems(); 387 while (count-- > 0) { 388 delete (keyboard_device *)fDevices.RemoveItem((int32)0); 389 } 390 391 #if DEBUG 392 fclose(sLogFile); 393 #endif 394 } 395 396 397 status_t 398 KeyboardInputDevice::SystemShuttingDown() 399 { 400 CALLED(); 401 if (fTMWindow) 402 fTMWindow->PostMessage(SYSTEM_SHUTTING_DOWN); 403 404 return B_OK; 405 } 406 407 408 status_t 409 KeyboardInputDevice::_InitFromSettings(void *cookie, uint32 opcode) 410 { 411 CALLED(); 412 413 keyboard_device *device = (keyboard_device *)cookie; 414 415 if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) { 416 if (get_key_repeat_rate(&device->settings.key_repeat_rate) != B_OK) 417 LOG_ERR("error when get_key_repeat_rate\n"); 418 else if (ioctl(device->fd, KB_SET_KEY_REPEAT_RATE, 419 &device->settings.key_repeat_rate) != B_OK) 420 LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", device->fd); 421 } 422 423 if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) { 424 if (get_key_repeat_delay(&device->settings.key_repeat_delay) != B_OK) 425 LOG_ERR("error when get_key_repeat_delay\n"); 426 else if (ioctl(device->fd, KB_SET_KEY_REPEAT_DELAY, 427 &device->settings.key_repeat_delay) != B_OK) 428 LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", device->fd); 429 } 430 431 if (opcode == 0 432 || opcode == B_KEY_MAP_CHANGED 433 || opcode == B_KEY_LOCKS_CHANGED) { 434 BAutolock lock(fKeymapLock); 435 fKeymap.LoadCurrent(); 436 device->modifiers = fKeymap.Locks(); 437 _SetLeds(device); 438 } 439 440 return B_OK; 441 } 442 443 444 status_t 445 KeyboardInputDevice::InitCheck() 446 { 447 CALLED(); 448 // TODO: this doesn't belong here! 449 _RecursiveScan(kKeyboardDevicesDirectory); 450 451 StartMonitoringDevice(kKeyboardDevicesDirectoryPS2); 452 StartMonitoringDevice(kKeyboardDevicesDirectoryUSB); 453 454 return B_OK; 455 } 456 457 458 status_t 459 KeyboardInputDevice::Start(const char *name, void *cookie) 460 { 461 CALLED(); 462 keyboard_device *device = (keyboard_device *)cookie; 463 464 if ((device->fd = open(device->path, O_RDWR)) < B_OK) { 465 fprintf(stderr, "error when opening %s: %s\n", device->path, strerror(errno)); 466 return B_ERROR; 467 } 468 469 _InitFromSettings(device); 470 471 char threadName[B_OS_NAME_LENGTH]; 472 snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name); 473 474 device->active = true; 475 device->device_watcher = spawn_thread(_DeviceWatcher, threadName, 476 kKeyboardThreadPriority, device); 477 if (device->device_watcher < B_OK) 478 return device->device_watcher; 479 480 resume_thread(device->device_watcher); 481 return B_OK; 482 } 483 484 485 status_t 486 KeyboardInputDevice::Stop(const char *name, void *cookie) 487 { 488 CALLED(); 489 keyboard_device *device = (keyboard_device *)cookie; 490 491 LOG("Stop(%s)\n", name); 492 493 close(device->fd); 494 device->fd = -1; 495 496 device->active = false; 497 if (device->device_watcher >= 0) { 498 suspend_thread(device->device_watcher); 499 resume_thread(device->device_watcher); 500 status_t dummy; 501 wait_for_thread(device->device_watcher, &dummy); 502 } 503 504 if (fTMWindow) { 505 fTMWindow->PostMessage(B_QUIT_REQUESTED); 506 fTMWindow = NULL; 507 } 508 509 return B_OK; 510 } 511 512 513 status_t 514 KeyboardInputDevice::Control(const char *name, void *cookie, 515 uint32 command, BMessage *message) 516 { 517 CALLED(); 518 LOG("Control(%s, code: %lu)\n", name, command); 519 520 if (command == B_NODE_MONITOR) 521 _HandleMonitor(message); 522 else if (command >= B_KEY_MAP_CHANGED 523 && command <= B_KEY_REPEAT_RATE_CHANGED) { 524 _InitFromSettings(cookie, command); 525 } 526 return B_OK; 527 } 528 529 530 status_t 531 KeyboardInputDevice::_HandleMonitor(BMessage *message) 532 { 533 CALLED(); 534 int32 opcode = 0; 535 status_t status; 536 if ((status = message->FindInt32("opcode", &opcode)) < B_OK) 537 return status; 538 539 if (opcode != B_ENTRY_CREATED 540 && opcode != B_ENTRY_REMOVED) 541 return B_OK; 542 543 BEntry entry; 544 BPath path; 545 dev_t device; 546 ino_t directory; 547 const char *name = NULL; 548 549 message->FindInt32("device", &device); 550 message->FindInt64("directory", &directory); 551 message->FindString("name", &name); 552 553 entry_ref ref(device, directory, name); 554 555 if ((status = entry.SetTo(&ref)) != B_OK) 556 return status; 557 if ((status = entry.GetPath(&path)) != B_OK) 558 return status; 559 if ((status = path.InitCheck()) != B_OK) 560 return status; 561 562 if (opcode == B_ENTRY_CREATED) 563 _AddDevice(path.Path()); 564 else 565 _RemoveDevice(path.Path()); 566 567 return status; 568 } 569 570 571 status_t 572 KeyboardInputDevice::_AddDevice(const char *path) 573 { 574 CALLED(); 575 keyboard_device *device = new (std::nothrow) keyboard_device(path); 576 if (device == NULL) 577 return B_NO_MEMORY; 578 579 device->owner = this; 580 581 input_device_ref *devices[2]; 582 devices[0] = &device->device_ref; 583 devices[1] = NULL; 584 585 fDevices.AddItem(device); 586 587 return RegisterDevices(devices); 588 } 589 590 591 status_t 592 KeyboardInputDevice::_RemoveDevice(const char *path) 593 { 594 CALLED(); 595 keyboard_device *device; 596 for (int i = 0; (device = (keyboard_device *)fDevices.ItemAt(i)) != NULL; i++) { 597 if (!strcmp(device->path, path)) { 598 fDevices.RemoveItem(device); 599 600 input_device_ref *devices[2]; 601 devices[0] = &device->device_ref; 602 devices[1] = NULL; 603 UnregisterDevices(devices); 604 605 delete device; 606 return B_OK; 607 } 608 } 609 610 return B_ENTRY_NOT_FOUND; 611 } 612 613 614 /*static*/ int32 615 KeyboardInputDevice::_DeviceWatcher(void *arg) 616 { 617 CALLED(); 618 keyboard_device* device = (keyboard_device *)arg; 619 KeyboardInputDevice* owner = device->owner; 620 uint8 buffer[16]; 621 uint8 activeDeadKey = 0; 622 Keymap* keymap = &owner->fKeymap; 623 uint32 lastKeyCode = 0; 624 uint32 repeatCount = 1; 625 uint8 states[16]; 626 627 memset(states, 0, sizeof(states)); 628 629 LOG("%s\n", __PRETTY_FUNCTION__); 630 631 while (device->active) { 632 if (ioctl(device->fd, KB_READ, &buffer) != B_OK) 633 return 0; 634 635 uint32 keycode = 0; 636 bool isKeyDown = false; 637 bigtime_t timestamp = 0; 638 639 LOG("KB_READ :"); 640 641 if (device->isAT) { 642 at_kbd_io *at_kbd = (at_kbd_io *)buffer; 643 if (at_kbd->scancode > 0) 644 keycode = kATKeycodeMap[at_kbd->scancode-1]; 645 isKeyDown = at_kbd->is_keydown; 646 timestamp = at_kbd->timestamp; 647 LOG(" %02x", at_kbd->scancode); 648 } else { 649 raw_key_info *raw_kbd = (raw_key_info *)buffer; 650 isKeyDown = raw_kbd->is_keydown; 651 timestamp = raw_kbd->timestamp; 652 keycode = raw_kbd->be_keycode; 653 } 654 655 if (keycode == 0) 656 continue; 657 658 LOG(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode); 659 660 if (isKeyDown && keycode == 0x68) { 661 // MENU KEY for OpenTracker 5.2.0+ 662 bool noOtherKeyPressed = true; 663 for (int32 i = 0; i < 16; i++) { 664 if (states[i] != 0) { 665 noOtherKeyPressed = false; 666 break; 667 } 668 } 669 670 if (noOtherKeyPressed) { 671 BMessenger deskbar("application/x-vnd.Be-TSKB"); 672 if (deskbar.IsValid()) 673 deskbar.SendMessage('BeMn'); 674 } 675 } 676 677 if (keycode < 256) { 678 if (isKeyDown) 679 states[(keycode) >> 3] |= (1 << (7 - (keycode & 0x7))); 680 else 681 states[(keycode) >> 3] &= (!(1 << (7 - (keycode & 0x7)))); 682 } 683 684 if (isKeyDown 685 && keycode == 0x34 // DELETE KEY 686 && (states[0x5c >> 3] & (1 << (7 - (0x5c & 0x7)))) 687 && (states[0x5d >> 3] & (1 << (7 - (0x5d & 0x7))))) { 688 LOG("TeamMonitor called\n"); 689 690 // show the team monitor 691 if (owner->fTMWindow == NULL) 692 owner->fTMWindow = new (std::nothrow) TMWindow(); 693 694 if (owner->fTMWindow != NULL) { 695 owner->fTMWindow->Enable(); 696 697 // cancel timer only for R5 698 if (ioctl(device->fd, KB_CANCEL_CONTROL_ALT_DEL, NULL) == B_OK) 699 LOG("KB_CANCEL_CONTROL_ALT_DEL : OK\n"); 700 } 701 } 702 703 BAutolock lock(owner->fKeymapLock); 704 705 uint32 modifiers = keymap->Modifier(keycode); 706 if (modifiers 707 && (!(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)) 708 || isKeyDown)) { 709 BMessage *msg = new BMessage; 710 if (msg == NULL) 711 continue; 712 713 msg->AddInt64("when", timestamp); 714 msg->what = B_MODIFIERS_CHANGED; 715 msg->AddInt32("be:old_modifiers", device->modifiers); 716 717 if ((isKeyDown && !(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))) 718 || (isKeyDown && !(device->modifiers & modifiers))) 719 device->modifiers |= modifiers; 720 else 721 device->modifiers &= ~modifiers; 722 723 msg->AddInt32("modifiers", device->modifiers); 724 msg->AddData("states", B_UINT8_TYPE, states, 16); 725 726 if (owner->EnqueueMessage(msg)!=B_OK) 727 delete msg; 728 729 if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)) 730 owner->_SetLeds(device); 731 } 732 733 uint8 newDeadKey = 0; 734 if (activeDeadKey == 0) 735 newDeadKey = keymap->IsDeadKey(keycode, device->modifiers); 736 737 if (newDeadKey == 0) { 738 char *string = NULL, *rawString = NULL; 739 int32 numBytes = 0, rawNumBytes = 0; 740 keymap->GetChars(keycode, device->modifiers, activeDeadKey, &string, &numBytes); 741 keymap->GetChars(keycode, 0, 0, &rawString, &rawNumBytes); 742 743 BMessage *msg = new BMessage; 744 if (msg == NULL) 745 continue; 746 747 if (numBytes > 0) 748 msg->what = isKeyDown ? B_KEY_DOWN : B_KEY_UP; 749 else 750 msg->what = isKeyDown ? B_UNMAPPED_KEY_DOWN : B_UNMAPPED_KEY_UP; 751 752 msg->AddInt64("when", timestamp); 753 msg->AddInt32("key", keycode); 754 msg->AddInt32("modifiers", device->modifiers); 755 msg->AddData("states", B_UINT8_TYPE, states, 16); 756 if (numBytes > 0) { 757 for (int i = 0; i < numBytes; i++) { 758 msg->AddInt8("byte", (int8)string[i]); 759 } 760 msg->AddString("bytes", string); 761 762 if (rawNumBytes <= 0) { 763 rawNumBytes = 1; 764 delete[] rawString; 765 rawString = string; 766 } else 767 delete[] string; 768 769 if (isKeyDown && lastKeyCode == keycode) { 770 repeatCount++; 771 msg->AddInt32("be:key_repeat", repeatCount); 772 } else 773 repeatCount = 1; 774 } else 775 delete[] string; 776 777 if (rawNumBytes > 0) 778 msg->AddInt32("raw_char", (uint32)((uint8)rawString[0] & 0x7f)); 779 780 delete[] rawString; 781 782 if (isKeyDown && !modifiers && activeDeadKey != 0 783 && device->input_method_started) { 784 // a dead key was completed 785 device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, 786 string, true, msg); 787 } else if (owner->EnqueueMessage(msg) != B_OK) 788 delete msg; 789 } else if (isKeyDown) { 790 // start of a dead key 791 if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) { 792 char *string = NULL; 793 int32 numBytes = 0; 794 keymap->GetChars(keycode, device->modifiers, 0, &string, &numBytes); 795 796 if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK) 797 device->input_method_started = true; 798 } 799 } 800 801 if (!isKeyDown && !modifiers) { 802 if (activeDeadKey != 0) { 803 device->EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED); 804 device->input_method_started = false; 805 } 806 807 activeDeadKey = newDeadKey; 808 } 809 810 lastKeyCode = isKeyDown ? keycode : 0; 811 } 812 813 return 0; 814 } 815 816 817 void 818 KeyboardInputDevice::_RecursiveScan(const char *directory) 819 { 820 CALLED(); 821 BEntry entry; 822 BDirectory dir(directory); 823 while (dir.GetNextEntry(&entry) == B_OK) { 824 BPath path; 825 entry.GetPath(&path); 826 if (entry.IsDirectory()) 827 _RecursiveScan(path.Path()); 828 else 829 _AddDevice(path.Path()); 830 } 831 } 832 833 834 void 835 KeyboardInputDevice::_SetLeds(keyboard_device *device) 836 { 837 if (device->fd < 0) 838 return; 839 840 uint32 locks = device->modifiers; 841 char lock_io[3]; 842 memset(lock_io, 0, sizeof(lock_io)); 843 if (locks & B_NUM_LOCK) 844 lock_io[0] = 1; 845 if (locks & B_CAPS_LOCK) 846 lock_io[1] = 1; 847 if (locks & B_SCROLL_LOCK) 848 lock_io[2] = 1; 849 850 ioctl(device->fd, KB_SET_LEDS, &lock_io); 851 } 852 853 854 // #pragma mark - 855 856 857 keyboard_device::keyboard_device(const char *path) 858 : BHandler("keyboard device"), 859 owner(NULL), 860 fd(-1), 861 device_watcher(-1), 862 active(false), 863 input_method_started(false) 864 { 865 strcpy(this->path, path); 866 device_ref.name = get_short_name(path); 867 device_ref.type = B_KEYBOARD_DEVICE; 868 device_ref.cookie = this; 869 870 isAT = strstr(path, "keyboard/at") != NULL; 871 872 if (be_app->Lock()) { 873 be_app->AddHandler(this); 874 be_app->Unlock(); 875 } 876 } 877 878 879 keyboard_device::~keyboard_device() 880 { 881 free(device_ref.name); 882 883 if (be_app->Lock()) { 884 be_app->RemoveHandler(this); 885 be_app->Unlock(); 886 } 887 } 888 889 890 status_t 891 keyboard_device::EnqueueInlineInputMethod(int32 opcode, 892 const char* string, bool confirmed, BMessage* keyDown) 893 { 894 BMessage* message = new BMessage(B_INPUT_METHOD_EVENT); 895 if (message == NULL) 896 return B_NO_MEMORY; 897 898 message->AddInt32("be:opcode", opcode); 899 message->AddBool("be:inline_only", true); 900 901 if (string != NULL) 902 message->AddString("be:string", string); 903 if (confirmed) 904 message->AddBool("be:confirmed", true); 905 if (keyDown) 906 message->AddMessage("be:translated", keyDown); 907 if (opcode == B_INPUT_METHOD_STARTED) 908 message->AddMessenger("be:reply_to", this); 909 910 status_t status = owner->EnqueueMessage(message); 911 if (status != B_OK) 912 delete message; 913 914 return status; 915 } 916 917 918 void 919 keyboard_device::MessageReceived(BMessage *message) 920 { 921 if (message->what != B_INPUT_METHOD_EVENT) { 922 BHandler::MessageReceived(message); 923 return; 924 } 925 926 int32 opcode; 927 if (message->FindInt32("be:opcode", &opcode) != B_OK) 928 return; 929 930 if (opcode == B_INPUT_METHOD_STOPPED) 931 input_method_started = false; 932 } 933 934