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