parent
1b443c5971
commit
1136dcbc53
26 changed files with 1859 additions and 640 deletions
Binary file not shown.
@ -0,0 +1,47 @@ |
||||
#!/usr/bin/env python3 |
||||
import sys |
||||
|
||||
try: |
||||
target_path = sys.argv[1] |
||||
rxbuf_size = 0; rxbuf_minsize = 6144 |
||||
txbuf_size = 0; txbuf_minsize = 384 |
||||
line_index = 0 |
||||
rx_line_index = 0 |
||||
tx_line_index = 0 |
||||
with open(target_path) as sf: |
||||
for line in sf: |
||||
line_index += 1 |
||||
if line.startswith("#define RX_QUEUE_SIZE"): |
||||
ents = line.split(" ") |
||||
try: |
||||
rxbuf_size = int(ents[2]) |
||||
rx_line_index = line_index |
||||
except Exception as e: |
||||
print(f"Could not parse Bluetooth RX_QUEUE_SIZE: {e}") |
||||
|
||||
if line.startswith("#define TX_QUEUE_SIZE"): |
||||
ents = line.split(" ") |
||||
try: |
||||
txbuf_size = int(ents[2]) |
||||
tx_line_index = line_index |
||||
except Exception as e: |
||||
print(f"Could not parse Bluetooth RX_QUEUE_SIZE: {e}") |
||||
|
||||
if rxbuf_size != 0 and txbuf_size != 0: |
||||
break |
||||
|
||||
if rxbuf_size < rxbuf_minsize: |
||||
print(f"Error: The configured ESP32 Bluetooth RX buffer size is too small, please set it to at least {rxbuf_minsize} and try compiling again.") |
||||
print(f"The buffer configuration can be modified in line {rx_line_index} of: {target_path}") |
||||
exit(1) |
||||
|
||||
if txbuf_size < txbuf_minsize: |
||||
print(f"Error: The configured ESP32 Bluetooth TX buffer size is too small, please set it to at least {txbuf_minsize} and try compiling again.") |
||||
print(f"The buffer configuration can be modified in line {tx_line_index} of: {target_path}") |
||||
exit(1) |
||||
|
||||
exit(0) |
||||
|
||||
except Exception as e: |
||||
print(f"Could not determine ESP32 Bluetooth buffer configuration: {e}") |
||||
print("Please fix this error and try again") |
@ -0,0 +1,155 @@ |
||||
// Copyright (C) 2024, Mark Qvist
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// This class is for BLE serial functionality on ESP32 boards ONLY
|
||||
|
||||
#include <Arduino.h> |
||||
#include "../../Boards.h" |
||||
|
||||
#if PLATFORM != PLATFORM_NRF52 |
||||
#if HAS_BLE |
||||
|
||||
#include "BLESerial.h" |
||||
|
||||
uint32_t bt_passkey_callback(); |
||||
void bt_passkey_notify_callback(uint32_t passkey); |
||||
bool bt_security_request_callback(); |
||||
void bt_authentication_complete_callback(esp_ble_auth_cmpl_t auth_result); |
||||
bool bt_confirm_pin_callback(uint32_t pin); |
||||
void bt_connect_callback(BLEServer *server); |
||||
void bt_disconnect_callback(BLEServer *server); |
||||
bool bt_client_authenticated(); |
||||
|
||||
uint32_t BLESerial::onPassKeyRequest() { return bt_passkey_callback(); } |
||||
void BLESerial::onPassKeyNotify(uint32_t passkey) { bt_passkey_notify_callback(passkey); } |
||||
bool BLESerial::onSecurityRequest() { return bt_security_request_callback(); } |
||||
void BLESerial::onAuthenticationComplete(esp_ble_auth_cmpl_t auth_result) { bt_authentication_complete_callback(auth_result); } |
||||
void BLESerial::onConnect(BLEServer *server) { bt_connect_callback(server); } |
||||
void BLESerial::onDisconnect(BLEServer *server) { bt_disconnect_callback(server); ble_server->startAdvertising(); } |
||||
bool BLESerial::onConfirmPIN(uint32_t pin) { return bt_confirm_pin_callback(pin); }; |
||||
bool BLESerial::connected() { return ble_server->getConnectedCount() > 0; } |
||||
|
||||
int BLESerial::read() { |
||||
int result = this->rx_buffer.pop(); |
||||
if (result == '\n') { this->numAvailableLines--; } |
||||
return result; |
||||
} |
||||
|
||||
size_t BLESerial::readBytes(uint8_t *buffer, size_t bufferSize) { |
||||
int i = 0; |
||||
while (i < bufferSize && available()) { buffer[i] = (uint8_t)this->rx_buffer.pop(); i++; } |
||||
return i; |
||||
} |
||||
|
||||
int BLESerial::peek() { |
||||
if (this->rx_buffer.getLength() == 0) return -1; |
||||
return this->rx_buffer.get(0); |
||||
} |
||||
|
||||
int BLESerial::available() { return this->rx_buffer.getLength(); } |
||||
|
||||
size_t BLESerial::print(const char *str) { |
||||
if (ble_server->getConnectedCount() <= 0) return 0; |
||||
size_t written = 0; for (size_t i = 0; str[i] != '\0'; i++) { written += this->write(str[i]); } |
||||
flush(); |
||||
|
||||
return written; |
||||
} |
||||
|
||||
size_t BLESerial::write(const uint8_t *buffer, size_t bufferSize) { |
||||
if (ble_server->getConnectedCount() <= 0) { return 0; } else { |
||||
size_t written = 0; for (int i = 0; i < bufferSize; i++) { written += this->write(buffer[i]); } |
||||
flush(); |
||||
|
||||
return written; |
||||
} |
||||
} |
||||
|
||||
size_t BLESerial::write(uint8_t byte) { |
||||
if (bt_client_authenticated()) { |
||||
if (ble_server->getConnectedCount() <= 0) { return 0; } else { |
||||
this->transmitBuffer[this->transmitBufferLength] = byte; |
||||
this->transmitBufferLength++; |
||||
if (this->transmitBufferLength == maxTransferSize) { flush(); } |
||||
return 1; |
||||
} |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
void BLESerial::flush() { |
||||
if (this->transmitBufferLength > 0) { |
||||
TxCharacteristic->setValue(this->transmitBuffer, this->transmitBufferLength); |
||||
this->transmitBufferLength = 0; |
||||
this->lastFlushTime = millis(); |
||||
TxCharacteristic->notify(true); |
||||
} |
||||
} |
||||
|
||||
void BLESerial::begin(const char *name) { |
||||
ConnectedDeviceCount = 0; |
||||
BLEDevice::init(name); |
||||
|
||||
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
|
||||
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9); |
||||
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9); |
||||
|
||||
ble_server = BLEDevice::createServer(); |
||||
ble_server->setCallbacks(this); |
||||
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM); |
||||
BLEDevice::setSecurityCallbacks(this); |
||||
|
||||
SetupSerialService(); |
||||
|
||||
ble_adv = BLEDevice::getAdvertising(); |
||||
ble_adv->addServiceUUID(BLE_SERIAL_SERVICE_UUID); |
||||
ble_adv->setMinPreferred(0x20); |
||||
ble_adv->setMaxPreferred(0x40); |
||||
ble_adv->setScanResponse(true); |
||||
ble_adv->start(); |
||||
} |
||||
|
||||
void BLESerial::end() { BLEDevice::deinit(); } |
||||
|
||||
void BLESerial::onWrite(BLECharacteristic *characteristic) { |
||||
if (characteristic->getUUID().toString() == BLE_RX_UUID) { |
||||
auto value = characteristic->getValue(); |
||||
for (int i = 0; i < value.length(); i++) { rx_buffer.push(value[i]); } |
||||
} |
||||
} |
||||
|
||||
void BLESerial::SetupSerialService() { |
||||
SerialService = ble_server->createService(BLE_SERIAL_SERVICE_UUID); |
||||
|
||||
RxCharacteristic = SerialService->createCharacteristic(BLE_RX_UUID, BLECharacteristic::PROPERTY_WRITE); |
||||
RxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM); |
||||
RxCharacteristic->addDescriptor(new BLE2902()); |
||||
RxCharacteristic->setWriteProperty(true); |
||||
RxCharacteristic->setCallbacks(this); |
||||
|
||||
TxCharacteristic = SerialService->createCharacteristic(BLE_TX_UUID, BLECharacteristic::PROPERTY_NOTIFY); |
||||
TxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM); |
||||
TxCharacteristic->addDescriptor(new BLE2902()); |
||||
TxCharacteristic->setNotifyProperty(true); |
||||
TxCharacteristic->setReadProperty(true); |
||||
|
||||
SerialService->start(); |
||||
} |
||||
|
||||
BLESerial::BLESerial() { } |
||||
|
||||
#endif |
||||
#endif |
@ -0,0 +1,135 @@ |
||||
// Copyright (C) 2024, Mark Qvist
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// This class is for BLE serial functionality on ESP32 boards ONLY
|
||||
|
||||
#include "../../Boards.h" |
||||
|
||||
#if PLATFORM != PLATFORM_NRF52 |
||||
#if HAS_BLE |
||||
|
||||
#include <Arduino.h> |
||||
|
||||
#include <BLEDevice.h> |
||||
#include <BLEUtils.h> |
||||
#include <BLEServer.h> |
||||
#include <BLE2902.h> |
||||
|
||||
template <size_t n> |
||||
class BLEFIFO { |
||||
private: |
||||
uint8_t buffer[n]; |
||||
int head = 0; |
||||
int tail = 0; |
||||
|
||||
public: |
||||
void push(uint8_t value) { |
||||
buffer[head] = value; |
||||
head = (head + 1) % n; |
||||
if (head == tail) { tail = (tail + 1) % n; } |
||||
} |
||||
|
||||
int pop() { |
||||
if (head == tail) { |
||||
return -1; |
||||
} else { |
||||
uint8_t value = buffer[tail]; |
||||
tail = (tail + 1) % n; |
||||
return value; |
||||
} |
||||
} |
||||
|
||||
void clear() { head = 0; tail = 0; } |
||||
|
||||
int get(size_t index) { |
||||
if (index >= this->getLength()) { |
||||
return -1; |
||||
} else { |
||||
return buffer[(tail + index) % n]; |
||||
} |
||||
} |
||||
|
||||
size_t getLength() { |
||||
if (head >= tail) { |
||||
return head - tail; |
||||
} else { |
||||
return n - tail + head; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
#define RX_BUFFER_SIZE 6144 |
||||
#define BLE_BUFFER_SIZE 512 // Must fit in max GATT attribute length
|
||||
#define MIN_MTU 50 |
||||
|
||||
class BLESerial : public BLECharacteristicCallbacks, public BLEServerCallbacks, public BLESecurityCallbacks, public Stream { |
||||
public: |
||||
BLESerial(); |
||||
|
||||
void begin(const char *name); |
||||
void end(); |
||||
void onWrite(BLECharacteristic *characteristic); |
||||
int available(); |
||||
int peek(); |
||||
int read(); |
||||
size_t readBytes(uint8_t *buffer, size_t bufferSize); |
||||
size_t write(uint8_t byte); |
||||
size_t write(const uint8_t *buffer, size_t bufferSize); |
||||
size_t print(const char *value); |
||||
void flush(); |
||||
void onConnect(BLEServer *server); |
||||
void onDisconnect(BLEServer *server); |
||||
|
||||
uint32_t onPassKeyRequest(); |
||||
void onPassKeyNotify(uint32_t passkey); |
||||
bool onSecurityRequest(); |
||||
void onAuthenticationComplete(esp_ble_auth_cmpl_t); |
||||
bool onConfirmPIN(uint32_t pin); |
||||
|
||||
bool connected(); |
||||
|
||||
BLEServer *ble_server; |
||||
BLEAdvertising *ble_adv; |
||||
BLEService *SerialService; |
||||
BLECharacteristic *TxCharacteristic; |
||||
BLECharacteristic *RxCharacteristic; |
||||
size_t transmitBufferLength; |
||||
unsigned long long lastFlushTime; |
||||
|
||||
private: |
||||
BLESerial(BLESerial const &other) = delete; |
||||
void operator=(BLESerial const &other) = delete; |
||||
|
||||
BLEFIFO<RX_BUFFER_SIZE> rx_buffer; |
||||
size_t numAvailableLines; |
||||
uint8_t transmitBuffer[BLE_BUFFER_SIZE]; |
||||
|
||||
int ConnectedDeviceCount; |
||||
void SetupSerialService(); |
||||
|
||||
uint16_t peerMTU; |
||||
uint16_t maxTransferSize = BLE_BUFFER_SIZE; |
||||
|
||||
bool checkMTU(); |
||||
|
||||
const char *BLE_SERIAL_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; |
||||
const char *BLE_RX_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"; |
||||
const char *BLE_TX_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; |
||||
|
||||
bool started = false; |
||||
}; |
||||
|
||||
#endif |
||||
#endif |
Loading…
Reference in new issue