LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces/BLEMIDI - ESP32Backend.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 72.3 % 47 34
Test Date: 2026-06-06 17:44:35 Functions: 83.3 % 12 10
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <AH/Error/Error.hpp>
       4              : 
       5              : #include "BLEAPI.hpp"
       6              : #include "BufferedBLEMIDIParser.hpp"
       7              : #include "ThreadedBLEMIDISender.hpp"
       8              : #include "Util/ESP32Threads.hpp"
       9              : 
      10              : #include <atomic>
      11              : 
      12              : #ifndef ARDUINO
      13              : #define ESP_LOGD(...) ((void)0)
      14              : #define ESP_LOGE(...) ((void)0)
      15              : #define ESP_LOGI(...) ((void)0)
      16              : #endif
      17              : 
      18              : BEGIN_CS_NAMESPACE
      19              : 
      20              : /// ESP32 backend intended to be plugged into @ref GenericBLEMIDI_Interface.
      21              : /// @p Impl can be used to select different low-level BLE stacks.
      22              : template <class Impl>
      23              : class ESP32BLEBackend : private ThreadedBLEMIDISender<ESP32BLEBackend<Impl>>,
      24              :                         private MIDIBLEInstance {
      25              :   protected:
      26              :     [[no_unique_address]] Impl impl;
      27              :     using Sender = ThreadedBLEMIDISender<ESP32BLEBackend>;
      28              :     friend Sender;
      29           22 :     void sendData(BLEDataView data) {
      30           22 :         auto chr = characteristic.load();
      31           22 :         auto con = connection.load();
      32              :         ESP_LOGD("CS-BLEMIDI", "conn=%d, char=%d", con.conn,
      33              :                  chr.characteristic);
      34           22 :         if (chr.characteristic == 0xFFFF)
      35            0 :             return;
      36           22 :         impl.notify(con, chr, data);
      37              :     }
      38              :     std::atomic<BLEConnectionHandle> connection;
      39              :     std::atomic<BLECharacteristicHandle> characteristic;
      40              : 
      41              :   protected:
      42           28 :     void handleConnect(BLEConnectionHandle conn_handle) override {
      43              :         ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
      44           28 :         this->connection.store(conn_handle);
      45           28 :     }
      46            0 :     void handleDisconnect(
      47              :         [[maybe_unused]] BLEConnectionHandle conn_handle) override {
      48              :         ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
      49            0 :         this->connection.store({});
      50            0 :         this->characteristic.store({});
      51            0 :     }
      52            0 :     void handleMTU([[maybe_unused]] BLEConnectionHandle conn_handle,
      53              :                    uint16_t mtu) override {
      54              :         ESP_LOGD("CS-BLEMIDI", "conn=%d, mtu=%d", conn_handle.conn, mtu);
      55            0 :         Sender::updateMTU(mtu);
      56            0 :     }
      57           28 :     void handleSubscribe(BLEConnectionHandle conn_handle,
      58              :                          BLECharacteristicHandle char_handle,
      59              :                          bool notify) override {
      60              :         ESP_LOGD("CS-BLEMIDI", "conn=%d, char=%d, notify=%d", conn_handle.conn,
      61              :                  char_handle.characteristic, +notify);
      62           28 :         if (notify) {
      63           28 :             this->connection.store(conn_handle);
      64           28 :             this->characteristic.store(char_handle);
      65              :         } else {
      66            0 :             this->characteristic.store({});
      67              :         }
      68           28 :     }
      69           15 :     void handleData([[maybe_unused]] BLEConnectionHandle conn_handle,
      70              :                     BLEDataGenerator &&data, BLEDataLifetime) override {
      71              :         ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
      72           15 :         BLEDataView packet = data();
      73           15 :         if (!packet)
      74            0 :             return;
      75           15 :         if (!parser.pushPacket(packet)) {
      76              :             ESP_LOGE("CS-BLEMIDI", "BLE packet dropped, size=%d",
      77              :                      packet.length);
      78            0 :             return;
      79              :         }
      80           15 :         while (BLEDataView cont = data()) {
      81            0 :             if (!parser.pushPacket(cont, BLEDataType::Continuation)) {
      82              :                 ESP_LOGE("CS-BLEMIDI", "BLE chunk dropped, size=%d",
      83              :                          cont.length);
      84            0 :                 return;
      85              :             } else {
      86              :                 ESP_LOGI("CS-BLEMIDI", "added chunk, size=%d", cont.length);
      87              :             }
      88              :         }
      89              :     }
      90              : 
      91              :   private:
      92              :     struct AtomicSize {
      93              : #ifdef ESP32
      94              :         constexpr static size_t alignment = 32; // default cache size
      95              : #else
      96              :         constexpr static size_t alignment = 64;
      97              : #endif
      98           29 :         AtomicSize(uint_fast16_t value) : value {value} {}
      99              :         std::atomic_uint_fast16_t value;
     100           42 :         uint_fast16_t load_acquire() const {
     101           84 :             return value.load(std::memory_order_acquire);
     102              :         }
     103           15 :         void add_release(uint_fast16_t t) {
     104           15 :             value.fetch_add(t, std::memory_order_release);
     105           15 :         }
     106           27 :         void sub_release(uint_fast16_t t) {
     107           27 :             value.fetch_sub(t, std::memory_order_release);
     108           27 :         }
     109              :     };
     110              :     /// Contains incoming BLE MIDI data to be parsed.
     111              :     BufferedBLEMIDIParser<4096, AtomicSize> parser;
     112              : 
     113              :   public:
     114              :     using IncomingMIDIMessage = AnyMIDIMessage;
     115           52 :     bool popMessage(IncomingMIDIMessage &incomingMessage) {
     116           52 :         return parser.popMessage(incomingMessage);
     117              :     }
     118              : 
     119              :   public:
     120           28 :     void begin(BLESettings ble_settings) {
     121           28 :         impl.init(*this, ble_settings);
     122              :         // Need larger stack than default, pin to non-Arduino core
     123           28 :         ScopedThreadConfig sc {4096, 3, true, "CS-BLEMIDI", 0};
     124           28 :         Sender::begin();
     125           28 :     }
     126              :     void end() {
     127              :         FATAL_ERROR(F("ESP32BLEBackend::end not implemented"), 0x3278);
     128              :     }
     129              :     bool isConnected() const {
     130              :         return connection.load(std::memory_order_relaxed).conn != 0xFFFF;
     131              :     }
     132              :     using Sender::acquirePacket;
     133              :     using Sender::forceMinMTU;
     134              :     using Sender::getMinMTU;
     135              :     using Sender::releasePacketAndNotify;
     136              :     using Sender::sendNow;
     137              :     using Sender::setTimeout;
     138              : };
     139              : 
     140              : END_CS_NAMESPACE
        

Generated by: LCOV version 2.4-beta