Plugin Kaleidoscope-HardwareVirtual is now obsolete. Everything device related has been incorporated in the core repo as a virtual device in kaleidoscope/devices/virtual. Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>pull/729/head
parent
f524955253
commit
0356318fa8
@ -0,0 +1,125 @@
|
||||
/* Kaleidoscope - Firmware for computer input devices
|
||||
* Copyright (C) 2013-2019 Keyboard.io, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||
|
||||
#include "DefaultHIDReportConsumer.h"
|
||||
#include "MultiReport/Keyboard.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include "virtual_io.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace kaleidoscope {
|
||||
|
||||
using namespace logging;
|
||||
|
||||
// For each bit set in 'bitfield', output the corresponding string to 'stream'
|
||||
#define FOREACHBIT(bitfield, stream, str0, str1, str2, str3, str4, str5, str6, str7) \
|
||||
if((bitfield) & 1<<0) stream << str0; \
|
||||
if((bitfield) & 1<<1) stream << str1; \
|
||||
if((bitfield) & 1<<2) stream << str2; \
|
||||
if((bitfield) & 1<<3) stream << str3; \
|
||||
if((bitfield) & 1<<4) stream << str4; \
|
||||
if((bitfield) & 1<<5) stream << str5; \
|
||||
if((bitfield) & 1<<6) stream << str6; \
|
||||
if((bitfield) & 1<<7) stream << str7;
|
||||
|
||||
void DefaultHIDReportConsumer::processHIDReport(
|
||||
uint8_t id, const void *data, int len, int result) {
|
||||
if (id != HID_REPORTID_NKRO_KEYBOARD) {
|
||||
log_info("***Ignoring hid report with id = %d\n", id);
|
||||
return;
|
||||
}
|
||||
|
||||
const HID_KeyboardReport_Data_t &report_data
|
||||
= *static_cast<const HID_KeyboardReport_Data_t *>(data);
|
||||
|
||||
std::stringstream keypresses;
|
||||
bool anything = false;
|
||||
|
||||
if (report_data.modifiers) anything = true;
|
||||
else for (int i = 0; i < KEY_BYTES; i++) if (report_data.keys[i]) {
|
||||
anything = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!anything) {
|
||||
keypresses << "none";
|
||||
} else {
|
||||
FOREACHBIT(report_data.modifiers, keypresses,
|
||||
"lctrl ", "lshift ", "lalt ", "lgui ",
|
||||
"rctrl ", "rshift ", "ralt ", "rgui ")
|
||||
FOREACHBIT(report_data.keys[0], keypresses,
|
||||
"NO_EVENT ", "ERROR_ROLLOVER ", "POST_FAIL ", "ERROR_UNDEFINED ",
|
||||
"a ", "b ", "c ", "d ")
|
||||
FOREACHBIT(report_data.keys[1], keypresses,
|
||||
"e ", "f ", "g ", "h ", "i ", "j ", "k ", "l ")
|
||||
FOREACHBIT(report_data.keys[2], keypresses,
|
||||
"m ", "n ", "o ", "p ", "q ", "r ", "s ", "t ")
|
||||
FOREACHBIT(report_data.keys[3], keypresses,
|
||||
"u ", "v ", "w ", "x ", "y ", "z ", "1/! ", "2/@ ")
|
||||
FOREACHBIT(report_data.keys[4], keypresses,
|
||||
"3/# ", "4/$ ", "5/% ", "6/^ ", "7/& ", "8/* ", "9/( ", "0/) ")
|
||||
FOREACHBIT(report_data.keys[5], keypresses,
|
||||
"enter ", "esc ", "del/bksp ", "tab ",
|
||||
"space ", "-/_ ", "=/+ ", "[/{ ")
|
||||
FOREACHBIT(report_data.keys[6], keypresses,
|
||||
"]/} ", "\\/| ", "#/~ ", ";/: ", "'/\" ", "`/~ ", ",/< ", "./> ")
|
||||
FOREACHBIT(report_data.keys[7], keypresses,
|
||||
"//? ", "capslock ", "F1 ", "F2 ", "F3 ", "F4 ", "F5 ", "F6 ")
|
||||
FOREACHBIT(report_data.keys[8], keypresses,
|
||||
"F7 ", "F8 ", "F9 ", "F10 ", "F11 ", "F12 ", "prtscr ", "scrolllock ")
|
||||
FOREACHBIT(report_data.keys[9], keypresses,
|
||||
"pause ", "ins ", "home ", "pgup ", "del ", "end ", "pgdn ", "r_arrow ")
|
||||
FOREACHBIT(report_data.keys[10], keypresses,
|
||||
"l_arrow ", "d_arrow ", "u_arrow ", "numlock ",
|
||||
"num/ ", "num* ", "num- ", "num+ ")
|
||||
FOREACHBIT(report_data.keys[11], keypresses,
|
||||
"numenter ", "num1 ", "num2 ", "num3 ",
|
||||
"num4 ", "num5 ", "num6 ", "num7 ")
|
||||
FOREACHBIT(report_data.keys[12], keypresses,
|
||||
"num8 ", "num9 ", "num0 ", "num. ", "\\/| ", "app ", "power ", "num= ")
|
||||
FOREACHBIT(report_data.keys[13], keypresses,
|
||||
"F13 ", "F14 ", "F15 ", "F16 ", "F17 ", "F18 ", "F19 ", "F20 ")
|
||||
FOREACHBIT(report_data.keys[14], keypresses,
|
||||
"F21 ", "F22 ", "F23 ", "F24 ", "exec ", "help ", "menu ", "sel ")
|
||||
FOREACHBIT(report_data.keys[15], keypresses,
|
||||
"stop ", "again ", "undo ", "cut ", "copy ", "paste ", "find ", "mute ")
|
||||
FOREACHBIT(report_data.keys[16], keypresses,
|
||||
"volup ", "voldn ", "capslock_l ", "numlock_l ",
|
||||
"scrolllock_l ", "num, ", "num= ", "(other) ")
|
||||
|
||||
for (int i = 17; i < KEY_BYTES; i++) {
|
||||
// A little imprecise, in two ways:
|
||||
// (1) obviously, "(other)" refers to many distinct keys
|
||||
// (2) this might undercount the number of "other" keys pressed
|
||||
// Therefore, if any keys are frequently used, they should be handled above and not via "other"
|
||||
if (report_data.keys[i]) keypresses << "(other) ";
|
||||
}
|
||||
}
|
||||
|
||||
log_info("Sent virtual HID report. Pressed keys: %s\n", keypresses.str().c_str());
|
||||
logUSBEvent_keyboard("Keyboard HID report; pressed keys: " + keypresses.str());
|
||||
}
|
||||
|
||||
} // namespace kaleidoscope
|
||||
|
||||
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
@ -0,0 +1,34 @@
|
||||
/* Kaleidoscope - Firmware for computer input devices
|
||||
* Copyright (C) 2013-2019 Keyboard.io, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace kaleidoscope {
|
||||
|
||||
class DefaultHIDReportConsumer {
|
||||
public:
|
||||
|
||||
static void processHIDReport(uint8_t id, const void *data,
|
||||
int len, int result);
|
||||
};
|
||||
|
||||
} // namespace kaleidoscope
|
||||
|
||||
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (c) 2015, Arduino LLC
|
||||
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
any purpose with or without fee is hereby granted, provided that the
|
||||
above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// This is a modified version of the original HID.cpp from
|
||||
// library KeyboardioHID. It replaces all hardware related stuff
|
||||
// with stub implementations.
|
||||
|
||||
// Include KeyboardioHID's HID.h header
|
||||
//
|
||||
#include "HID.h"
|
||||
|
||||
#include "HIDReportObserver.h"
|
||||
|
||||
#if defined(USBCON)
|
||||
|
||||
HID_ &HID() {
|
||||
static HID_ obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
int HID_::getInterface(uint8_t *interfaceCount) {
|
||||
*interfaceCount += 1; // uses 1
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_::getDescriptor(USBSetup &setup) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t HID_::getShortName(char *name) {
|
||||
name[0] = 'v';
|
||||
name[1] = 'i';
|
||||
name[2] = 'r';
|
||||
name[3] = 't';
|
||||
name[4] = 'u';
|
||||
name[5] = 'a';
|
||||
name[6] = 'l';
|
||||
return 7;
|
||||
}
|
||||
|
||||
void HID_::AppendDescriptor(HIDSubDescriptor *node) {
|
||||
if (!rootNode) {
|
||||
rootNode = node;
|
||||
} else {
|
||||
HIDSubDescriptor *current = rootNode;
|
||||
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
current->next = node;
|
||||
}
|
||||
|
||||
descriptorSize += node->length;
|
||||
}
|
||||
|
||||
int HID_::SendReport(uint8_t id, const void *data, int len) {
|
||||
HIDReportObserver::observeReport(id, data, len, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool HID_::setup(USBSetup &setup) {
|
||||
return true;
|
||||
}
|
||||
|
||||
HID_::HID_(void) : PluggableUSBModule(1, 1, epType),
|
||||
rootNode(NULL), descriptorSize(0),
|
||||
protocol(HID_REPORT_PROTOCOL), idle(1) {
|
||||
setReportData.reportId = 0;
|
||||
setReportData.leds = 0;
|
||||
epType[0] = EP_TYPE_INTERRUPT_IN;
|
||||
//PluggableUSB().plug(this);
|
||||
}
|
||||
|
||||
int HID_::begin(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* if defined(USBCON) */
|
@ -0,0 +1,33 @@
|
||||
/* Kaleidoscope - Firmware for computer input devices
|
||||
* Copyright (C) 2013-2019 Keyboard.io, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace logging {
|
||||
|
||||
static bool __verboseOutputEnabled = true;
|
||||
|
||||
void toggleVerboseOutput(bool state) {
|
||||
__verboseOutputEnabled = state;
|
||||
}
|
||||
|
||||
bool verboseOutputEnabled() {
|
||||
return __verboseOutputEnabled;
|
||||
}
|
||||
|
||||
} // namespace logging
|
||||
} // namespace kaleidoscope
|
@ -0,0 +1,96 @@
|
||||
/* Kaleidoscope - Firmware for computer input devices
|
||||
* Copyright (C) 2013-2019 Keyboard.io, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||
|
||||
#include "utility"
|
||||
#include "stdio.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace logging {
|
||||
|
||||
extern void toggleVerboseOutput(bool state);
|
||||
extern bool verboseOutputEnabled();
|
||||
|
||||
// Please note that we prefer stdio based logging against
|
||||
// stream based output, to stay compatible with possible future global
|
||||
// logging functions introduced by Kaleidoscope. Stream
|
||||
// based logging is not available on the target platform due to restricted
|
||||
// resources.
|
||||
|
||||
// Below, we use perfect forwarding to pass printf style log messages
|
||||
// to different printf derivates. gcc warns when the the format string
|
||||
// is not a literal, which is not the case here due to our forwarding.
|
||||
// To silence the related warning, which is not desired in our application,
|
||||
// we disable the format-security diagnostic until the end of this file.
|
||||
|
||||
// Disable diagnostic for literal format strings.
|
||||
//
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||
|
||||
#ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_debug(Args__&&... args) {}
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_info(Args__&&... args) {}
|
||||
|
||||
#else // #ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_debug(Args__&&... args) {
|
||||
if (verboseOutputEnabled()) {
|
||||
fprintf(stdout, std::forward<Args__>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_info(Args__&&... args) {
|
||||
if (verboseOutputEnabled()) {
|
||||
fprintf(stdout, std::forward<Args__>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef KALEIDOSCOPE_HARDWARE_VIRTUAL_NO_LOGGING
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_error(Args__&&... args) {
|
||||
fprintf(stderr, std::forward<Args__>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args__>
|
||||
inline
|
||||
void log_critical(Args__&&... args) {
|
||||
fprintf(stderr, std::forward<Args__>(args)...);
|
||||
}
|
||||
|
||||
} // namespace logging
|
||||
} // namespace kaleidoscope
|
||||
|
||||
// Re-enable diagnostic for literal format strings.
|
||||
//
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
@ -0,0 +1,396 @@
|
||||
/* -*- mode: c++ -*-
|
||||
* Kaleidoscope-Hardware-Model01 -- Keyboard.io Model01 hardware support for Kaleidoscope
|
||||
* Copyright (C) 2017-2019 Keyboard.io, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||
|
||||
#include "kaleidoscope/device/virtual/Virtual.h"
|
||||
#include "kaleidoscope/device/virtual/DefaultHIDReportConsumer.h"
|
||||
#include "kaleidoscope/device/virtual/Logging.h"
|
||||
|
||||
#include "kaleidoscope/keyswitch_state.h"
|
||||
#include "Kaleidoscope.h"
|
||||
|
||||
#include "HIDReportObserver.h"
|
||||
#include "virtual_io.h"
|
||||
#include "EEPROM.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
|
||||
// FIXME: This relates to virtual/cores/arduino/EEPROM.h.
|
||||
// EEPROM static data must be defined here as only
|
||||
// the device knows about the EEPROM size.
|
||||
//
|
||||
// It might be better to move the EEPROM.h header here as
|
||||
// well???
|
||||
|
||||
uint8_t EERef::eeprom_[kaleidoscope::DeviceProps::StorageProps::length];
|
||||
|
||||
EEPROMClass EEPROM;
|
||||
|
||||
uint16_t EEPROMClass::length() {
|
||||
return kaleidoscope::DeviceProps::StorageProps::length;
|
||||
}
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace device {
|
||||
namespace virt {
|
||||
|
||||
using namespace kaleidoscope::logging;
|
||||
|
||||
//##############################################################################
|
||||
// VirtualKeyScanner
|
||||
//##############################################################################
|
||||
|
||||
VirtualKeyScanner::VirtualKeyScanner()
|
||||
: n_pressed_switches_{0},
|
||||
n_previously_pressed_switches_{0},
|
||||
read_matrix_enabled_{true} {
|
||||
}
|
||||
|
||||
void VirtualKeyScanner::setup() {
|
||||
|
||||
HIDReportObserver::resetHook(&DefaultHIDReportConsumer::processHIDReport);
|
||||
|
||||
for (auto key_addr : KeyAddr::all()) {
|
||||
keystates_[key_addr.toInt()] = KeyState::NotPressed;
|
||||
keystates_prev_[key_addr.toInt()] = KeyState::NotPressed;
|
||||
mask_[key_addr.toInt()] = false;
|
||||
}
|
||||
}
|
||||
|
||||
enum Mode {
|
||||
M_TAP,
|
||||
M_DOWN,
|
||||
M_UP,
|
||||
};
|
||||
|
||||
// FIXME: getRCfromPhysicalKey only works for the Model01 with default
|
||||
// layout. We might want to remove this as the virtual hardware
|
||||
// intents to simulate any type of keyboard.
|
||||
//
|
||||
// static KeyAddr getRCfromPhysicalKey(std::string keyname) {
|
||||
// if (keyname == "prog") return KeyAddr{0, 0};
|
||||
// else if (keyname == "1") return KeyAddr{0, 1};
|
||||
// else if (keyname == "2") return KeyAddr{0, 2};
|
||||
// else if (keyname == "3") return KeyAddr{0, 3};
|
||||
// else if (keyname == "4") return KeyAddr{0, 4};
|
||||
// else if (keyname == "5") return KeyAddr{0, 5};
|
||||
// else if (keyname == "led") return KeyAddr{0, 6};
|
||||
// else if (keyname == "any") return KeyAddr{0, 9};
|
||||
// else if (keyname == "6") return KeyAddr{0, 10};
|
||||
// else if (keyname == "7") return KeyAddr{0, 11};
|
||||
// else if (keyname == "8") return KeyAddr{0, 12};
|
||||
// else if (keyname == "9") return KeyAddr{0, 13};
|
||||
// else if (keyname == "0") return KeyAddr{0, 14};
|
||||
// else if (keyname == "num") return KeyAddr{0, 15};
|
||||
// else if (keyname == "`") return KeyAddr{1, 0};
|
||||
// else if (keyname == "q") return KeyAddr{1, 1};
|
||||
// else if (keyname == "w") return KeyAddr{1, 2};
|
||||
// else if (keyname == "e") return KeyAddr{1, 3};
|
||||
// else if (keyname == "r") return KeyAddr{1, 4};
|
||||
// else if (keyname == "t") return KeyAddr{1, 5};
|
||||
// else if (keyname == "tab") return KeyAddr{1, 6};
|
||||
// else if (keyname == "enter") return KeyAddr{1, 9};
|
||||
// else if (keyname == "y") return KeyAddr{1, 10};
|
||||
// else if (keyname == "u") return KeyAddr{1, 11};
|
||||
// else if (keyname == "i") return KeyAddr{1, 12};
|
||||
// else if (keyname == "o") return KeyAddr{1, 13};
|
||||
// else if (keyname == "p") return KeyAddr{1, 14};
|
||||
// else if (keyname == "=") return KeyAddr{1, 15};
|
||||
// else if (keyname == "pgup") return KeyAddr{2, 0};
|
||||
// else if (keyname == "a") return KeyAddr{2, 1};
|
||||
// else if (keyname == "s") return KeyAddr{2, 2};
|
||||
// else if (keyname == "d") return KeyAddr{2, 3};
|
||||
// else if (keyname == "f") return KeyAddr{2, 4};
|
||||
// else if (keyname == "g") return KeyAddr{2, 5};
|
||||
// else if (keyname == "h") return KeyAddr{2, 10};
|
||||
// else if (keyname == "j") return KeyAddr{2, 11};
|
||||
// else if (keyname == "k") return KeyAddr{2, 12};
|
||||
// else if (keyname == "l") return KeyAddr{2, 13};
|
||||
// else if (keyname == ";") return KeyAddr{2, 14};
|
||||
// else if (keyname == "'") return KeyAddr{2, 15};
|
||||
// else if (keyname == "pgdn") return KeyAddr{3, 0};
|
||||
// else if (keyname == "z") return KeyAddr{3, 1};
|
||||
// else if (keyname == "x") return KeyAddr{3, 2};
|
||||
// else if (keyname == "c") return KeyAddr{3, 3};
|
||||
// else if (keyname == "v") return KeyAddr{3, 4};
|
||||
// else if (keyname == "b") return KeyAddr{3, 5};
|
||||
// else if (keyname == "esc") return KeyAddr{2, 6}; // yes, row 2
|
||||
// else if (keyname == "fly") return KeyAddr{2, 9}; // yes, row 2
|
||||
// else if (keyname == "n") return KeyAddr{3, 10};
|
||||
// else if (keyname == "m") return KeyAddr{3, 11};
|
||||
// else if (keyname == ",") return KeyAddr{3, 12};
|
||||
// else if (keyname == ".") return KeyAddr{3, 13};
|
||||
// else if (keyname == "/") return KeyAddr{3, 14};
|
||||
// else if (keyname == "-") return KeyAddr{3, 15};
|
||||
// else if (keyname == "lctrl") return KeyAddr{0, 7};
|
||||
// else if (keyname == "bksp") return KeyAddr{1, 7};
|
||||
// else if (keyname == "cmd") return KeyAddr{2, 7};
|
||||
// else if (keyname == "lshift") return KeyAddr{3, 7};
|
||||
// else if (keyname == "rshift") return KeyAddr{3, 8};
|
||||
// else if (keyname == "alt") return KeyAddr{2, 8};
|
||||
// else if (keyname == "space") return KeyAddr{1, 8};
|
||||
// else if (keyname == "rctrl") return KeyAddr{0, 8};
|
||||
// else if (keyname == "lfn") return KeyAddr{3, 6};
|
||||
// else if (keyname == "rfn") return KeyAddr{3, 9};
|
||||
//
|
||||
// return KeyAddr{}; // Invalid key
|
||||
// }
|
||||
|
||||
void VirtualKeyScanner::readMatrix() {
|
||||
|
||||
if (!read_matrix_enabled_) return;
|
||||
|
||||
std::stringstream sline;
|
||||
sline << getLineOfInput(anythingHeld());
|
||||
Mode mode = M_TAP;
|
||||
|
||||
while (true) {
|
||||
std::string token;
|
||||
std::getline(sline, token, ' ');
|
||||
|
||||
if (token == "") break; // end of line
|
||||
else if (token == "#") break; // skip the rest of the line
|
||||
else if ((token == "?" || token == "help") && isInteractive()) {
|
||||
printHelp();
|
||||
} else if (token == "Q") {
|
||||
exit(0);
|
||||
} else if (token == "T") {
|
||||
mode = M_TAP;
|
||||
} else if (token == "D") {
|
||||
mode = M_DOWN;
|
||||
} else if (token == "U") {
|
||||
mode = M_UP;
|
||||
} else if (token == "C") {
|
||||
for (auto key_addr : KeyAddr::all()) {
|
||||
keystates_[key_addr.toInt()] = KeyState::NotPressed;
|
||||
}
|
||||
} else {
|
||||
KeyAddr key_addr;
|
||||
|
||||
if (token.front() == '(' && token.back() == ')') {
|
||||
size_t commapos = token.find_first_of(',');
|
||||
|
||||
if (commapos == std::string::npos) {
|
||||
log_error("Bad (r,c) pair: %s\n", token.c_str());
|
||||
continue;
|
||||
} else {
|
||||
key_addr = KeyAddr(
|
||||
(uint8_t)std::stoi(token.substr(1, commapos - 1)),
|
||||
(uint8_t)std::stoi(token.substr(commapos + 1, token.length() - commapos - 1))
|
||||
);
|
||||
|
||||
if (!key_addr.isValid()) {
|
||||
log_error("Bad coordinates: %s\n", token.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: Is there a device independent
|
||||
// way to determine KeyAddr from key names?
|
||||
// key_addr = getRCfromPhysicalKey(token);
|
||||
//
|
||||
// if (!key_addr.isValid()) {
|
||||
// log_error("Unrecognized command: %s\n", token.c_str());
|
||||
// continue;
|
||||
// }
|
||||
}
|
||||
|
||||
keystates_[key_addr.toInt()] =
|
||||
(mode == M_DOWN) ? KeyState::Pressed :
|
||||
(mode == M_UP) ? KeyState::NotPressed :
|
||||
KeyState::Tap;
|
||||
}
|
||||
}
|
||||
}
|
||||
void VirtualKeyScanner::actOnMatrixScan() {
|
||||
|
||||
n_pressed_switches_ = 0;
|
||||
n_previously_pressed_switches_ = 0;
|
||||
|
||||
for (auto key_addr : KeyAddr::all()) {
|
||||
uint8_t key_state = 0;
|
||||
|
||||
switch (keystates_prev_[key_addr.toInt()]) {
|
||||
case KeyState::Pressed:
|
||||
key_state |= WAS_PRESSED;
|
||||
++n_previously_pressed_switches_;
|
||||
break;
|
||||
|
||||
case KeyState::Tap:
|
||||
log_error("Error: assertion failed, keystates_prev_ should not be KeyState::Tap\n");
|
||||
break;
|
||||
|
||||
case KeyState::NotPressed:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (keystates_[key_addr.toInt()]) {
|
||||
case KeyState::Pressed:
|
||||
case KeyState::Tap:
|
||||
key_state |= IS_PRESSED;
|
||||
++n_pressed_switches_;
|
||||
break;
|
||||
|
||||
case KeyState::NotPressed:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
handleKeyswitchEvent(Key_NoKey, key_addr, key_state);
|
||||
keystates_prev_[key_addr.toInt()] = keystates_[key_addr.toInt()];
|
||||
|
||||
if (keystates_[key_addr.toInt()] == KeyState::Tap) {
|
||||
key_state = WAS_PRESSED & ~IS_PRESSED;
|
||||
handleKeyswitchEvent(Key_NoKey, key_addr, key_state);
|
||||
keystates_[key_addr.toInt()] = KeyState::NotPressed;
|
||||
keystates_prev_[key_addr.toInt()] = KeyState::NotPressed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t VirtualKeyScanner::pressedKeyswitchCount() const {
|
||||
return n_pressed_switches_;
|
||||
}
|
||||
bool VirtualKeyScanner::isKeyswitchPressed(KeyAddr key_addr) const {
|
||||
if (keystates_[key_addr.toInt()] == KeyState::NotPressed) {
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t VirtualKeyScanner::previousPressedKeyswitchCount() const {
|
||||
return n_previously_pressed_switches_;
|
||||
}
|
||||
bool VirtualKeyScanner::wasKeyswitchPressed(KeyAddr key_addr) const {
|
||||
if (keystates_prev_[key_addr.toInt()] == KeyState::NotPressed) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VirtualKeyScanner::maskKey(KeyAddr key_addr) {
|
||||
if (!key_addr.isValid()) {
|
||||
log_error("Virtual::maskKey: key_addr invalid\n");
|
||||
return;
|
||||
}
|
||||
mask_[key_addr.toInt()] = true;
|
||||
}
|
||||
|
||||
void VirtualKeyScanner::unMaskKey(KeyAddr key_addr) {
|
||||
if (!key_addr.isValid()) {
|
||||
log_error("Virtual::unMaskKey: key_addr invalid\n");
|
||||
return;
|
||||
}
|
||||
mask_[key_addr.toInt()] = false;
|
||||
}
|
||||
|
||||
bool VirtualKeyScanner::isKeyMasked(KeyAddr key_addr) const {
|
||||
if (!key_addr.isValid()) {
|
||||
log_error("Virtual::isKeyMasked: key_addr invalid\n");
|
||||
return false;
|
||||
}
|
||||
return mask_[key_addr.toInt()];
|
||||
}
|
||||
|
||||
void VirtualKeyScanner::setKeystate(KeyAddr keyAddr, KeyState ks) {
|
||||
keystates_[keyAddr.toInt()] = ks;
|
||||
}
|
||||
|
||||
VirtualKeyScanner::KeyState VirtualKeyScanner::getKeystate(KeyAddr keyAddr) const {
|
||||
return keystates_[keyAddr.toInt()];
|
||||
}
|
||||
|
||||
bool VirtualKeyScanner::anythingHeld() {
|
||||
for (auto key_addr : KeyAddr::all()) {
|
||||
if (keystates_[key_addr.toInt()] == KeyState::Pressed) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//##############################################################################
|
||||
// VirtualLEDDriver
|
||||
//##############################################################################
|
||||
|
||||
void VirtualLEDDriver::setup() {
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
led_states_[i] = CRGB(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualLEDDriver::syncLeds() {
|
||||
// log format: red.green.blue where values are written in hex; followed by a space, followed by the next LED
|
||||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
|
||||
for (int i = 0; i < led_count; i++) {
|
||||
const cRGB state = led_states_[i];
|
||||
ss << (unsigned int) state.r << "." << (unsigned int) state.g << "." << (unsigned int) state.b << " ";
|
||||
}
|
||||
|
||||
ss << std::endl;
|
||||
logLEDStates(ss.str());
|
||||
}
|
||||
|
||||
void VirtualLEDDriver::setCrgbAt(uint8_t i, cRGB color) {
|
||||
if ((int)i >= (int)led_count) {
|
||||
log_error("Virtual::setCrgbAt: Index %d out of bounds\n", i);
|
||||
return;
|
||||
}
|
||||
led_states_[i] = color;
|
||||
}
|
||||
|
||||
cRGB VirtualLEDDriver::getCrgbAt(uint8_t i) const {
|
||||
if ((int)i >= (int)led_count) {
|
||||
log_error("Virtual::getCrgbAt: Index %d out of bounds\n", i);
|
||||
return CRGB(0, 0, 0);
|
||||
}
|
||||
return led_states_[i];
|
||||
}
|
||||
|
||||
uint8_t VirtualLEDDriver::getLedIndex(uint8_t key_offset) const {
|
||||
return kaleidoscope::DeviceProps::LEDDriverProps::getLedIndex(key_offset);
|
||||
}
|
||||
|
||||
} // namespace virt
|
||||
} // namespace device
|
||||
|
||||
|
||||
namespace driver {
|
||||
namespace led {
|
||||
|
||||
template<>
|
||||
Base<kaleidoscope::DeviceProps::LEDDriverProps>::LEDs
|
||||
Base<kaleidoscope::DeviceProps::LEDDriverProps>::LEDs_{};
|
||||
|
||||
} // namespace led
|
||||
} // namespace driver
|
||||
|
||||
} // namespace kaleidoscope
|
||||
|
||||
|
||||
|
||||
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
@ -0,0 +1,160 @@
|
||||
/* -*- mode: c++ -*-
|
||||
* Kaleidoscope-Hardware-Model01 -- Keyboard.io Model01 hardware support for Kaleidoscope
|
||||
* Copyright (C) 2017-2019 Keyboard.io, Inc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||
|
||||
#include KALEIDOSCOPE_HARDWARE_H
|
||||
|
||||
#include "kaleidoscope/driver/bootloader/None.h"
|
||||
#include "kaleidoscope/driver/led/Base.h"
|
||||
|
||||
namespace kaleidoscope {
|
||||
namespace device {
|
||||
namespace virt {
|
||||
|
||||
class VirtualKeyScanner
|
||||
: public kaleidoscope::driver::keyscanner::Base<kaleidoscope::DeviceProps::KeyScannerProps> {
|
||||
private:
|
||||
|
||||
typedef VirtualKeyScanner ThisType;
|
||||
typedef kaleidoscope::driver::keyscanner::Base<kaleidoscope::DeviceProps::KeyScannerProps> ParentType;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename ParentType::KeyAddr KeyAddr;
|
||||
|
||||
enum class KeyState {
|
||||
Pressed,
|
||||
NotPressed,
|
||||
Tap
|
||||
};
|
||||
|
||||
static constexpr uint8_t matrix_rows = kaleidoscope::DeviceProps::KeyScannerProps::matrix_rows;
|
||||
static constexpr uint8_t matrix_columns = kaleidoscope::DeviceProps::KeyScannerProps::matrix_columns;
|
||||
|
||||
VirtualKeyScanner();
|
||||
|
||||
void setup();
|
||||
void readMatrix();
|
||||
void scanMatrix() {
|
||||
this->readMatrix();
|
||||
this->actOnMatrixScan();
|
||||
}
|
||||
void actOnMatrixScan();
|
||||
|
||||
uint8_t pressedKeyswitchCount() const;
|
||||
bool isKeyswitchPressed(KeyAddr key_addr) const;
|
||||
|
||||
uint8_t previousPressedKeyswitchCount() const;
|
||||
bool wasKeyswitchPressed(KeyAddr key_addr) const;
|
||||
|
||||
void maskKey(KeyAddr key_addr);
|
||||
void unMaskKey(KeyAddr key_addr);
|
||||
bool isKeyMasked(KeyAddr key_addr) const;
|
||||
|
||||
void setEnableReadMatrix(bool state) {
|
||||
read_matrix_enabled_ = state;
|
||||
}
|
||||
|
||||
void setKeystate(KeyAddr keyAddr, KeyState ks);
|
||||
KeyState getKeystate(KeyAddr keyAddr) const;
|
||||
|
||||
private:
|
||||
|
||||
bool anythingHeld();
|
||||
|
||||
private:
|
||||
|
||||
uint8_t n_pressed_switches_,
|
||||
n_previously_pressed_switches_;
|
||||
|
||||
bool read_matrix_enabled_;
|
||||
|
||||
KeyState keystates_[matrix_rows * matrix_columns];
|
||||
KeyState keystates_prev_[matrix_rows * matrix_columns];
|
||||
|
||||
bool mask_[matrix_rows * matrix_columns];
|
||||
};
|
||||
|
||||
class VirtualLEDDriver
|
||||
: public driver::led::Base<kaleidoscope::DeviceProps::LEDDriverProps> {
|
||||
public:
|
||||
|
||||
typedef driver::led::Base<kaleidoscope::DeviceProps::LEDDriverProps>
|
||||
ParentType;
|
||||
|
||||
using typename ParentType::LEDs;
|
||||
|
||||
static constexpr uint8_t led_count = kaleidoscope::DeviceProps::LEDDriverProps::led_count;
|
||||
|
||||
void setup();
|
||||
void syncLeds();
|
||||
void setCrgbAt(uint8_t i, cRGB color);
|
||||
cRGB getCrgbAt(uint8_t i) const;
|
||||
uint8_t getLedIndex(uint8_t key_offset) const;
|
||||
|
||||
private:
|
||||
|
||||
cRGB led_states_[led_count];
|
||||
};
|
||||
|
||||
// This overrides only the drivers and keeps the driver props of
|
||||
// the physical keyboard.
|
||||
//
|
||||
struct VirtualProps : public kaleidoscope::DeviceProps {
|
||||
typedef typename kaleidoscope::DeviceProps::KeyScannerProps
|
||||
KeyScannerProps;
|
||||
typedef VirtualKeyScanner
|
||||
KeyScanner;
|
||||
typedef KeyScannerProps::KeyAddr
|
||||
KeyAddr;
|
||||
|
||||
typedef typename kaleidoscope::DeviceProps::LEDDriverProps
|
||||
LEDDriverProps;
|
||||
typedef VirtualLEDDriver
|
||||
LEDDriver;
|
||||
|
||||
typedef kaleidoscope::driver::mcu::None MCU;
|
||||
|
||||
typedef kaleidoscope::driver::bootloader::None
|
||||
BootLoader;
|
||||
|
||||
typedef typename kaleidoscope::DeviceProps::StorageProps
|
||||
StorageProps;
|
||||
typedef typename kaleidoscope::DeviceProps::Storage
|
||||
Storage;
|
||||
};
|
||||
|
||||
class VirtualDevice
|
||||
: public kaleidoscope::device::Base<device::virt::VirtualProps> {
|
||||
public:
|
||||
|
||||
auto serialPort() -> decltype(Serial) & {
|
||||
return Serial;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace virt
|
||||
} // namespace device
|
||||
|
||||
typedef device::virt::VirtualDevice Device;
|
||||
|
||||
} // namespace kaleidoscope
|
||||
|
||||
#endif // ifdef KALEIDOSCOPE_VIRTUAL_BUILD
|
Loading…
Reference in new issue