// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include "keyboard-vt100.h" #include "keyboard.h" namespace { // State reported to keypress_handler(). uint8_t g_keycode; int g_modifiers; bool g_got_keypress = false; void keypress_handler(uint8_t keycode, int modifiers) { g_keycode = keycode; g_modifiers = modifiers; g_got_keypress = true; } void expect_keypress(uint8_t expected_keycode, int expected_modifiers, uint8_t expected_char) { EXPECT_EQ(g_got_keypress, true, ""); g_got_keypress = false; EXPECT_EQ(g_keycode, expected_keycode, ""); EXPECT_EQ(g_modifiers, expected_modifiers, ""); char output[4] = {}; uint32_t length = hid_key_to_vt100_code( g_keycode, g_modifiers, qwerty_map, output, sizeof(output)); if (expected_char == 0) { EXPECT_EQ(length, 0, ""); } else { EXPECT_EQ(length, 1, ""); EXPECT_EQ(output[0], expected_char, ""); } } class KeyboardInputHelper { public: KeyboardInputHelper() { EXPECT_EQ(vc_input_create(&vi_, keypress_handler, -1), ZX_OK, ""); } ~KeyboardInputHelper() { } void WriteReportBuf() { vc_input_process(vi_, report_buf_); } // Byte 0 contains one bit per modifier key. void set_modifiers_byte(uint8_t value) { report_buf_[0] = value; } // Bytes 2+ contain USB HID key codes. void set_first_keycode(uint8_t value) { report_buf_[2] = value; } private: // USB HID key state buffer. uint8_t report_buf_[8] = {}; vc_input_t* vi_; }; bool test_keyboard_input_thread() { BEGIN_TEST; KeyboardInputHelper helper; // Test pressing keys without any modifiers. helper.set_first_keycode(HID_USAGE_KEY_M); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_M, 0, 'm'); helper.set_first_keycode(HID_USAGE_KEY_6); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_6, 0, '6'); // Press a modifier (but no other keys). helper.set_first_keycode(0); // Unset the earlier key helper.set_modifiers_byte(2); // Left Shift key helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT, '\0'); // Test keys with modifiers pressed. // Test Shift-N. helper.set_first_keycode(HID_USAGE_KEY_N); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_N, MOD_LSHIFT, 'N'); // Test Shift-8. helper.set_first_keycode(HID_USAGE_KEY_8); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_8, MOD_LSHIFT, '*'); // Test Ctrl modifier. First send a separate report_buf event to // report unsetting the Shift key state, to account for a quirk of the // current implementation. helper.set_modifiers_byte(0); helper.WriteReportBuf(); helper.set_modifiers_byte(1); // Left Ctrl key helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_LEFT_CTRL, MOD_LCTRL, '\0'); // Test Ctrl-J. helper.set_first_keycode(HID_USAGE_KEY_J); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_J, MOD_LCTRL, 10); // Test Ctrl-1. The Ctrl modifier should be ignored in this case so // that we just get '1'. helper.set_first_keycode(HID_USAGE_KEY_1); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_1, MOD_LCTRL, '1'); // Try Shift and Ctrl together. helper.set_first_keycode(0); helper.set_modifiers_byte(1 | 2); // Left Shift and Left Ctrl keys helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT | MOD_LCTRL, '\0'); // Test Shift-Ctrl-J. This should be equivalent to Ctrl-J. helper.set_first_keycode(HID_USAGE_KEY_J); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_J, MOD_LSHIFT | MOD_LCTRL, 10); // Test Shift-Ctrl-1. This should be equivalent to Shift-1. helper.set_first_keycode(HID_USAGE_KEY_1); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_1, MOD_LSHIFT | MOD_LCTRL, '!'); END_TEST; } bool test_caps_lock() { BEGIN_TEST; KeyboardInputHelper helper; helper.set_first_keycode(HID_USAGE_KEY_CAPSLOCK); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_CAPSLOCK, '\0'); // Test that letters are capitalized. helper.set_first_keycode(HID_USAGE_KEY_M); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_M, MOD_CAPSLOCK, 'M'); // Non-letter characters should not be affected. This isn't Shift Lock. helper.set_first_keycode(HID_USAGE_KEY_1); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_1, MOD_CAPSLOCK, '1'); // Test unsetting Caps Lock. helper.set_first_keycode(HID_USAGE_KEY_CAPSLOCK); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_CAPSLOCK, 0, '\0'); helper.set_first_keycode(HID_USAGE_KEY_M); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_M, 0, 'm'); END_TEST; } bool test_caps_lock_with_shift() { BEGIN_TEST; KeyboardInputHelper helper; helper.set_modifiers_byte(2); // Left Shift key helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT, '\0'); helper.set_first_keycode(HID_USAGE_KEY_CAPSLOCK); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_LSHIFT | MOD_CAPSLOCK, '\0'); // Shift should undo the effect of Caps Lock for letters. helper.set_first_keycode(HID_USAGE_KEY_M); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_M, MOD_LSHIFT | MOD_CAPSLOCK, 'm'); helper.set_first_keycode(HID_USAGE_KEY_1); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_1, MOD_LSHIFT | MOD_CAPSLOCK, '!'); // Test unsetting Caps Lock. helper.set_first_keycode(HID_USAGE_KEY_CAPSLOCK); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_LSHIFT, '\0'); helper.set_first_keycode(HID_USAGE_KEY_M); helper.WriteReportBuf(); expect_keypress(HID_USAGE_KEY_M, MOD_LSHIFT, 'M'); END_TEST; } BEGIN_TEST_CASE(gfxconsole_keyboard_tests) RUN_TEST(test_keyboard_input_thread) RUN_TEST(test_caps_lock) RUN_TEST(test_caps_lock_with_shift) END_TEST_CASE(gfxconsole_keyboard_tests) }