Separate 6KRO and NKRO report structs

This commit is contained in:
fauxpark 2023-10-13 19:35:15 +11:00
parent 527a4ee846
commit c1ed464b7a
24 changed files with 221 additions and 180 deletions

View File

@ -31,7 +31,7 @@ static void ap2_ble_swtich_ble_driver(void);
/* -------------------- Static Local Variables ------------------------------ */ /* -------------------- Static Local Variables ------------------------------ */
static host_driver_t ap2_ble_driver = { static host_driver_t ap2_ble_driver = {
ap2_ble_leds, ap2_ble_keyboard, ap2_ble_mouse, ap2_ble_extra ap2_ble_leds, ap2_ble_keyboard, NULL, ap2_ble_mouse, ap2_ble_extra
}; };
static uint8_t ble_mcu_wakeup[11] = {0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x01, 0x7d, 0x02, 0x01, 0x02}; static uint8_t ble_mcu_wakeup[11] = {0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x01, 0x7d, 0x02, 0x01, 0x02};
@ -167,5 +167,5 @@ static void ap2_ble_extra(report_extra_t *report) {
static void ap2_ble_keyboard(report_keyboard_t *report) { static void ap2_ble_keyboard(report_keyboard_t *report) {
sdPut(&SD1, 0x0); sdPut(&SD1, 0x0);
sdWrite(&SD1, ble_mcu_send_report, sizeof(ble_mcu_send_report)); sdWrite(&SD1, ble_mcu_send_report, sizeof(ble_mcu_send_report));
sdWrite(&SD1, &report->raw[0], KEYBOARD_REPORT_SIZE); sdWrite(&SD1, (uint8_t *)report, KEYBOARD_REPORT_SIZE);
} }

View File

@ -86,13 +86,12 @@ void bluetooth_send_keyboard(report_keyboard_t *report)
send_str(PSTR("AT+BLEKEYBOARDCODE=")); send_str(PSTR("AT+BLEKEYBOARDCODE="));
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) send_bytes(report->mods);
{ send_str(PSTR("-"));
send_bytes(report->raw[i]); send_bytes(0);
if (i < (KEYBOARD_EPSIZE - 1)) for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
{ send_str(PSTR("-"));
send_str(PSTR("-")); send_bytes(report->keys[i]);
}
} }
send_str(PSTR("\r\n")); send_str(PSTR("\r\n"));

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#define WS2812_SPI SPID1 #define WS2812_SPI_DRIVER SPID1
#define WS2812_SPI_MOSI_PAL_MODE 5 #define WS2812_SPI_MOSI_PAL_MODE 5
#define WS2812_SPI_SCK_PIN B13 #define WS2812_SPI_SCK_PIN B13
#define WS2812_SPI_SCK_PAL_MODE 5 #define WS2812_SPI_SCK_PAL_MODE 5

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#define WS2812_SPI SPID2 #define WS2812_SPI_DRIVER SPID2
#define WS2812_SPI_MOSI_PAL_MODE 5 #define WS2812_SPI_MOSI_PAL_MODE 5
#define WS2812_SPI_SCK_PIN B13 #define WS2812_SPI_SCK_PIN B13
#define WS2812_SPI_SCK_PAL_MODE 5 #define WS2812_SPI_SCK_PAL_MODE 5

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#define WS2812_SPI SPID1 #define WS2812_SPI_DRIVER SPID1
#define WS2812_SPI_MOSI_PAL_MODE 5 #define WS2812_SPI_MOSI_PAL_MODE 5
#define WS2812_SPI_SCK_PIN B13 #define WS2812_SPI_SCK_PIN B13
#define WS2812_SPI_SCK_PAL_MODE 5 #define WS2812_SPI_SCK_PAL_MODE 5

View File

@ -925,7 +925,7 @@ __attribute__((weak)) void register_code(uint8_t code) {
// Force a new key press if the key is already pressed // Force a new key press if the key is already pressed
// without this, keys with the same keycode, but different // without this, keys with the same keycode, but different
// modifiers will be reported incorrectly, see issue #1708 // modifiers will be reported incorrectly, see issue #1708
if (is_key_pressed(keyboard_report, code)) { if (is_key_pressed(code)) {
del_key(code); del_key(code);
send_keyboard_report(); send_keyboard_report();
} }

View File

@ -35,6 +35,9 @@ static uint8_t suppressed_mods = 0;
// TODO: pointer variable is not needed // TODO: pointer variable is not needed
// report_keyboard_t keyboard_report = {}; // report_keyboard_t keyboard_report = {};
report_keyboard_t *keyboard_report = &(report_keyboard_t){}; report_keyboard_t *keyboard_report = &(report_keyboard_t){};
#ifdef NKRO_ENABLE
report_nkro_t *nkro_report = &(report_nkro_t){};
#endif
extern inline void add_key(uint8_t key); extern inline void add_key(uint8_t key);
extern inline void del_key(uint8_t key); extern inline void del_key(uint8_t key);
@ -256,7 +259,7 @@ bool is_oneshot_enabled(void) {
* *
* FIXME: needs doc * FIXME: needs doc
*/ */
void send_keyboard_report(void) { void send_6kro_report(void) {
keyboard_report->mods = real_mods; keyboard_report->mods = real_mods;
keyboard_report->mods |= weak_mods; keyboard_report->mods |= weak_mods;
@ -269,7 +272,7 @@ void send_keyboard_report(void) {
} }
# endif # endif
keyboard_report->mods |= oneshot_mods; keyboard_report->mods |= oneshot_mods;
if (has_anykey(keyboard_report)) { if (has_anykey()) {
clear_oneshot_mods(); clear_oneshot_mods();
} }
} }
@ -295,6 +298,53 @@ void send_keyboard_report(void) {
#endif #endif
} }
#ifdef NKRO_ENABLE
void send_nkro_report(void) {
nkro_report->mods = real_mods | weak_mods;
# ifndef NO_ACTION_ONESHOT
if (oneshot_mods) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_mods_timed_out()) {
dprintf("Oneshot: timeout\n");
clear_oneshot_mods();
}
# endif
nkro_report->mods |= oneshot_mods;
if (has_anykey()) {
clear_oneshot_mods();
}
}
# endif
# ifdef KEY_OVERRIDE_ENABLE
// These need to be last to be able to properly control key overrides
nkro_report->mods &= ~suppressed_mods;
nkro_report->mods |= weak_override_mods;
# endif
static report_nkro_t last_report;
/* Only send the report if there are changes to propagate to the host. */
if (memcmp(nkro_report, &last_report, sizeof(report_nkro_t)) != 0) {
memcpy(&last_report, nkro_report, sizeof(report_nkro_t));
host_nkro_send(nkro_report);
}
}
#endif
void send_keyboard_report(void) {
#ifdef NKRO_ENABLE
if (keymap_config.nkro) {
send_nkro_report();
} else {
send_6kro_report();
}
#else
send_6kro_report();
#endif
}
/** \brief Get mods /** \brief Get mods
* *
* FIXME: needs doc * FIXME: needs doc

View File

@ -26,20 +26,23 @@ extern "C" {
#endif #endif
extern report_keyboard_t *keyboard_report; extern report_keyboard_t *keyboard_report;
#ifdef NKRO_ENABLE
extern report_nkro_t *nkro_report;
#endif
void send_keyboard_report(void); void send_keyboard_report(void);
/* key */ /* key */
inline void add_key(uint8_t key) { inline void add_key(uint8_t key) {
add_key_to_report(keyboard_report, key); add_key_to_report(key);
} }
inline void del_key(uint8_t key) { inline void del_key(uint8_t key) {
del_key_from_report(keyboard_report, key); del_key_from_report(key);
} }
inline void clear_keys(void) { inline void clear_keys(void) {
clear_keys_from_report(keyboard_report); clear_keys_from_report();
} }
/* modifier */ /* modifier */

View File

@ -95,12 +95,12 @@ std::ostream& operator<<(std::ostream& os, const report_keyboard_t& report) {
} }
KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) { KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) {
memset(m_report.raw, 0, sizeof(m_report.raw)); memset(&m_report, 0, sizeof(report_keyboard_t));
for (auto k : keys) { for (auto k : keys) {
if (IS_MODIFIER_KEYCODE(k)) { if (IS_MODIFIER_KEYCODE(k)) {
m_report.mods |= MOD_BIT(k); m_report.mods |= MOD_BIT(k);
} else { } else {
add_key_to_report(&m_report, k); add_key_byte(&m_report, k);
} }
} }
} }

View File

@ -19,21 +19,21 @@
#include <ostream> #include <ostream>
#include "gmock/gmock.h" #include "gmock/gmock.h"
bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs); bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs);
std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& value); std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& value);
class KeyboardReportMatcher : public testing::MatcherInterface<report_keyboard_t&> { class KeyboardReportMatcher : public testing::MatcherInterface<report_keyboard_t&> {
public: public:
KeyboardReportMatcher(const std::vector<uint8_t>& keys); KeyboardReportMatcher(const std::vector<uint8_t>& keys);
virtual bool MatchAndExplain(report_keyboard_t& report, testing::MatchResultListener* listener) const override; virtual bool MatchAndExplain(report_keyboard_t& report, testing::MatchResultListener* listener) const override;
virtual void DescribeTo(::std::ostream* os) const override; virtual void DescribeTo(::std::ostream* os) const override;
virtual void DescribeNegationTo(::std::ostream* os) const override; virtual void DescribeNegationTo(::std::ostream* os) const override;
private:
private:
report_keyboard_t m_report; report_keyboard_t m_report;
}; };
template <typename... Ts>
template<typename... Ts>
inline testing::Matcher<report_keyboard_t&> KeyboardReport(Ts... keys) { inline testing::Matcher<report_keyboard_t&> KeyboardReport(Ts... keys) {
return testing::MakeMatcher(new KeyboardReportMatcher(std::vector<uint8_t>({keys...}))); return testing::MakeMatcher(new KeyboardReportMatcher(std::vector<uint8_t>({keys...})));
} }

View File

@ -31,7 +31,7 @@ uint8_t hex_digit_to_keycode(uint8_t digit) {
} }
} // namespace } // namespace
TestDriver::TestDriver() : m_driver{&TestDriver::keyboard_leds, &TestDriver::send_keyboard, &TestDriver::send_mouse, &TestDriver::send_extra} { TestDriver::TestDriver() : m_driver{&TestDriver::keyboard_leds, &TestDriver::send_keyboard, &TestDriver::send_nkro, &TestDriver::send_mouse, &TestDriver::send_extra} {
host_set_driver(&m_driver); host_set_driver(&m_driver);
m_this = this; m_this = this;
} }
@ -49,6 +49,10 @@ void TestDriver::send_keyboard(report_keyboard_t* report) {
m_this->send_keyboard_mock(*report); m_this->send_keyboard_mock(*report);
} }
void TestDriver::send_nkro(report_nkro_t* report) {
m_this->send_nkro_mock(*report);
}
void TestDriver::send_mouse(report_mouse_t* report) { void TestDriver::send_mouse(report_mouse_t* report) {
m_this->send_mouse_mock(*report); m_this->send_mouse_mock(*report);
} }

View File

@ -32,12 +32,14 @@ class TestDriver {
} }
MOCK_METHOD1(send_keyboard_mock, void(report_keyboard_t&)); MOCK_METHOD1(send_keyboard_mock, void(report_keyboard_t&));
MOCK_METHOD1(send_nkro_mock, void(report_nkro_t&));
MOCK_METHOD1(send_mouse_mock, void(report_mouse_t&)); MOCK_METHOD1(send_mouse_mock, void(report_mouse_t&));
MOCK_METHOD1(send_extra_mock, void(report_extra_t&)); MOCK_METHOD1(send_extra_mock, void(report_extra_t&));
private: private:
static uint8_t keyboard_leds(void); static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t* report); static void send_keyboard(report_keyboard_t* report);
static void send_nkro(report_nkro_t* report);
static void send_mouse(report_mouse_t* report); static void send_mouse(report_mouse_t* report);
static void send_extra(report_extra_t* report); static void send_extra(report_extra_t* report);
host_driver_t m_driver; host_driver_t m_driver;

View File

@ -46,9 +46,7 @@ else
endif endif
ifeq ($(strip $(NKRO_ENABLE)), yes) ifeq ($(strip $(NKRO_ENABLE)), yes)
ifeq ($(PROTOCOL), VUSB) ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
$(info NKRO is not currently supported on V-USB, and has been disabled.)
else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
$(info NKRO is not currently supported with Bluetooth, and has been disabled.) $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
else else
OPT_DEFS += -DNKRO_ENABLE OPT_DEFS += -DNKRO_ENABLE

View File

@ -36,6 +36,7 @@ uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; // Saved USB state from ha
void main_subtasks(void); void main_subtasks(void);
uint8_t keyboard_leds(void); uint8_t keyboard_leds(void);
void send_keyboard(report_keyboard_t *report); void send_keyboard(report_keyboard_t *report);
void send_nkro(report_nkro_t *report);
void send_mouse(report_mouse_t *report); void send_mouse(report_mouse_t *report);
void send_extra(report_extra_t *report); void send_extra(report_extra_t *report);
@ -43,7 +44,7 @@ void send_extra(report_extra_t *report);
void deferred_exec_task(void); void deferred_exec_task(void);
#endif // DEFERRED_EXEC_ENABLE #endif // DEFERRED_EXEC_ENABLE
host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
uint8_t led_states; uint8_t led_states;
@ -59,41 +60,41 @@ uint8_t keyboard_leds(void) {
void send_keyboard(report_keyboard_t *report) { void send_keyboard(report_keyboard_t *report) {
uint32_t irqflags; uint32_t irqflags;
while (udi_hid_kbd_b_report_trans_ongoing) {
main_subtasks();
} // Run other tasks while waiting for USB to be free
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
memcpy(udi_hid_kbd_report, report, UDI_HID_KBD_REPORT_SIZE);
udi_hid_kbd_b_report_valid = 1;
udi_hid_kbd_send_report();
__DMB();
__set_PRIMASK(irqflags);
}
void send_nkro(report_nkro_t *report) {
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (!keymap_config.nkro) { uint32_t irqflags;
#endif // NKRO_ENABLE
while (udi_hid_kbd_b_report_trans_ongoing) {
main_subtasks();
} // Run other tasks while waiting for USB to be free
irqflags = __get_PRIMASK(); while (udi_hid_nkro_b_report_trans_ongoing) {
__disable_irq(); main_subtasks();
__DMB(); } // Run other tasks while waiting for USB to be free
memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE); irqflags = __get_PRIMASK();
udi_hid_kbd_b_report_valid = 1; __disable_irq();
udi_hid_kbd_send_report(); __DMB();
__DMB(); memcpy(udi_hid_nkro_report, report, UDI_HID_NKRO_REPORT_SIZE);
__set_PRIMASK(irqflags); udi_hid_nkro_b_report_valid = 1;
#ifdef NKRO_ENABLE udi_hid_nkro_send_report();
} else {
while (udi_hid_nkro_b_report_trans_ongoing) {
main_subtasks();
} // Run other tasks while waiting for USB to be free
irqflags = __get_PRIMASK(); __DMB();
__disable_irq(); __set_PRIMASK(irqflags);
__DMB(); #endif
memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
udi_hid_nkro_b_report_valid = 1;
udi_hid_nkro_send_report();
__DMB();
__set_PRIMASK(irqflags);
}
#endif // NKRO_ENABLE
} }
void send_mouse(report_mouse_t *report) { void send_mouse(report_mouse_t *report) {

View File

@ -59,11 +59,12 @@
/* declarations */ /* declarations */
uint8_t keyboard_leds(void); uint8_t keyboard_leds(void);
void send_keyboard(report_keyboard_t *report); void send_keyboard(report_keyboard_t *report);
void send_nkro(report_nkro_t *report);
void send_mouse(report_mouse_t *report); void send_mouse(report_mouse_t *report);
void send_extra(report_extra_t *report); void send_extra(report_extra_t *report);
/* host struct */ /* host struct */
host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
#ifdef VIRTSER_ENABLE #ifdef VIRTSER_ENABLE
void virtser_task(void); void virtser_task(void);

View File

@ -71,7 +71,7 @@ static virtual_timer_t keyboard_idle_timer;
static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg); static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg);
report_keyboard_t keyboard_report_sent = {{0}}; report_keyboard_t keyboard_report_sent = {0};
report_mouse_t mouse_report_sent = {0}; report_mouse_t mouse_report_sent = {0};
union { union {
@ -883,26 +883,22 @@ void send_report(uint8_t endpoint, void *report, size_t size) {
/* prepare and start sending a report IN /* prepare and start sending a report IN
* not callable from ISR or locked state */ * not callable from ISR or locked state */
void send_keyboard(report_keyboard_t *report) { void send_keyboard(report_keyboard_t *report) {
uint8_t ep = KEYBOARD_IN_EPNUM;
size_t size = KEYBOARD_REPORT_SIZE;
/* If we're in Boot Protocol, don't send any report ID or other funky fields */ /* If we're in Boot Protocol, don't send any report ID or other funky fields */
if (!keyboard_protocol) { if (!keyboard_protocol) {
send_report(ep, &report->mods, 8); send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);
} else { } else {
#ifdef NKRO_ENABLE send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);
if (keymap_config.nkro) {
ep = SHARED_IN_EPNUM;
size = sizeof(struct nkro_report);
}
#endif
send_report(ep, report, size);
} }
keyboard_report_sent = *report; keyboard_report_sent = *report;
} }
void send_nkro(report_nkro_t *report) {
#ifdef NKRO_ENABLE
send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t));
#endif
}
/* --------------------------------------------------------- /* ---------------------------------------------------------
* Mouse functions * Mouse functions
* --------------------------------------------------------- * ---------------------------------------------------------

View File

@ -81,26 +81,29 @@ void host_keyboard_send(report_keyboard_t *report) {
#endif #endif
if (!driver) return; if (!driver) return;
#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
if (keyboard_protocol && keymap_config.nkro) {
/* The callers of this function assume that report->mods is where mods go in.
* But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
*/
report->nkro.mods = report->mods;
report->nkro.report_id = REPORT_ID_NKRO;
} else
#endif
{
#ifdef KEYBOARD_SHARED_EP #ifdef KEYBOARD_SHARED_EP
report->report_id = REPORT_ID_KEYBOARD; report->report_id = REPORT_ID_KEYBOARD;
#endif #endif
}
(*driver->send_keyboard)(report); (*driver->send_keyboard)(report);
if (debug_keyboard) { if (debug_keyboard) {
dprint("keyboard_report: "); dprintf("keyboard_report: %02X | ", report->mods);
for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
dprintf("%02X ", report->raw[i]); dprintf("%02X ", report->keys[i]);
}
dprint("\n");
}
}
void host_nkro_send(report_nkro_t *report) {
if (!driver) return;
report->report_id = REPORT_ID_NKRO;
(*driver->send_nkro)(report);
if (debug_keyboard) {
dprintf("nkro_report: %02X | ", report->mods);
for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) {
dprintf("%02X ", report->bits[i]);
} }
dprint("\n"); dprint("\n");
} }

View File

@ -38,6 +38,7 @@ host_driver_t *host_get_driver(void);
uint8_t host_keyboard_leds(void); uint8_t host_keyboard_leds(void);
led_t host_keyboard_led_state(void); led_t host_keyboard_led_state(void);
void host_keyboard_send(report_keyboard_t *report); void host_keyboard_send(report_keyboard_t *report);
void host_nkro_send(report_nkro_t *report);
void host_mouse_send(report_mouse_t *report); void host_mouse_send(report_mouse_t *report);
void host_system_send(uint16_t usage); void host_system_send(uint16_t usage);
void host_consumer_send(uint16_t usage); void host_consumer_send(uint16_t usage);

View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
typedef struct { typedef struct {
uint8_t (*keyboard_leds)(void); uint8_t (*keyboard_leds)(void);
void (*send_keyboard)(report_keyboard_t *); void (*send_keyboard)(report_keyboard_t *);
void (*send_nkro)(report_nkro_t *);
void (*send_mouse)(report_mouse_t *); void (*send_mouse)(report_mouse_t *);
void (*send_extra)(report_extra_t *); void (*send_extra)(report_extra_t *);
} host_driver_t; } host_driver_t;

View File

@ -55,12 +55,6 @@
#include "usb_device_state.h" #include "usb_device_state.h"
#include <util/atomic.h> #include <util/atomic.h>
#ifdef NKRO_ENABLE
# include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif
#ifdef VIRTSER_ENABLE #ifdef VIRTSER_ENABLE
# include "virtser.h" # include "virtser.h"
#endif #endif
@ -83,9 +77,10 @@ static report_keyboard_t keyboard_report_sent;
/* Host driver */ /* Host driver */
static uint8_t keyboard_leds(void); static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report); static void send_keyboard(report_keyboard_t *report);
static void send_nkro(report_nkro_t *report);
static void send_mouse(report_mouse_t *report); static void send_mouse(report_mouse_t *report);
static void send_extra(report_extra_t *report); static void send_extra(report_extra_t *report);
host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
void send_report(uint8_t endpoint, void *report, size_t size) { void send_report(uint8_t endpoint, void *report, size_t size) {
uint8_t timeout = 255; uint8_t timeout = 255;
@ -559,27 +554,26 @@ static uint8_t keyboard_leds(void) {
* FIXME: Needs doc * FIXME: Needs doc
*/ */
static void send_keyboard(report_keyboard_t *report) { static void send_keyboard(report_keyboard_t *report) {
/* Select the Keyboard Report Endpoint */
uint8_t ep = KEYBOARD_IN_EPNUM;
uint8_t size = KEYBOARD_REPORT_SIZE;
/* If we're in Boot Protocol, don't send any report ID or other funky fields */ /* If we're in Boot Protocol, don't send any report ID or other funky fields */
if (!keyboard_protocol) { if (!keyboard_protocol) {
send_report(ep, &report->mods, 8); send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);
} else { } else {
#ifdef NKRO_ENABLE send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);
if (keymap_config.nkro) {
ep = SHARED_IN_EPNUM;
size = sizeof(struct nkro_report);
}
#endif
send_report(ep, report, size);
} }
keyboard_report_sent = *report; keyboard_report_sent = *report;
} }
/** \brief Send NKRO
*
* FIXME: Needs doc
*/
static void send_nkro(report_nkro_t *report) {
#ifdef NKRO_ENABLE
send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t));
#endif
}
/** \brief Send Mouse /** \brief Send Mouse
* *
* FIXME: Needs doc * FIXME: Needs doc

View File

@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "action_util.h"
#include "report.h" #include "report.h"
#include "host.h" #include "host.h"
#include "keycode_config.h" #include "keycode_config.h"
@ -35,14 +36,14 @@ static int8_t cb_count = 0;
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
uint8_t has_anykey(report_keyboard_t* keyboard_report) { uint8_t has_anykey(void) {
uint8_t cnt = 0; uint8_t cnt = 0;
uint8_t* p = keyboard_report->keys; uint8_t* p = keyboard_report->keys;
uint8_t lp = sizeof(keyboard_report->keys); uint8_t lp = sizeof(keyboard_report->keys);
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
p = keyboard_report->nkro.bits; p = nkro_report->bits;
lp = sizeof(keyboard_report->nkro.bits); lp = sizeof(nkro_report->bits);
} }
#endif #endif
while (lp--) { while (lp--) {
@ -55,13 +56,13 @@ uint8_t has_anykey(report_keyboard_t* keyboard_report) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
uint8_t get_first_key(report_keyboard_t* keyboard_report) { uint8_t get_first_key(void) {
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
uint8_t i = 0; uint8_t i = 0;
for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++)
; ;
return i << 3 | biton(keyboard_report->nkro.bits[i]); return i << 3 | biton(nkro_report->bits[i]);
} }
#endif #endif
#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE
@ -83,20 +84,20 @@ uint8_t get_first_key(report_keyboard_t* keyboard_report) {
* Returns true if the keyboard_report reports that the key is pressed, otherwise false * Returns true if the keyboard_report reports that the key is pressed, otherwise false
* Note: The function doesn't support modifers currently, and it returns false for KC_NO * Note: The function doesn't support modifers currently, and it returns false for KC_NO
*/ */
bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { bool is_key_pressed(uint8_t key) {
if (key == KC_NO) { if (key == KC_NO) {
return false; return false;
} }
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
if ((key >> 3) < KEYBOARD_REPORT_BITS) { if ((key >> 3) < NKRO_REPORT_BITS) {
return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); return nkro_report->bits[key >> 3] & 1 << (key & 7);
} else { } else {
return false; return false;
} }
} }
#endif #endif
for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { for (int i = 0; i < NKRO_REPORT_BITS; i++) {
if (keyboard_report->keys[i] == key) { if (keyboard_report->keys[i] == key) {
return true; return true;
} }
@ -215,9 +216,9 @@ void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { void add_key_bit(report_nkro_t* nkro_report, uint8_t code) {
if ((code >> 3) < KEYBOARD_REPORT_BITS) { if ((code >> 3) < NKRO_REPORT_BITS) {
keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); nkro_report->bits[code >> 3] |= 1 << (code & 7);
} else { } else {
dprintf("add_key_bit: can't add: %02X\n", code); dprintf("add_key_bit: can't add: %02X\n", code);
} }
@ -227,9 +228,9 @@ void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { void del_key_bit(report_nkro_t* nkro_report, uint8_t code) {
if ((code >> 3) < KEYBOARD_REPORT_BITS) { if ((code >> 3) < NKRO_REPORT_BITS) {
keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); nkro_report->bits[code >> 3] &= ~(1 << (code & 7));
} else { } else {
dprintf("del_key_bit: can't del: %02X\n", code); dprintf("del_key_bit: can't del: %02X\n", code);
} }
@ -240,10 +241,10 @@ void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { void add_key_to_report(uint8_t key) {
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
add_key_bit(keyboard_report, key); add_key_bit(nkro_report, key);
return; return;
} }
#endif #endif
@ -254,10 +255,10 @@ void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { void del_key_from_report(uint8_t key) {
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
del_key_bit(keyboard_report, key); del_key_bit(nkro_report, key);
return; return;
} }
#endif #endif
@ -268,11 +269,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) {
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
void clear_keys_from_report(report_keyboard_t* keyboard_report) { void clear_keys_from_report(void) {
// not clear mods // not clear mods
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); memset(nkro_report->bits, 0, sizeof(nkro_report->bits));
return; return;
} }
#endif #endif

View File

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "keycode.h" #include "keycode.h"
#include "util.h"
// clang-format off // clang-format off
@ -124,21 +125,7 @@ enum desktop_usages {
// clang-format on // clang-format on
#define NKRO_SHARED_EP #define NKRO_REPORT_BITS 30
/* key report size(NKRO or boot mode) */
#if defined(NKRO_ENABLE)
# if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
# include "protocol/usb_descriptor.h"
# define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
# elif defined(PROTOCOL_ARM_ATSAM)
# include "protocol/arm_atsam/usb/udi_device_epsize.h"
# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
# undef NKRO_SHARED_EP
# undef MOUSE_SHARED_EP
# else
# error "NKRO not supported with this protocol"
# endif
#endif
#ifdef KEYBOARD_SHARED_EP #ifdef KEYBOARD_SHARED_EP
# define KEYBOARD_REPORT_SIZE 9 # define KEYBOARD_REPORT_SIZE 9
@ -172,36 +159,30 @@ extern "C" {
* desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui
* *
*/ */
typedef union { typedef struct {
uint8_t raw[KEYBOARD_REPORT_SIZE];
struct {
#ifdef KEYBOARD_SHARED_EP #ifdef KEYBOARD_SHARED_EP
uint8_t report_id; uint8_t report_id;
#endif #endif
uint8_t mods; uint8_t mods;
uint8_t reserved; uint8_t reserved;
uint8_t keys[KEYBOARD_REPORT_KEYS]; uint8_t keys[KEYBOARD_REPORT_KEYS];
}; } PACKED report_keyboard_t;
#ifdef NKRO_ENABLE
struct nkro_report { typedef struct {
# ifdef NKRO_SHARED_EP uint8_t report_id;
uint8_t report_id; uint8_t mods;
# endif uint8_t bits[NKRO_REPORT_BITS];
uint8_t mods; } report_nkro_t;
uint8_t bits[KEYBOARD_REPORT_BITS];
} nkro;
#endif
} __attribute__((packed)) report_keyboard_t;
typedef struct { typedef struct {
uint8_t report_id; uint8_t report_id;
uint16_t usage; uint16_t usage;
} __attribute__((packed)) report_extra_t; } PACKED report_extra_t;
typedef struct { typedef struct {
uint8_t report_id; uint8_t report_id;
uint32_t usage; uint32_t usage;
} __attribute__((packed)) report_programmable_button_t; } PACKED report_programmable_button_t;
#ifdef MOUSE_EXTENDED_REPORT #ifdef MOUSE_EXTENDED_REPORT
typedef int16_t mouse_xy_report_t; typedef int16_t mouse_xy_report_t;
@ -222,7 +203,7 @@ typedef struct {
mouse_xy_report_t y; mouse_xy_report_t y;
int8_t v; int8_t v;
int8_t h; int8_t h;
} __attribute__((packed)) report_mouse_t; } PACKED report_mouse_t;
typedef struct { typedef struct {
#ifdef DIGITIZER_SHARED_EP #ifdef DIGITIZER_SHARED_EP
@ -234,7 +215,7 @@ typedef struct {
uint8_t reserved : 5; uint8_t reserved : 5;
uint16_t x; uint16_t x;
uint16_t y; uint16_t y;
} __attribute__((packed)) report_digitizer_t; } PACKED report_digitizer_t;
typedef struct { typedef struct {
#ifdef JOYSTICK_SHARED_EP #ifdef JOYSTICK_SHARED_EP
@ -251,7 +232,7 @@ typedef struct {
#if JOYSTICK_BUTTON_COUNT > 0 #if JOYSTICK_BUTTON_COUNT > 0
uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];
#endif #endif
} __attribute__((packed)) report_joystick_t; } PACKED report_joystick_t;
/* keycode to system usage */ /* keycode to system usage */
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
@ -329,20 +310,20 @@ static inline uint16_t KEYCODE2CONSUMER(uint8_t key) {
} }
} }
uint8_t has_anykey(report_keyboard_t* keyboard_report); uint8_t has_anykey(void);
uint8_t get_first_key(report_keyboard_t* keyboard_report); uint8_t get_first_key(void);
bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); bool is_key_pressed(uint8_t key);
void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code); void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code); void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); void add_key_bit(report_nkro_t* nkro_report, uint8_t code);
void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); void del_key_bit(report_nkro_t* nkro_report, uint8_t code);
#endif #endif
void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); void add_key_to_report(uint8_t key);
void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); void del_key_from_report(uint8_t key);
void clear_keys_from_report(report_keyboard_t* keyboard_report); void clear_keys_from_report(void);
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report); bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report);

View File

@ -359,10 +359,10 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
// Keycodes // Keycodes
HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
HID_RI_USAGE_MINIMUM(8, 0x00), HID_RI_USAGE_MINIMUM(8, 0x00),
HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1), HID_RI_USAGE_MAXIMUM(8, NKRO_REPORT_BITS * 8 - 1),
HID_RI_LOGICAL_MINIMUM(8, 0x00), HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01), HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS * 8), HID_RI_REPORT_COUNT(8, NKRO_REPORT_BITS * 8),
HID_RI_REPORT_SIZE(8, 0x01), HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),

View File

@ -91,6 +91,7 @@ enum usb_interfaces {
static uint8_t keyboard_led_state = 0; static uint8_t keyboard_led_state = 0;
static uint8_t vusb_idle_rate = 0; static uint8_t vusb_idle_rate = 0;
uint8_t keyboard_protocol = 1;
/* Keyboard report send buffer */ /* Keyboard report send buffer */
#define KBUF_SIZE 16 #define KBUF_SIZE 16
@ -231,10 +232,11 @@ void console_task(void) {
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
static uint8_t keyboard_leds(void); static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report); static void send_keyboard(report_keyboard_t *report);
static void send_nkro(report_nkro_t *report);
static void send_mouse(report_mouse_t *report); static void send_mouse(report_mouse_t *report);
static void send_extra(report_extra_t *report); static void send_extra(report_extra_t *report);
static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; static host_driver_t driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
host_driver_t *vusb_driver(void) { host_driver_t *vusb_driver(void) {
return &driver; return &driver;
@ -259,6 +261,10 @@ static void send_keyboard(report_keyboard_t *report) {
keyboard_report_sent = *report; keyboard_report_sent = *report;
} }
static void send_nkro(report_nkro_t *report) {
// TODO: Implement NKRO
}
#ifndef KEYBOARD_SHARED_EP #ifndef KEYBOARD_SHARED_EP
# define usbInterruptIsReadyShared usbInterruptIsReady3 # define usbInterruptIsReadyShared usbInterruptIsReady3
# define usbSetInterruptShared usbSetInterrupt3 # define usbSetInterruptShared usbSetInterrupt3