keyboard_report_util.cpp
3262 bytes
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
22using namespace testing;
23
24extern std::map<uint16_t, std::string> KEYCODE_ID_TABLE;
25
26namespace {
27
28std::vector<uint8_t> get_keys(const report_keyboard_t& report) {
29 std::vector<uint8_t> result;
30#if defined(NKRO_ENABLE)
31# error NKRO support not implemented yet
32#else
33 for (size_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
34 if (report.keys[i]) {
35 result.emplace_back(report.keys[i]);
36 }
37 }
38#endif
39 std::sort(result.begin(), result.end());
40 return result;
41}
42
43std::vector<uint8_t> get_mods(const report_keyboard_t& report) {
44 std::vector<uint8_t> result;
45 for (size_t i = 0; i < 8; i++) {
46 if (report.mods & (1 << i)) {
47 uint8_t code = KC_LEFT_CTRL + i;
48 result.emplace_back(code);
49 }
50 }
51 std::sort(result.begin(), result.end());
52 return result;
53}
54
55} // namespace
56
57bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) {
58 auto lhskeys = get_keys(lhs);
59 auto rhskeys = get_keys(rhs);
60 return lhs.mods == rhs.mods && lhskeys == rhskeys;
61}
62
63std::ostream& operator<<(std::ostream& os, const report_keyboard_t& report) {
64 auto keys = get_keys(report);
65 auto mods = get_mods(report);
66
67 os << std::setw(10) << std::left << "report: ";
68
69 if (!keys.size() && !mods.size()) {
70 return os << "empty" << std::endl;
71 }
72
73 os << "(";
74 for (auto key = keys.cbegin(); key != keys.cend();) {
75 os << KEYCODE_ID_TABLE.at(*key);
76 key++;
77 if (key != keys.cend()) {
78 os << ", ";
79 }
80 }
81
82 os << ") [";
83
84 for (auto mod = mods.cbegin(); mod != mods.cend();) {
85 os << KEYCODE_ID_TABLE.at(*mod);
86 mod++;
87 if (mod != mods.cend()) {
88 os << ", ";
89 }
90 }
91
92 return os << "]" << std::endl;
93}
94
95KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) {
96 memset(&m_report, 0, sizeof(report_keyboard_t));
97 for (auto k : keys) {
98 if (IS_MODIFIER_KEYCODE(k)) {
99 m_report.mods |= MOD_BIT(k);
100 } else {
101 add_key_byte(&m_report, k);
102 }
103 }
104}
105
106bool KeyboardReportMatcher::MatchAndExplain(report_keyboard_t& report, MatchResultListener* listener) const {
107 return m_report == report;
108}
109
110void KeyboardReportMatcher::DescribeTo(::std::ostream* os) const {
111 *os << "is equal to " << m_report;
112}
113
114void KeyboardReportMatcher::DescribeNegationTo(::std::ostream* os) const {
115 *os << "is not equal to " << m_report;
116}