Bluetooth (#518)

* Bluetooth LE addition

* fixes

* use the psram!

helps a little on S3 (t-deck)

* custom device name

* Update symbols.c

* Feedback + fixes

Fixes external app start/stop server (child devices)
Fixes BtManage causing a full system hang upon disabling bt when a device is connected to the host.

* updoot

* more updoot

* move back!

* Revert "move back!"

This reverts commit d3694365c634acc5db62ac59771c496cb971a727.

* fix some of the things

* Addressing feedback? hmm

* Fixes

Bug 1 — Reconnect loop / Reconnect not working fixed
Bug 2 — Name-only advertising overwrites HID advertising
Bug 3 — BleHidDeviceCtx leak on re-enable
Enhancement — HID device auto-start on radio re-enable

* stuff...

* update for consistency with others

* fix crashes

and some bonus symbols

* a few symbols, i2c speed, cdn message

100kHz i2c speed seems to be more compatible with m5stack modules...and probably in general.
cdn message no longer applies

* Hide BT Settings when bt not enabled

* Addressing things and device fixes

* Missed one!

* stuff
This commit is contained in:
Shadowtrance
2026-05-23 06:49:37 +10:00
committed by GitHub
parent 895e6bc50d
commit 5c78d55b04
72 changed files with 7155 additions and 352 deletions
@@ -0,0 +1,9 @@
#pragma once
#include <Tactility/app/App.h>
namespace tt::app::btmanage {
LaunchId start();
} // namespace tt::app::btmanage
@@ -0,0 +1,99 @@
#pragma once
#include <array>
#include <string>
#include <vector>
#include <cstdint>
struct Device;
namespace tt::bluetooth {
enum class RadioState {
Off,
OnPending,
On,
OffPending,
};
struct PeerRecord {
std::array<uint8_t, 6> addr;
std::string name;
int8_t rssi;
bool paired;
bool connected;
/** Profile used to pair (BtProfileId value). Only meaningful for paired peers. */
int profileId = 0;
};
/** Find the first ready BLE device in the kernel device registry. Returns nullptr if unavailable. */
struct Device* findFirstDevice();
/** @return the current radio state */
RadioState getRadioState();
/** For logging purposes */
const char* radioStateToString(RadioState state);
/** @return the peers found during the last scan */
std::vector<PeerRecord> getScanResults();
/** @return the list of currently paired peers */
std::vector<PeerRecord> getPairedPeers();
/**
* @brief Initiate pairing with a peer.
* Returns immediately; result is delivered via kernel event callback (BT_EVENT_PAIR_RESULT).
*/
void pair(const std::array<uint8_t, 6>& addr);
/**
* @brief Remove a previously paired peer.
* @param[in] addr the peer address
*/
void unpair(const std::array<uint8_t, 6>& addr);
/**
* @brief Connect to a peer using the specified profile.
* @param[in] addr the peer address
* @param[in] profileId the BtProfileId value (from bluetooth.h)
*/
void connect(const std::array<uint8_t, 6>& addr, int profileId);
/**
* @brief Disconnect a peer from the specified profile.
* @param[in] addr the peer address
* @param[in] profileId the BtProfileId value (from bluetooth.h)
*/
void disconnect(const std::array<uint8_t, 6>& addr, int profileId);
/**
* @brief Check whether a given profile is supported on this build/SOC.
* @param[in] profileId the BtProfileId value to query
* @return true when the profile is available
*/
bool isProfileSupported(int profileId);
// ---- BLE HID Host (central role — connect to external BLE keyboard/mouse) ----
/**
* @brief Connect to a remote BLE HID device (keyboard, mouse, etc.) as a host.
* Discovery, CCCD subscription, and LVGL indev registration happen automatically.
* @param[in] addr 6-byte BLE address of the HID peripheral
*/
void hidHostConnect(const std::array<uint8_t, 6>& addr);
/** @brief Disconnect from the currently connected BLE HID device. */
void hidHostDisconnect();
/** @return true when a BLE HID peripheral is fully subscribed and acting as LVGL input device */
bool hidHostIsConnected();
/**
* @brief Initialize the Bluetooth bridge layer and optionally enable the radio.
* Called once from Tactility startup (after kernel drivers are ready).
* Reads settings and enables the radio if configured to auto-start.
*/
void systemStart();
} // namespace tt::bluetooth
@@ -0,0 +1,30 @@
#pragma once
#include <array>
#include <cstdint>
#include <string>
#include <vector>
namespace tt::bluetooth::settings {
struct PairedDevice {
std::string name;
std::array<uint8_t, 6> addr;
bool autoConnect = false;
/** Profile used to pair (BtProfileId value). Defaults to BT_PROFILE_SPP=2. */
int profileId = 2;
};
std::string addrToHex(const std::array<uint8_t, 6>& addr);
bool hasFileForDevice(const std::string& addr_hex);
bool load(const std::string& addr_hex, PairedDevice& device);
bool save(const PairedDevice& device);
bool remove(const std::string& addr_hex);
std::vector<PairedDevice> loadAll();
} // namespace tt::bluetooth::settings
@@ -0,0 +1,14 @@
#pragma once
namespace tt::bluetooth::settings {
void setEnableOnBoot(bool enable);
bool shouldEnableOnBoot();
void setSppAutoStart(bool enable);
bool shouldSppAutoStart();
void setMidiAutoStart(bool enable);
bool shouldMidiAutoStart();
} // namespace tt::bluetooth::settings