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