/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS keyboard driver. * * By Jason Wilkins, rewritten by Angelo Mottola to use the unified * pckeys API. * * See readme.txt for copyright information. */ #include #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #ifndef ALLEGRO_BEOS #error something is wrong with the makefile #endif #define KEY_ID_PC101 0 // the docs say it should be 0x83ab, but they lie #define KEY_SEMAPHORE_NAME "keyboard driver waiting..." #define KEY_THREAD_PERIOD 33333 // microseconds, 1/30th of a second #define KEY_THREAD_NAME "keyboard driver" #define KEY_THREAD_PRIORITY 60 // above average #define BE_KEY_PAUSE 16 #define BE_KEY_NUMLOCK 34 #define BE_KEY_CAPSLOCK 59 #define BE_KEY_SCROLOCK 15 #define PREFIX_I "al-bkey INFO: " #define PREFIX_W "al-bkey WARNING: " #define PREFIX_E "al-bkey ERROR: " static uint16 keyboard_id = (uint16)(-1); static volatile int keyboard_thread_running = FALSE; static thread_id keyboard_thread_id = -1; static sem_id waiting_for_input = -1; static const int be_to_pc[128] = { // Scancode Be Key -1, // 0 (not used) 0x1, // 1 ESC 0x3b, // 2 F1 0x3c, // 3 F2 0x3d, // 4 F3 0x3e, // 5 F4 0x3f, // 6 F5 0x40, // 7 F6 0x41, // 8 F7 0x42, // 9 F8 0x43, // 10 F9 0x44, // 11 F10 0x57, // 12 F11 0x58, // 13 F12 0x54, // 14 Print Screen / SysRq 0x46, // 15 Scroll Lock 0, // 16 Pause / Break 0x29, // 17 Tilde 0x2, // 18 '1' 0x3, // 19 '2' 0x4, // 20 '3' 0x5, // 21 '4' 0x6, // 22 '5' 0x7, // 23 '6' 0x8, // 24 '7' 0x9, // 25 '8' 0xa, // 26 '9' 0xb, // 27 '0' 0xc, // 28 '-' 0xd, // 29 '=' 0xe, // 30 Backspace 0x5200, // 31 Insert 0x4700, // 32 Home 0x4900, // 33 Page Up 0x45, // 34 Num Lock 0x3500, // 35 Pad '/' 0x37, // 36 Pad '*' 0x4a, // 37 Pad '-' 0xf, // 38 Tab 0x10, // 39 'q' 0x11, // 40 'w' 0x12, // 41 'e' 0x13, // 42 'r' 0x14, // 43 't' 0x15, // 44 'y' 0x16, // 45 'u' 0x17, // 46 'i' 0x18, // 47 'o' 0x19, // 48 'p' 0x1a, // 49 '[' 0x1b, // 50 ']' 0x35, // 51 '\' 0x5300, // 52 Delete 0x4f00, // 53 End 0x5100, // 54 Page Down 0x47, // 55 Pad '7' 0x48, // 56 Pad '8' 0x49, // 57 Pad '9' 0x4e, // 58 Pad '+' 0x3a, // 59 Caps Lock 0x1e, // 60 'a' 0x1f, // 61 's' 0x20, // 62 'd' 0x21, // 63 'f' 0x22, // 64 'g' 0x23, // 65 'h' 0x24, // 66 'j' 0x25, // 67 'k' 0x26, // 68 'l' 0x27, // 69 ';' 0x28, // 70 ''' 0x1c, // 71 Enter 0x4b, // 72 Pad '4' 0x4c, // 73 Pad '5' 0x4d, // 74 Pad '6' 0x2a, // 75 Left Shift 0x2c, // 76 'z' 0x2d, // 77 'x' 0x2e, // 78 'c' 0x2f, // 79 'v' 0x30, // 80 'b' 0x31, // 81 'n' 0x32, // 82 'm' 0x33, // 83 ',' 0x34, // 84 '.' 0x35, // 85 '/' 0x36, // 86 Right Shift 0x4800, // 87 Up 0x4f, // 88 Pad '1' 0x50, // 89 Pad '2' 0x51, // 90 Pad '3' 0x1c00, // 91 Pad Enter 0x1d, // 92 Left Control 0x38, // 93 Left Alt 0x39, // 94 Space 0x3800, // 95 Right Alt 0x1d00, // 96 Right Control 0x4b00, // 97 Left 0x5000, // 98 Down 0x4d00, // 99 Right 0x52, // 100 Pad '0' 0x53, // 101 Pad Del 0x5b, // 102 Left Windows Key 0x5c, // 103 Right Windows Key 0x5d, // 104 Menu -1, // 105 (not used) -1, // 106 (not used) -1, // 107 (not used) -1, // 108 (not used) -1, // 109 (not used) -1, // 110 (not used) -1, // 111 (not used) -1, // 112 (not used) -1, // 113 (not used) -1, // 114 (not used) -1, // 115 (not used) -1, // 116 (not used) -1, // 117 (not used) -1, // 118 (not used) -1, // 119 (not used) -1, // 120 (not used) -1, // 121 (not used) -1, // 122 (not used) -1, // 123 (not used) -1, // 124 (not used) -1, // 125 (not used) -1, // 126 (not used) -1 // 127 (not used) }; /* keyboard_thread: */ static int32 keyboard_thread(void *keyboard_started) { key_info key_info_old; key_info key_info_new; get_key_info(&key_info_old); if (key_info_old.modifiers & B_CAPS_LOCK) _key_shifts |= KB_CAPSLOCK_FLAG; if (key_info_old.modifiers & B_SCROLL_LOCK) _key_shifts |= KB_SCROLOCK_FLAG; if (key_info_old.modifiers & B_NUM_LOCK) _key_shifts |= KB_NUMLOCK_FLAG; release_sem(*(sem_id *)keyboard_started); while(keyboard_thread_running) { int i; snooze(KEY_THREAD_PERIOD); if (!_be_focus_count) continue; get_key_info(&key_info_new); if (three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG) && (key_info_new.key_states[52 / 8] & (52 % 8)) ) { _be_terminate(keyboard_thread_id, true); } for (i=0; i<128; i++) { int new_key_pressed; int old_key_pressed; int scancode; new_key_pressed = key_info_new.key_states[i >> 3] & (1 << (7 - (i % 8))); old_key_pressed = key_info_old.key_states[i >> 3] & (1 << (7 - (i % 8))); if (new_key_pressed != old_key_pressed) { scancode = be_to_pc[i]; if (scancode != -1) { if (i == BE_KEY_PAUSE) { /* pause key special case */ _handle_key_press(0, KEY_PAUSE); _handle_key_release(KEY_PAUSE); continue; } if ((i == BE_KEY_CAPSLOCK) || (i == BE_KEY_SCROLOCK) || (i == BE_KEY_NUMLOCK)) { /* caps lock, scroll lock, and num lock special cases */ _handle_pckey(scancode); _handle_pckey(scancode | 0x80); continue; } if (scancode & 0xff00) { /* extended code */ _handle_pckey(0xe0); scancode >>= 8; } /* handle normal key press/release */ if (!new_key_pressed) scancode |= 0x80; _handle_pckey(scancode); } } } key_info_old = key_info_new; } TRACE(PREFIX_I "keyboard thread exited\n"); return 0; } /* set_default_key_repeat: */ static inline bool set_default_key_repeat(void) { int32 rate; bigtime_t delay; if (get_key_repeat_rate(&rate) != B_OK) { return false; } if (get_key_repeat_delay(&delay) != B_OK) { return false; } set_keyboard_rate((delay / 1000), (10000 / rate)); return true; } /* be_key_init: */ extern "C" int be_key_init(void) { sem_id keyboard_started; _pckeys_init(); if (get_keyboard_id(&keyboard_id) == B_ERROR) { goto cleanup; } if (keyboard_id != KEY_ID_PC101) { goto cleanup; } waiting_for_input = create_sem(0, "waiting for input..."); if (waiting_for_input < B_NO_ERROR) { goto cleanup; } keyboard_started = create_sem(0, "starting keyboard thread..."); if (keyboard_started < B_NO_ERROR) { goto cleanup; } keyboard_thread_id = spawn_thread(keyboard_thread, KEY_THREAD_NAME, KEY_THREAD_PRIORITY, &keyboard_started); if (keyboard_thread_id < 0) { goto cleanup; } keyboard_thread_running = TRUE; resume_thread(keyboard_thread_id); acquire_sem(keyboard_started); delete_sem(keyboard_started); if(!set_default_key_repeat()) { goto cleanup; } return 0; cleanup: { if (keyboard_started > 0) { delete_sem(keyboard_started); } be_key_exit(); return 1; } } /* be_key_exit: */ extern "C" void be_key_exit(void) { if (keyboard_thread_id > 0) { keyboard_thread_running = FALSE; wait_for_thread(keyboard_thread_id, &ignore_result); keyboard_thread_id = -1; } if (waiting_for_input > 0) { delete_sem(waiting_for_input); waiting_for_input = -1; } keyboard_id = (uint16)(-1); } /* be_key_set_leds: * Sets keyboard leds. */ extern "C" void be_key_set_leds(int leds) { uint32 modifiers; modifiers = 0; _key_shifts &= ~(KB_CAPSLOCK_FLAG | KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG); if (leds & KB_CAPSLOCK_FLAG) { modifiers |= B_CAPS_LOCK; _key_shifts |= KB_CAPSLOCK_FLAG; } if (leds & KB_SCROLOCK_FLAG) { modifiers |= B_SCROLL_LOCK; _key_shifts |= KB_SCROLOCK_FLAG; } if (leds & KB_NUMLOCK_FLAG) { modifiers |= B_NUM_LOCK; _key_shifts |= KB_NUMLOCK_FLAG; } set_keyboard_locks(modifiers); } /* be_key_set_rate: * Sets keyboard repeat rate and delay. */ extern "C" void be_key_set_rate(int delay, int repeat) { if (delay < 250) delay = 250; else if (delay < 500) delay = 500; else if (delay < 750) delay = 750; else delay = 1000; set_key_repeat_delay((bigtime_t)(delay * 1000)); if (repeat > 0) set_key_repeat_rate(10000 / repeat); } /* be_key_wait_for_input: */ extern "C" void be_key_wait_for_input(void) { acquire_sem(waiting_for_input); } /* be_key_stop_waiting_for_input: */ extern "C" void be_key_stop_waiting_for_input(void) { release_sem(waiting_for_input); } extern "C" void be_key_suspend(void) { suspend_thread(keyboard_thread_id); } extern "C" void be_key_resume(void) { resume_thread(keyboard_thread_id); }