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 status_t status = BInputServerDevice::InitCheck(); 449 if (status < B_OK) 450 return status; 451 452 // TODO: this doesn't belong here! 453 _RecursiveScan(kKeyboardDevicesDirectory); 454 455 StartMonitoringDevice(kKeyboardDevicesDirectoryPS2); 456 StartMonitoringDevice(kKeyboardDevicesDirectoryUSB); 457 458 return B_OK; 459 } 460 461 462 status_t 463 KeyboardInputDevice::Start(const char *name, void *cookie) 464 { 465 CALLED(); 466 keyboard_device *device = (keyboard_device *)cookie; 467 468 if ((device->fd = open(device->path, O_RDWR)) < B_OK) { 469 fprintf(stderr, "error when opening %s: %s\n", device->path, strerror(errno)); 470 return B_ERROR; 471 } 472 473 _InitFromSettings(device); 474 475 char threadName[B_OS_NAME_LENGTH]; 476 snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name); 477 478 device->active = true; 479 device->device_watcher = spawn_thread(_DeviceWatcher, threadName, 480 kKeyboardThreadPriority, device); 481 if (device->device_watcher < B_OK) 482 return device->device_watcher; 483 484 resume_thread(device->device_watcher); 485 return B_OK; 486 } 487 488 489 status_t 490 KeyboardInputDevice::Stop(const char *name, void *cookie) 491 { 492 CALLED(); 493 keyboard_device *device = (keyboard_device *)cookie; 494 495 LOG("Stop(%s)\n", name); 496 497 close(device->fd); 498 device->fd = -1; 499 500 device->active = false; 501 if (device->device_watcher >= 0) { 502 suspend_thread(device->device_watcher); 503 resume_thread(device->device_watcher); 504 status_t dummy; 505 wait_for_thread(device->device_watcher, &dummy); 506 } 507 508 if (fTMWindow) { 509 fTMWindow->PostMessage(B_QUIT_REQUESTED); 510 fTMWindow = NULL; 511 } 512 513 return B_OK; 514 } 515 516 517 status_t 518 KeyboardInputDevice::Control(const char *name, void *cookie, 519 uint32 command, BMessage *message) 520 { 521 CALLED(); 522 LOG("Control(%s, code: %lu)\n", name, command); 523 524 if (command == B_NODE_MONITOR) 525 _HandleMonitor(message); 526 else if (command >= B_KEY_MAP_CHANGED 527 && command <= B_KEY_REPEAT_RATE_CHANGED) { 528 _InitFromSettings(cookie, command); 529 } 530 return B_OK; 531 } 532 533 534 status_t 535 KeyboardInputDevice::_HandleMonitor(BMessage *message) 536 { 537 CALLED(); 538 int32 opcode = 0; 539 status_t status; 540 if ((status = message->FindInt32("opcode", &opcode)) < B_OK) 541 return status; 542 543 if (opcode != B_ENTRY_CREATED 544 && opcode != B_ENTRY_REMOVED) 545 return B_OK; 546 547 BEntry entry; 548 BPath path; 549 dev_t device; 550 ino_t directory; 551 const char *name = NULL; 552 553 message->FindInt32("device", &device); 554 message->FindInt64("directory", &directory); 555 message->FindString("name", &name); 556 557 entry_ref ref(device, directory, name); 558 559 if ((status = entry.SetTo(&ref)) != B_OK) 560 return status; 561 if ((status = entry.GetPath(&path)) != B_OK) 562 return status; 563 if ((status = path.InitCheck()) != B_OK) 564 return status; 565 566 if (opcode == B_ENTRY_CREATED) 567 _AddDevice(path.Path()); 568 else 569 _RemoveDevice(path.Path()); 570 571 return status; 572 } 573 574 575 status_t 576 KeyboardInputDevice::_AddDevice(const char *path) 577 { 578 CALLED(); 579 keyboard_device *device = new (std::nothrow) keyboard_device(path); 580 if (device == NULL) 581 return B_NO_MEMORY; 582 583 device->owner = this; 584 585 input_device_ref *devices[2]; 586 devices[0] = &device->device_ref; 587 devices[1] = NULL; 588 589 fDevices.AddItem(device); 590 591 return RegisterDevices(devices); 592 } 593 594 595 status_t 596 KeyboardInputDevice::_RemoveDevice(const char *path) 597 { 598 CALLED(); 599 keyboard_device *device; 600 for (int i = 0; (device = (keyboard_device *)fDevices.ItemAt(i)) != NULL; i++) { 601 if (!strcmp(device->path, path)) { 602 fDevices.RemoveItem(device); 603 604 input_device_ref *devices[2]; 605 devices[0] = &device->device_ref; 606 devices[1] = NULL; 607 UnregisterDevices(devices); 608 609 delete device; 610 return B_OK; 611 } 612 } 613 614 return B_ENTRY_NOT_FOUND; 615 } 616 617 618 /*static*/ int32 619 KeyboardInputDevice::_DeviceWatcher(void *arg) 620 { 621 CALLED(); 622 keyboard_device* device = (keyboard_device *)arg; 623 KeyboardInputDevice* owner = device->owner; 624 uint8 buffer[16]; 625 uint8 activeDeadKey = 0; 626 Keymap* keymap = &owner->fKeymap; 627 uint32 lastKeyCode = 0; 628 uint32 repeatCount = 1; 629 uint8 states[16]; 630 631 memset(states, 0, sizeof(states)); 632 633 LOG("%s\n", __PRETTY_FUNCTION__); 634 635 while (device->active) { 636 if (ioctl(device->fd, KB_READ, &buffer) != B_OK) 637 return 0; 638 639 uint32 keycode = 0; 640 bool isKeyDown = false; 641 bigtime_t timestamp = 0; 642 643 LOG("KB_READ :"); 644 645 if (device->isAT) { 646 at_kbd_io *at_kbd = (at_kbd_io *)buffer; 647 if (at_kbd->scancode > 0) 648 keycode = kATKeycodeMap[at_kbd->scancode-1]; 649 isKeyDown = at_kbd->is_keydown; 650 timestamp = at_kbd->timestamp; 651 LOG(" %02x", at_kbd->scancode); 652 } else { 653 raw_key_info *raw_kbd = (raw_key_info *)buffer; 654 isKeyDown = raw_kbd->is_keydown; 655 timestamp = raw_kbd->timestamp; 656 keycode = raw_kbd->be_keycode; 657 } 658 659 if (keycode == 0) 660 continue; 661 662 LOG(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode); 663 664 if (isKeyDown && keycode == 0x68) { 665 // MENU KEY for OpenTracker 5.2.0+ 666 bool noOtherKeyPressed = true; 667 for (int32 i = 0; i < 16; i++) { 668 if (states[i] != 0) { 669 noOtherKeyPressed = false; 670 break; 671 } 672 } 673 674 if (noOtherKeyPressed) { 675 BMessenger deskbar("application/x-vnd.Be-TSKB"); 676 if (deskbar.IsValid()) 677 deskbar.SendMessage('BeMn'); 678 } 679 } 680 681 if (keycode < 256) { 682 if (isKeyDown) 683 states[(keycode) >> 3] |= (1 << (7 - (keycode & 0x7))); 684 else 685 states[(keycode) >> 3] &= (!(1 << (7 - (keycode & 0x7)))); 686 } 687 688 if (isKeyDown 689 && keycode == 0x34 // DELETE KEY 690 && (states[0x5c >> 3] & (1 << (7 - (0x5c & 0x7)))) 691 && (states[0x5d >> 3] & (1 << (7 - (0x5d & 0x7))))) { 692 LOG("TeamMonitor called\n"); 693 694 // show the team monitor 695 if (owner->fTMWindow == NULL) 696 owner->fTMWindow = new (std::nothrow) TMWindow(); 697 698 if (owner->fTMWindow != NULL) { 699 owner->fTMWindow->Enable(); 700 701 // cancel timer only for R5 702 if (ioctl(device->fd, KB_CANCEL_CONTROL_ALT_DEL, NULL) == B_OK) 703 LOG("KB_CANCEL_CONTROL_ALT_DEL : OK\n"); 704 } 705 } 706 707 BAutolock lock(owner->fKeymapLock); 708 709 uint32 modifiers = keymap->Modifier(keycode); 710 if (modifiers 711 && (!(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)) 712 || isKeyDown)) { 713 BMessage *msg = new BMessage; 714 if (msg == NULL) 715 continue; 716 717 msg->AddInt64("when", timestamp); 718 msg->what = B_MODIFIERS_CHANGED; 719 msg->AddInt32("be:old_modifiers", device->modifiers); 720 721 if ((isKeyDown && !(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))) 722 || (isKeyDown && !(device->modifiers & modifiers))) 723 device->modifiers |= modifiers; 724 else 725 device->modifiers &= ~modifiers; 726 727 msg->AddInt32("modifiers", device->modifiers); 728 msg->AddData("states", B_UINT8_TYPE, states, 16); 729 730 if (owner->EnqueueMessage(msg)!=B_OK) 731 delete msg; 732 733 if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)) 734 owner->_SetLeds(device); 735 } 736 737 uint8 newDeadKey = 0; 738 if (activeDeadKey == 0) 739 newDeadKey = keymap->IsDeadKey(keycode, device->modifiers); 740 741 if (newDeadKey == 0) { 742 char *string = NULL, *rawString = NULL; 743 int32 numBytes = 0, rawNumBytes = 0; 744 keymap->GetChars(keycode, device->modifiers, activeDeadKey, &string, &numBytes); 745 keymap->GetChars(keycode, 0, 0, &rawString, &rawNumBytes); 746 747 BMessage *msg = new BMessage; 748 if (msg == NULL) 749 continue; 750 751 if (numBytes > 0) 752 msg->what = isKeyDown ? B_KEY_DOWN : B_KEY_UP; 753 else 754 msg->what = isKeyDown ? B_UNMAPPED_KEY_DOWN : B_UNMAPPED_KEY_UP; 755 756 msg->AddInt64("when", timestamp); 757 msg->AddInt32("key", keycode); 758 msg->AddInt32("modifiers", device->modifiers); 759 msg->AddData("states", B_UINT8_TYPE, states, 16); 760 if (numBytes > 0) { 761 for (int i = 0; i < numBytes; i++) { 762 msg->AddInt8("byte", (int8)string[i]); 763 } 764 msg->AddString("bytes", string); 765 766 if (rawNumBytes <= 0) { 767 rawNumBytes = 1; 768 delete[] rawString; 769 rawString = string; 770 } else 771 delete[] string; 772 773 if (isKeyDown && lastKeyCode == keycode) { 774 repeatCount++; 775 msg->AddInt32("be:key_repeat", repeatCount); 776 } else 777 repeatCount = 1; 778 } else 779 delete[] string; 780 781 if (rawNumBytes > 0) 782 msg->AddInt32("raw_char", (uint32)((uint8)rawString[0] & 0x7f)); 783 784 delete[] rawString; 785 786 if (isKeyDown && !modifiers && activeDeadKey != 0 787 && device->input_method_started) { 788 // a dead key was completed 789 device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, 790 string, true, msg); 791 } else if (owner->EnqueueMessage(msg) != B_OK) 792 delete msg; 793 } else if (isKeyDown) { 794 // start of a dead key 795 if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) { 796 char *string = NULL; 797 int32 numBytes = 0; 798 keymap->GetChars(keycode, device->modifiers, 0, &string, &numBytes); 799 800 if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK) 801 device->input_method_started = true; 802 } 803 } 804 805 if (!isKeyDown && !modifiers) { 806 if (activeDeadKey != 0) { 807 device->EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED); 808 device->input_method_started = false; 809 } 810 811 activeDeadKey = newDeadKey; 812 } 813 814 lastKeyCode = isKeyDown ? keycode : 0; 815 } 816 817 return 0; 818 } 819 820 821 void 822 KeyboardInputDevice::_RecursiveScan(const char *directory) 823 { 824 CALLED(); 825 BEntry entry; 826 BDirectory dir(directory); 827 while (dir.GetNextEntry(&entry) == B_OK) { 828 BPath path; 829 entry.GetPath(&path); 830 if (entry.IsDirectory()) 831 _RecursiveScan(path.Path()); 832 else 833 _AddDevice(path.Path()); 834 } 835 } 836 837 838 void 839 KeyboardInputDevice::_SetLeds(keyboard_device *device) 840 { 841 if (device->fd < 0) 842 return; 843 844 uint32 locks = device->modifiers; 845 char lock_io[3]; 846 memset(lock_io, 0, sizeof(lock_io)); 847 if (locks & B_NUM_LOCK) 848 lock_io[0] = 1; 849 if (locks & B_CAPS_LOCK) 850 lock_io[1] = 1; 851 if (locks & B_SCROLL_LOCK) 852 lock_io[2] = 1; 853 854 ioctl(device->fd, KB_SET_LEDS, &lock_io); 855 } 856 857 858 // #pragma mark - 859 860 861 keyboard_device::keyboard_device(const char *path) 862 : BHandler("keyboard device"), 863 owner(NULL), 864 fd(-1), 865 device_watcher(-1), 866 active(false), 867 input_method_started(false) 868 { 869 strcpy(this->path, path); 870 device_ref.name = get_short_name(path); 871 device_ref.type = B_KEYBOARD_DEVICE; 872 device_ref.cookie = this; 873 874 isAT = strstr(path, "keyboard/at") != NULL; 875 876 if (be_app->Lock()) { 877 be_app->AddHandler(this); 878 be_app->Unlock(); 879 } 880 } 881 882 883 keyboard_device::~keyboard_device() 884 { 885 free(device_ref.name); 886 887 if (be_app->Lock()) { 888 be_app->RemoveHandler(this); 889 be_app->Unlock(); 890 } 891 } 892 893 894 status_t 895 keyboard_device::EnqueueInlineInputMethod(int32 opcode, 896 const char* string, bool confirmed, BMessage* keyDown) 897 { 898 BMessage* message = new BMessage(B_INPUT_METHOD_EVENT); 899 if (message == NULL) 900 return B_NO_MEMORY; 901 902 message->AddInt32("be:opcode", opcode); 903 message->AddBool("be:inline_only", true); 904 905 if (string != NULL) 906 message->AddString("be:string", string); 907 if (confirmed) 908 message->AddBool("be:confirmed", true); 909 if (keyDown) 910 message->AddMessage("be:translated", keyDown); 911 if (opcode == B_INPUT_METHOD_STARTED) 912 message->AddMessenger("be:reply_to", this); 913 914 status_t status = owner->EnqueueMessage(message); 915 if (status != B_OK) 916 delete message; 917 918 return status; 919 } 920 921 922 void 923 keyboard_device::MessageReceived(BMessage *message) 924 { 925 if (message->what != B_INPUT_METHOD_EVENT) { 926 BHandler::MessageReceived(message); 927 return; 928 } 929 930 int32 opcode; 931 if (message->FindInt32("be:opcode", &opcode) != B_OK) 932 return; 933 934 if (opcode == B_INPUT_METHOD_STOPPED) 935 input_method_started = false; 936 } 937 938