Add Bluetooth HID remote control support

Integrate BLE keyboard host functionality for page-turner remotes. Adds device pairing, button mapping, preset configurations for Free2/Free3 remotes, and persistent storage of mappings. Migrates from open-x4-sdk to freeink-sdk submodule which includes the BleKeyboardHost library. Implements CPU frequency locking during BLE operations to prevent watchdog timeouts.
This commit is contained in:
Justin Mitchell
2026-06-24 15:36:29 -04:00
parent 6e8dbd7f23
commit 9ab0b0bfb7
20 changed files with 984 additions and 15 deletions
@@ -3,6 +3,8 @@
#include <GfxRenderer.h>
#include <I18n.h>
#include "BleInput.h"
#include "CrossPointSettings.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"
@@ -22,7 +24,7 @@ EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInpu
std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuItems(bool hasFootnotes,
bool hasBookmarks) {
std::vector<MenuItem> items;
items.reserve(12);
items.reserve(13);
items.push_back({MenuAction::SELECT_CHAPTER, StrId::STR_SELECT_CHAPTER});
if (hasFootnotes) {
items.push_back({MenuAction::FOOTNOTES, StrId::STR_FOOTNOTES});
@@ -36,6 +38,7 @@ std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuI
items.push_back({MenuAction::GO_TO_PERCENT, StrId::STR_GO_TO_PERCENT});
items.push_back({MenuAction::SCREENSHOT, StrId::STR_SCREENSHOT_BUTTON});
items.push_back({MenuAction::DISPLAY_QR, StrId::STR_DISPLAY_QR});
items.push_back({MenuAction::TOGGLE_BLUETOOTH, StrId::STR_TOGGLE_BLUETOOTH});
items.push_back({MenuAction::GO_HOME, StrId::STR_GO_HOME_BUTTON});
items.push_back({MenuAction::SYNC, StrId::STR_SYNC_PROGRESS});
items.push_back({MenuAction::DELETE_CACHE, StrId::STR_DELETE_CACHE});
@@ -76,6 +79,19 @@ void EpubReaderMenuActivity::loop() {
return;
}
if (selectedAction == MenuAction::TOGGLE_BLUETOOTH) {
// Toggle in place and stay in the menu (no reader re-render needed).
SETTINGS.bluetoothEnabled = SETTINGS.bluetoothEnabled ? 0 : 1;
if (SETTINGS.bluetoothEnabled) {
bleinput::ensureStarted();
} else {
bleinput::stop();
}
SETTINGS.saveToFile();
requestUpdate();
return;
}
setResult(MenuResult{static_cast<int>(selectedAction), pendingOrientation, selectedPageTurnOption});
finish();
return;
@@ -125,6 +141,9 @@ void EpubReaderMenuActivity::render(RenderLock&&) {
} else if (value == MenuAction::AUTO_PAGE_TURN) {
// Render current page turn value on the right edge of the content area.
return pageTurnLabels[selectedPageTurnOption];
} else if (value == MenuAction::TOGGLE_BLUETOOTH) {
// Render current Bluetooth on/off state on the right edge.
return SETTINGS.bluetoothEnabled ? tr(STR_STATE_ON) : tr(STR_STATE_OFF);
} else {
return "";
}