summaryrefslogtreecommitdiff
path: root/src/drivers/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/include')
-rw-r--r--src/drivers/include/drivers/bluetooth.hpp116
-rw-r--r--src/drivers/include/drivers/bluetooth_types.hpp7
-rw-r--r--src/drivers/include/drivers/nvs.hpp7
3 files changed, 89 insertions, 41 deletions
diff --git a/src/drivers/include/drivers/bluetooth.hpp b/src/drivers/include/drivers/bluetooth.hpp
index 94a85263..449812d6 100644
--- a/src/drivers/include/drivers/bluetooth.hpp
+++ b/src/drivers/include/drivers/bluetooth.hpp
@@ -3,6 +3,7 @@
#include <array>
#include <atomic>
+#include <functional>
#include <map>
#include <mutex>
#include <optional>
@@ -25,28 +26,68 @@
namespace drivers {
/*
- * A handle used to interact with the bluetooth state machine.
+ * A handle used to interact with the bluetooth state machine. This is the main
+ * API that the rest of the system should use to interact with Bluetooth.
*/
class Bluetooth {
public:
- Bluetooth(NvsStorage& storage, tasks::WorkerPool&);
+ /*
+ * Callback invoked when an event is generated by the Bluetooth stack. This
+ * callback is invoked synchronously from a Bluetooth task context, so
+ * implementations should immediately hop to a different task to process the
+ * event.
+ */
+ using EventHandler = std::function<void(bluetooth::Event)>;
+
+ Bluetooth(NvsStorage&, tasks::WorkerPool&, EventHandler);
+
+ /* Enables or disables the entire Bluetooth stack. */
+ auto enable(bool en) -> void;
+ auto enabled() -> bool;
+
+ auto source(PcmBuffer*) -> void;
+ auto softVolume(float) -> void;
+
+ enum class ConnectionState {
+ kConnected,
+ kConnecting,
+ kDisconnected,
+ };
+
+ auto connectionState() -> ConnectionState;
+
+ /*
+ * The 'paired' device is a device that will be preferred for connections.
+ * When Bluetooth is first enabled, we immediately try to connect to the
+ * paired device. If the paired device is seen during a scan, then we will
+ * also automatically connect to it.
+ */
+ auto pairedDevice() -> std::optional<bluetooth::MacAndName>;
+
+ /*
+ * Sets the preferred device. If a device is provided, a connection will be
+ * attempted immediately, even if the device has not been detected in a
+ * previous scan.
+ */
+ auto pairedDevice(std::optional<bluetooth::MacAndName> dev) -> void;
+
+ /* A list of devices that have previously been the paired device. */
+ auto knownDevices() -> std::vector<bluetooth::MacAndName>;
+ auto forgetKnownDevice(const bluetooth::mac_addr_t&) -> void;
+
+ /* Enables or disables scanning for nearby Bluetooth devices. */
+ auto discoveryEnabled(bool) -> void;
+ auto discoveryEnabled() -> bool;
+
+ /*
+ * A list of nearby devices that have been discovered since discovery was
+ * last enabled. This list may include the paired device, as well as devices
+ * that are also present in the known devices list.
+ */
+ auto discoveredDevices() -> std::vector<bluetooth::MacAndName>;
- auto Enable() -> bool;
- auto Disable() -> void;
- auto IsEnabled() -> bool;
-
- auto IsConnected() -> bool;
- auto ConnectedDevice() -> std::optional<bluetooth::MacAndName>;
-
- auto KnownDevices() -> std::vector<bluetooth::Device>;
-
- auto SetPreferredDevice(std::optional<bluetooth::MacAndName> dev) -> void;
- auto PreferredDevice() -> std::optional<bluetooth::MacAndName>;
-
- auto SetSource(PcmBuffer*) -> void;
- auto SetVolumeFactor(float) -> void;
-
- auto SetEventHandler(std::function<void(bluetooth::Event)> cb) -> void;
+ private:
+ NvsStorage& nvs_;
};
namespace bluetooth {
@@ -56,7 +97,7 @@ struct Enable : public tinyfsm::Event {};
struct Disable : public tinyfsm::Event {};
struct ConnectTimedOut : public tinyfsm::Event {};
-struct PreferredDeviceChanged : public tinyfsm::Event {};
+struct PairedDeviceChanged : public tinyfsm::Event {};
struct SourceChanged : public tinyfsm::Event {};
struct DeviceDiscovered : public tinyfsm::Event {
const Device& device;
@@ -94,6 +135,8 @@ class Scanner {
auto StopScanning() -> void;
auto StopScanningNow() -> void;
+ auto enabled() -> bool;
+
auto HandleGapEvent(const events::internal::Gap&) -> void;
private:
@@ -103,25 +146,22 @@ class Scanner {
auto HandleDeviceDiscovery(const esp_bt_gap_cb_param_t& param) -> void;
};
+/*
+ * The main state machine for managing the state of the Bluetooth stack, and
+ * the current (if any) Bluetooth connection.
+ */
class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
public:
- static auto Init(NvsStorage& storage) -> void;
+ static auto Init(NvsStorage& storage, Bluetooth::EventHandler) -> void;
static auto lock() -> std::lock_guard<std::mutex>;
- static auto devices() -> std::vector<Device>;
-
- static auto preferred_device() -> std::optional<bluetooth::MacAndName>;
- static auto preferred_device(std::optional<bluetooth::MacAndName>) -> void;
+ static auto pairedDevice() -> std::optional<bluetooth::MacAndName>;
+ static auto pairedDevice(std::optional<bluetooth::MacAndName>) -> void;
- static auto scanning() -> bool;
static auto discovery() -> bool;
static auto discovery(bool) -> void;
-
- static auto source() -> PcmBuffer*;
- static auto source(PcmBuffer*) -> void;
-
- static auto event_handler(std::function<void(Event)>) -> void;
+ static auto discoveredDevices() -> std::vector<Device>;
virtual ~BluetoothState(){};
@@ -131,7 +171,7 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
virtual void react(const events::Enable& ev){};
virtual void react(const events::Disable& ev) = 0;
virtual void react(const events::ConnectTimedOut& ev){};
- virtual void react(const events::PreferredDeviceChanged& ev){};
+ virtual void react(const events::PairedDeviceChanged& ev){};
virtual void react(const events::SourceChanged& ev){};
virtual void react(const events::DeviceDiscovered&);
@@ -146,13 +186,11 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
static Scanner* sScanner_;
static std::mutex sFsmMutex;
- static std::map<mac_addr_t, Device> sDevices_;
- static std::optional<bluetooth::MacAndName> sPreferredDevice_;
-
- static std::optional<bluetooth::MacAndName> sConnectingDevice_;
+ static std::map<mac_addr_t, Device> sDiscoveredDevices_;
+ static std::optional<bluetooth::MacAndName> sPairedWith_;
+ static std::optional<bluetooth::MacAndName> sConnectingTo_;
static int sConnectAttemptsRemaining_;
- static std::atomic<PcmBuffer*> sSource_;
static std::function<void(Event)> sEventHandler_;
auto connect(const bluetooth::MacAndName&) -> bool;
@@ -177,7 +215,7 @@ class Idle : public BluetoothState {
void exit() override;
void react(const events::Disable& ev) override;
- void react(const events::PreferredDeviceChanged& ev) override;
+ void react(const events::PairedDeviceChanged& ev) override;
void react(events::internal::Gap ev) override;
@@ -189,7 +227,7 @@ class Connecting : public BluetoothState {
void entry() override;
void exit() override;
- void react(const events::PreferredDeviceChanged& ev) override;
+ void react(const events::PairedDeviceChanged& ev) override;
void react(const events::ConnectTimedOut& ev) override;
void react(const events::Disable& ev) override;
@@ -204,7 +242,7 @@ class Connected : public BluetoothState {
void entry() override;
void exit() override;
- void react(const events::PreferredDeviceChanged& ev) override;
+ void react(const events::PairedDeviceChanged& ev) override;
void react(const events::SourceChanged& ev) override;
void react(const events::Disable& ev) override;
diff --git a/src/drivers/include/drivers/bluetooth_types.hpp b/src/drivers/include/drivers/bluetooth_types.hpp
index d2e55ee5..05caee47 100644
--- a/src/drivers/include/drivers/bluetooth_types.hpp
+++ b/src/drivers/include/drivers/bluetooth_types.hpp
@@ -27,9 +27,12 @@ struct Device {
};
enum class SimpleEvent {
- kKnownDevicesChanged,
kConnectionStateChanged,
- kPreferredDeviceChanged,
+ kPairedDeviceChanged,
+ kKnownDevicesChanged,
+ kDiscoveryChanged,
+ kDeviceDiscovered,
+
// Passthrough events
kPlayPause,
kStop,
diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp
index 88dd5ae0..2bc77a31 100644
--- a/src/drivers/include/drivers/nvs.hpp
+++ b/src/drivers/include/drivers/nvs.hpp
@@ -96,6 +96,10 @@ class NvsStorage {
auto BluetoothVolume(const bluetooth::mac_addr_t&) -> uint8_t;
auto BluetoothVolume(const bluetooth::mac_addr_t&, uint8_t) -> void;
+ auto BluetoothNames() -> std::vector<bluetooth::MacAndName>;
+ auto BluetoothName(const bluetooth::mac_addr_t&, std::optional<std::string>)
+ -> void;
+
enum class Output : uint8_t {
kHeadphones = 0,
kBluetooth = 1,
@@ -154,7 +158,10 @@ class NvsStorage {
Setting<int8_t> amp_left_bias_;
Setting<uint8_t> input_mode_;
Setting<uint8_t> output_mode_;
+
Setting<bluetooth::MacAndName> bt_preferred_;
+ Setting<std::vector<bluetooth::MacAndName>> bt_names_;
+
Setting<uint8_t> db_auto_index_;
util::LruCache<10, bluetooth::mac_addr_t, uint8_t> bt_volumes_;