xref: /haiku/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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