keyboard stuff
1/* Copyright 2017 Fred Sundvik
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "keyboard_report_util.hpp"
18#include <cstdint>
19#include <vector>
20#include <algorithm>
21
22extern "C" {
23#include "keycode_string.h"
24}
25
26using namespace testing;
27
28extern std::map<uint16_t, std::string> KEYCODE_ID_TABLE;
29
30namespace {
31
32std::vector<uint8_t> get_keys(const report_keyboard_t& report) {
33 std::vector<uint8_t> result;
34#if defined(NKRO_ENABLE)
35# error NKRO support not implemented yet
36#else
37 for (size_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
38 if (report.keys[i]) {
39 result.emplace_back(report.keys[i]);
40 }
41 }
42#endif
43 std::sort(result.begin(), result.end());
44 return result;
45}
46
47std::vector<uint8_t> get_mods(const report_keyboard_t& report) {
48 std::vector<uint8_t> result;
49 for (size_t i = 0; i < 8; i++) {
50 if (report.mods & (1 << i)) {
51 uint8_t code = KC_LEFT_CTRL + i;
52 result.emplace_back(code);
53 }
54 }
55 std::sort(result.begin(), result.end());
56 return result;
57}
58
59} // namespace
60
61bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) {
62 auto lhskeys = get_keys(lhs);
63 auto rhskeys = get_keys(rhs);
64 return lhs.mods == rhs.mods && lhskeys == rhskeys;
65}
66
67std::ostream& operator<<(std::ostream& os, const report_keyboard_t& report) {
68 auto keys = get_keys(report);
69 auto mods = get_mods(report);
70
71 os << std::setw(10) << std::left << "report: ";
72
73 if (!keys.size() && !mods.size()) {
74 return os << "empty" << std::endl;
75 }
76
77 os << "(";
78 for (auto key = keys.cbegin(); key != keys.cend();) {
79 os << get_keycode_string(*key);
80 key++;
81 if (key != keys.cend()) {
82 os << ", ";
83 }
84 }
85
86 os << ") [";
87
88 for (auto mod = mods.cbegin(); mod != mods.cend();) {
89 os << get_keycode_string(*mod);
90 mod++;
91 if (mod != mods.cend()) {
92 os << ", ";
93 }
94 }
95
96 return os << "]" << std::endl;
97}
98
99KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) {
100 memset(&m_report, 0, sizeof(report_keyboard_t));
101 for (auto k : keys) {
102 if (IS_MODIFIER_KEYCODE(k)) {
103 m_report.mods |= MOD_BIT(k);
104 } else {
105 add_key_byte(&m_report, k);
106 }
107 }
108}
109
110bool KeyboardReportMatcher::MatchAndExplain(report_keyboard_t& report, MatchResultListener* listener) const {
111 return m_report == report;
112}
113
114void KeyboardReportMatcher::DescribeTo(::std::ostream* os) const {
115 *os << "is equal to " << m_report;
116}
117
118void KeyboardReportMatcher::DescribeNegationTo(::std::ostream* os) const {
119 *os << "is not equal to " << m_report;
120}