You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Kaleidoscope/src/kaleidoscope_internal/LEDModeManager.cpp

106 lines
3.4 KiB

/* Kaleidoscope - Firmware for computer input devices
* Copyright (C) 2013-2018 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 "kaleidoscope_internal/LEDModeManager.h"
#include "kaleidoscope/plugin/LEDMode.h"
namespace kaleidoscope {
namespace internal {
namespace {
// We want to export as little symbols as possible. That's why the
// internal state of the LED mode management lives in
// an anonymous namespace.
uint8_t cur_mode_id = 255; // We use 255 as a flag value that signals
// uninitialized. That's why we can only have
// LED mode ids in the range [0..254].
// A pointer to cache the current transient LED mode.
//
kaleidoscope::plugin::LEDMode *cur_led_mode = nullptr;
bool current_led_mode_dynamic = false;
}
kaleidoscope::plugin::LEDMode *LEDModeManager::getLEDMode(uint8_t mode_id) {
// If we end up here, the requested LED mode is a dynamic one.
// Check if the requested LED mode is already active
//
if (cur_mode_id == mode_id) {
return cur_led_mode;
}
// If there is already an active LED mode, its obviously the wrong one
// (see test above). To generate a new transient LED mode, we need
// to destroy the current one. To achieve this, we call its
// (possibly - see explanation below) virtual destuctor and let
// it take care of the cleanup.
//
// Please note that due to the fact that transient LED modes are
// allocated using placement new within a pre-existing static buffer,
// there is no need to free any memory after the destructor of the
// current LED mode was called. We can just reuse the buffer
// for the next LED mode instance.
//
// Please note: Currently, LEDMode has no virtual destructor.
// That's why the explicit destructor call below is a noop
// that is optimized out by the compiler. It is there
// to enable the possible future introduction of a virtual
// destructor for class LEDMode.
//
if (current_led_mode_dynamic) {
cur_led_mode->~LEDMode();
}
// Store the current mode id to enable cache access (see above).
//
cur_mode_id = mode_id;
// Get a factory struct for the creation of the new LED mode.
//
led_mode_management::LEDModeFactory fac;
retreiveLEDModeFactoryFromPROGMEM(mode_id, fac);
// The factories for persistent LED modes serve to pass through the LED
// mode plugin's pointer in parent_plugin_.
//
if (fac.isPersistentLEDMode()) {
current_led_mode_dynamic = false;
cur_led_mode = fac.getPersistentLEDMode();
} else {
current_led_mode_dynamic = true;
// Generate a new led mode by calling the factory function
// (fac.generate_led_mode_).
//
// We store a pointer to the newly created LED mode to enable
// cached access (see check above).
//
cur_led_mode = fac.generateTransientLEDMode(led_mode_buffer_, mode_id);
}
return cur_led_mode;
}
} // end namespace internal
} // end namespace kaleidoscope