blob: 0425c8d4e3dbdcfe181acfee79a48cfa7f8eeb35 [file] [log] [blame]
// 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 <hid/hid.h>
#include <hid/usages.h>
#include <unittest/unittest.h>
#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)
}