mirror of https://github.com/meshcore-dev/MeshCore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.2 KiB
200 lines
4.2 KiB
#pragma once
|
|
|
|
#include "BaseSerialInterface.h"
|
|
|
|
#ifndef MAX_INTERFACES
|
|
// ble, usb, wifi, ethernet
|
|
#define MAX_INTERFACES 4
|
|
#endif
|
|
|
|
enum class InterfaceType : uint8_t {
|
|
NONE,
|
|
Bluetooth,
|
|
USB,
|
|
WiFi,
|
|
Ethernet,
|
|
HardwareSerial
|
|
};
|
|
|
|
class MultiSerialInterface : public BaseSerialInterface {
|
|
private:
|
|
|
|
struct RegisteredInterface {
|
|
InterfaceType type = InterfaceType::NONE;
|
|
BaseSerialInterface* instance = nullptr;
|
|
};
|
|
|
|
bool _enabled = false;
|
|
RegisteredInterface _interfaces[MAX_INTERFACES] = {};
|
|
|
|
public:
|
|
bool addInterface(InterfaceType type, BaseSerialInterface* iface) {
|
|
// make sure an interface was provided
|
|
if(iface == nullptr){
|
|
return false;
|
|
}
|
|
|
|
// put it in the first free slot
|
|
for(int i = 0; i < MAX_INTERFACES; i++){
|
|
if(_interfaces[i].instance == nullptr){
|
|
_interfaces[i].instance = iface;
|
|
_interfaces[i].type = type;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// no free slots available
|
|
return false;
|
|
}
|
|
|
|
bool removeInterface(BaseSerialInterface* iface) {
|
|
// make sure an interface was provided
|
|
if(iface == nullptr){
|
|
return false;
|
|
}
|
|
|
|
// find and remove interface
|
|
for(int i = 0; i < MAX_INTERFACES; i++){
|
|
if(_interfaces[i].instance == iface){
|
|
_interfaces[i] = {};
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// interface not found
|
|
return false;
|
|
}
|
|
|
|
void enableBluetooth() {
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.type == InterfaceType::Bluetooth){
|
|
iface.instance->enable();
|
|
}
|
|
}
|
|
}
|
|
|
|
void disableBluetooth() {
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.type == InterfaceType::Bluetooth){
|
|
iface.instance->disable();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isBluetoothEnabled() {
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.type == InterfaceType::Bluetooth){
|
|
return iface.instance->isEnabled();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// enable all interfaces
|
|
void enable() override {
|
|
_enabled = true;
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance){
|
|
iface.instance->enable();
|
|
}
|
|
}
|
|
}
|
|
|
|
// disable all interfaces
|
|
void disable() override {
|
|
_enabled = false;
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance){
|
|
iface.instance->disable();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isEnabled() const override {
|
|
return _enabled;
|
|
}
|
|
|
|
bool isConnected() const override {
|
|
// not connected when disabled
|
|
if(!_enabled){
|
|
return false;
|
|
}
|
|
|
|
// check if any interface is connected
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.instance->isConnected()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// nothing connected
|
|
return false;
|
|
}
|
|
|
|
// loop all interfaces
|
|
void loop() override {
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance){
|
|
iface.instance->loop();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isWriteBusy() const override {
|
|
// not busy when disabled
|
|
if(!_enabled){
|
|
return false;
|
|
}
|
|
|
|
// check if any interface is busy
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.instance->isEnabled() && iface.instance->isWriteBusy()){
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// nothing busy
|
|
return false;
|
|
}
|
|
|
|
size_t writeFrame(const uint8_t src[], size_t len) override {
|
|
// don't write when disabled or nothing provided
|
|
if(!_enabled || len == 0){
|
|
return 0;
|
|
}
|
|
|
|
// write frame to all enabled interfaces
|
|
bool allSuccessful = true;
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.instance->isEnabled()){
|
|
if(iface.instance->writeFrame(src, len) != len){
|
|
allSuccessful = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// report success if all writes completed successfully
|
|
return allSuccessful ? len : 0;
|
|
}
|
|
|
|
size_t checkRecvFrame(uint8_t dest[]) override {
|
|
// don't read when disabled
|
|
if(!_enabled){
|
|
return 0;
|
|
}
|
|
|
|
// try to read a frame from any enabled interface
|
|
for(auto iface : _interfaces){
|
|
if(iface.instance && iface.instance->isEnabled()){
|
|
size_t frameSize = iface.instance->checkRecvFrame(dest);
|
|
if(frameSize > 0){
|
|
return frameSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// no frame received
|
|
return 0;
|
|
}
|
|
|
|
};
|
|
|