// 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 . #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