LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces/BLEMIDI - BLEAPI.hpp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 3 3 100.0 %
Date: 2024-11-09 15:32:27 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : /**
       4             :  * @file
       5             :  * Type definitions and callback interfaces for communication between the
       6             :  * low-level BLE stacks and higher-level MIDI BLE backends.
       7             :  */
       8             : 
       9             : #include <Settings/NamespaceSettings.hpp>
      10             : 
      11             : #include "Util/compat.hpp"
      12             : 
      13             : #include <cstddef>
      14             : #include <cstdint>
      15             : 
      16             : BEGIN_CS_NAMESPACE
      17             : 
      18             : /// Represents a handle to the connection to another device.
      19             : struct BLEConnectionHandle {
      20             :     uint16_t conn = 0xFFFF;
      21             :     explicit operator bool() const { return conn != 0xFFFF; }
      22             : 
      23             : #if __cplusplus < 201402L
      24             :     BLEConnectionHandle() = default;
      25             :     BLEConnectionHandle(uint16_t conn) : conn {conn} {}
      26             : #endif
      27             : };
      28             : 
      29             : /// Represents a handle to a local GATT characteristic.
      30             : struct BLECharacteristicHandle {
      31             :     uint16_t characteristic = 0xFFFF;
      32             :     explicit operator bool() const { return characteristic != 0xFFFF; }
      33             : 
      34             : #if __cplusplus < 201402L
      35             :     BLECharacteristicHandle() = default;
      36             :     BLECharacteristicHandle(uint16_t characteristic)
      37             :         : characteristic {characteristic} {}
      38             : #endif
      39             : };
      40             : 
      41             : /// Non-owning, std::span-style read-only view of BLE data.
      42             : struct BLEDataView {
      43             :     const uint8_t *data = nullptr;
      44             :     uint16_t length = 0;
      45          30 :     explicit operator bool() const { return length > 0; }
      46             : 
      47             : #if __cplusplus < 201402L
      48             :     BLEDataView() = default;
      49             :     BLEDataView(const uint8_t *data, uint16_t length)
      50             :         : data {data}, length {length} {}
      51             : #endif
      52             : };
      53             : 
      54             : /// Describes a byte buffer containing (part of) a BLE packet.
      55             : /// Packets can be stored across multiple buffers, in which case the first
      56             : /// first buffer has type `Packet` and subsequent buffers of the same packet
      57             : /// have the type `Continuation`.
      58             : enum class BLEDataType : uint8_t {
      59             :     None = 0,     ///< No buffers available.
      60             :     Packet,       ///< Buffer contains the start of a BLE packet.
      61             :     Continuation, ///< Buffer contains a chunk of a BLE packet.
      62             : };
      63             : 
      64             : /// Callable that returns the next chunk of data from a BLE packet when called.
      65             : /// Uses type erasure with a static buffer (no dynamic memory allocations).
      66             : class BLEDataGenerator {
      67             :   public:
      68             :     /// Get the next chunk of data from the BLE packet.
      69             :     /// Returns a chunk of size zero to indicate completion.
      70             :     /// @pre This wrapper is not empty.
      71             :     /// @pre There is still data available. Calling this function again after
      72             :     ///      the previous call returned an empty chunk is not allowed.
      73             :     BLEDataView operator()();
      74             :     /// Release the resources of the underlying data generator.
      75             :     void clear();
      76             :     /// Check if this wrapper contains an underlying data generator.
      77             :     explicit operator bool() const { return instance; }
      78             : 
      79             :     /// Create an empty BLEDataGenerator.
      80             :     BLEDataGenerator() = default;
      81             :     /// Store a callable of type @p T and initialize it by @p args.
      82             :     template <class T, class... Args>
      83             :     BLEDataGenerator(compat::in_place_type_t<T>, Args &&...args);
      84             :     /// Store a callable of type @p T (with cv qualifiers and references
      85             :     /// removed) and initialize it by forwarding @p t.
      86             :     template <class T>
      87             :     BLEDataGenerator(compat::in_place_t, T &&t);
      88             :     BLEDataGenerator(const BLEDataGenerator &) = delete;
      89             :     BLEDataGenerator &operator=(const BLEDataGenerator &) = delete;
      90             :     BLEDataGenerator(BLEDataGenerator &&other) noexcept;
      91             :     BLEDataGenerator &operator=(BLEDataGenerator &&other) noexcept;
      92          15 :     ~BLEDataGenerator() { clear(); }
      93             : 
      94             :   private:
      95             :     /// Type-erased interface.
      96             :     struct Iface;
      97             :     /// Specific class that implements the type-erased interface, wrapping the
      98             :     /// type @p T.
      99             :     template <class T>
     100             :     struct Impl;
     101             :     /// Alignment of the buffer to allocate the underlying data generator.
     102             :     using buffer_align_t = max_align_t;
     103             :     /// Size of the buffer to allocate the underlying data generator.
     104             :     static constexpr size_t capacity = 4 * sizeof(void *) - sizeof(Iface *);
     105             :     /// Buffer used for allocation of the underlying data generator.
     106             :     alignas(buffer_align_t) compat::byte storage[capacity];
     107             :     //// Type-erased pointer to the underlying data generator in @ref storage.
     108             :     Iface *instance = nullptr;
     109             : };
     110             : 
     111             : /// Should a buffer of BLEData be consumed immediately inside of the callback,
     112             : /// or can we hold on to it and process it later?
     113             : enum class BLEDataLifetime {
     114             :     /// Buffer is valid only during the callback. Do not keep any pointers to it.
     115             :     ConsumeImmediately,
     116             :     /// Buffer is valid for as long as the owning @ref BLEDataGenerator is not
     117             :     /// resumed or destroyed.
     118             :     Managed,
     119             : };
     120             : 
     121             : /// Defines the interface for callback functions registered by the low-level
     122             : /// BLE code.
     123             : /// @warning    These functions may be called from different tasks/threads or
     124             : ///             low-priority interrupt handlers. You cannot take locks, and you
     125             : ///             need to synchronize appropriately (e.g. using `std::atomic` or
     126             : ///             by using critical sections).
     127             : class MIDIBLEInstance {
     128             :   public:
     129          29 :     virtual ~MIDIBLEInstance() = default;
     130             :     /// Called by the BLE stack when a connection is established.
     131             :     virtual void handleConnect(BLEConnectionHandle conn_handle) = 0;
     132             :     /// Called by the BLE stack when a connection is terminated.
     133             :     virtual void handleDisconnect(BLEConnectionHandle conn_handle) = 0;
     134             :     /// Called by the BLE stack when the maximum transmission unit for the
     135             :     /// connection changes.
     136             :     virtual void handleMTU(BLEConnectionHandle conn_handle, uint16_t mtu) = 0;
     137             :     /// Called by the BLE stack when the central subscribes to receive
     138             :     /// notifications for the MIDI GATT characteristic.
     139             :     virtual void handleSubscribe(BLEConnectionHandle conn_handle,
     140             :                                  BLECharacteristicHandle char_handle,
     141             :                                  bool notify) = 0;
     142             :     /// Called by the BLE stack when the central writes data to the MIDI GATT
     143             :     /// characteristic.
     144             :     virtual void handleData(BLEConnectionHandle conn_handle,
     145             :                             BLEDataGenerator &&data,
     146             :                             BLEDataLifetime lifetime) = 0;
     147             : };
     148             : 
     149             : /// Configuration options for the low-level BLE code.
     150             : struct BLESettings {
     151             :     /// Device name (used for advertising)
     152             :     const char *device_name = "Control Surface MIDI";
     153             :     /// Connection intervals as multiples of 1.25 milliseconds
     154             :     /// (e.g.0x000C = 15 ms).
     155             :     struct {
     156             :         uint16_t minimum = 0x000C;
     157             :         uint16_t maximum = 0x000C;
     158             :     } connection_interval {};
     159             :     /// Set to true if you want the Arduino to always initiate the Bluetooth
     160             :     /// bonding or secure connection. As a result, it will show up as a "paired"
     161             :     /// device on your computer/phone/tablet. If set to false, security is still
     162             :     /// supported, but the central device should take the initiative.
     163             :     bool initiate_security = false;
     164             : };
     165             : 
     166             : END_CS_NAMESPACE
     167             : 
     168             : #include "BLEAPI.ipp"

Generated by: LCOV version 1.15