mirror of https://github.com/arendst/Tasmota.git
Merge pull request #12942 from Jason2866/C3_BLE
BLE support for ESP32-C3
This commit is contained in:
commit
308e4a536d
|
@ -4,6 +4,7 @@
|
|||
"ldscript": "esp32c3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DBOARD_HAS_PSRAM",
|
||||
"f_cpu": "160000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dout",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"ldscript": "esp32s2_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DBOARD_HAS_PSRAM",
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dout",
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
/*
|
||||
* Xtensa toolchain declares `int32_t` as `int` but RISC-V toolchain
|
||||
* declares `int32_t` as `long int` which causes compilation errors.
|
||||
*
|
||||
*
|
||||
* See:
|
||||
* https://github.com/espressif/esp-idf/issues/6906
|
||||
* https://github.com/espressif/arduino-esp32/issues/5086
|
||||
*
|
||||
* You need to add the following lines in `build_flags`:
|
||||
*
|
||||
* You need to add the following lines in `build_flags`:
|
||||
* -I$PROJECT_DIR/include
|
||||
* -include "esp32x_fixes.h"
|
||||
*/
|
||||
|
@ -39,16 +39,27 @@
|
|||
|
||||
#endif // __riscv
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
// fix a bug in esp-idf 4.4 for esp32c3
|
||||
#ifndef REG_SPI_BASE
|
||||
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 )))
|
||||
#endif
|
||||
//alias, deprecated for the chips after esp32s2
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define SPI_HOST SPI1_HOST
|
||||
#define HSPI_HOST SPI2_HOST
|
||||
#define VSPI_HOST SPI3_HOST
|
||||
|
||||
// SPI_MOSI_DLEN_REG is not defined anymore in esp32c3, instead use SPI_MS_DLEN_REG
|
||||
#define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x)
|
||||
//alias for different chips, deprecated for the chips after esp32s2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master and SPI Slave driver on ESP32-S2 and later
|
||||
#define SPI_HOST SPI1_HOST
|
||||
#define FSPI_HOST SPI2_HOST
|
||||
#define HSPI_HOST SPI3_HOST
|
||||
#define VSPI_HOST SPI3_HOST
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define SPI_HOST SPI1_HOST
|
||||
#define HSPI_HOST SPI2_HOST
|
||||
#define VSPI_HOST SPI2_HOST /* No SPI3_host on C3 */
|
||||
#endif
|
||||
// fix a bug in esp-idf 4.4 for esp32c3
|
||||
#ifndef REG_SPI_BASE
|
||||
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 )))
|
||||
// SPI_MOSI_DLEN_REG is not defined anymore in esp32c3, instead use SPI_MS_DLEN_REG
|
||||
#define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x)
|
||||
#endif // REG_SPI_BASE
|
||||
#endif // TARGET
|
||||
|
|
|
@ -2,6 +2,52 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.3.1] - 2021-08-04
|
||||
|
||||
### Fixed
|
||||
- Corrected a compiler/linker error when an application or a library uses bluetooth classic due to the redefinition of `btInUse`.
|
||||
|
||||
## [1.3.0] - 2021-08-02
|
||||
|
||||
### Added
|
||||
- `NimBLECharacteristic::removeDescriptor`: Dynamically remove a descriptor from a characterisic. Takes effect after all connections are closed and sends a service changed indication.
|
||||
- `NimBLEService::removeCharacteristic`: Dynamically remove a characteristic from a service. Takes effect after all connections are closed and sends a service changed indication
|
||||
- `NimBLEServerCallbacks::onMTUChange`: This is callback is called when the MTU is updated after connection with a client.
|
||||
- ESP32C3 support
|
||||
|
||||
- Whitelist API:
|
||||
- `NimBLEDevice::whiteListAdd`: Add a device to the whitelist.
|
||||
- `NimBLEDevice::whiteListRemove`: Remove a device from the whitelist.
|
||||
- `NimBLEDevice::onWhiteList`: Check if the device is on the whitelist.
|
||||
- `NimBLEDevice::getWhiteListCount`: Gets the size of the whitelist
|
||||
- `NimBLEDevice::getWhiteListAddress`: Get the address of a device on the whitelist by index value.
|
||||
|
||||
- Bond management API:
|
||||
- `NimBLEDevice::getNumBonds`: Gets the number of bonds stored.
|
||||
- `NimBLEDevice::isBonded`: Checks if the device is bonded.
|
||||
- `NimBLEDevice::deleteAllBonds`: Deletes all bonds.
|
||||
- `NimBLEDevice::getBondedAddress`: Gets the address of a bonded device by the index value.
|
||||
|
||||
- `NimBLECharacteristic::getCallbacks` to retrieve the current callback handler.
|
||||
- Connection Information class: `NimBLEConnInfo`.
|
||||
- `NimBLEScan::clearDuplicateCache`: This can be used to reset the cache of advertised devices so they will be immediately discovered again.
|
||||
|
||||
### Changed
|
||||
- FreeRTOS files have been removed as they are not used by the library.
|
||||
- Services, characteristics and descriptors can now be created statically and added after.
|
||||
- Excess logging and some asserts removed.
|
||||
- Use ESP_LOGx macros to enable using local log level filtering.
|
||||
|
||||
### Fixed
|
||||
- `NimBLECharacteristicCallbacks::onSubscribe` Is now called after the connection is added to the vector.
|
||||
- Corrected bonding failure when reinitializing the BLE stack.
|
||||
- Writing to a characterisic with a std::string value now correctly writes values with null characters.
|
||||
- Retrieving remote descriptors now uses the characterisic end handle correctly.
|
||||
- Missing data in long writes to remote descriptors.
|
||||
- Hanging on task notification when sending an indication from the characteristic callback.
|
||||
- BLE controller memory could be released when using Arduino as a component.
|
||||
- Complile errors with NimBLE release 1.3.0.
|
||||
|
||||
## [1.2.0] - 2021-02-08
|
||||
|
||||
### Added
|
||||
|
|
|
@ -72,9 +72,9 @@ such as increasing max connections, default is 3, absolute maximum connections i
|
|||
<br/>
|
||||
|
||||
# Development Status
|
||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@f4ae049.](https://github.com/espressif/esp-nimble)
|
||||
This Library is tracking the esp-nimble repo, nimble-1.3.0-idf master branch, currently [@5bb7b40.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@3caa969.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@639e7ad.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
<br/>
|
||||
|
||||
# Acknowledgments
|
||||
|
@ -82,10 +82,4 @@ Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@
|
|||
* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples.
|
||||
* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
|
||||
<br/>
|
||||
|
||||
# Todo
|
||||
- Improve host reset handler
|
||||
- Implement random address handling
|
||||
- Implement bond management
|
||||
- Add Bluetooth Mesh
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -69,8 +69,6 @@ For example `BLEServer::createService(SERVICE_UUID)` will work just as it did be
|
|||
|
||||
<a name="characteristics"></a>
|
||||
### Characteristics
|
||||
The constructor for `(Nim)BLECharacteristic` is now private, so if you currently subclass it to add logic you should switch to use `NimBLEService::createCharacteristic` instead. Any custom processing logic previously in a `BLECharacteristic` subclass should be moved to a `NimBLECharacteristicCallbacks` subclass instead, and passed into `NimBLECharacteristic::setCallbacks`.
|
||||
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* NimBLE_Scan_Whitelist demo
|
||||
*
|
||||
* Created May 16, 2021
|
||||
* Author: h2zero
|
||||
*/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
int scanTime = 5; //In seconds
|
||||
NimBLEScan* pBLEScan;
|
||||
|
||||
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
||||
Serial.printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
||||
/*
|
||||
* Here we add the device scanned to the whitelist based on service data but any
|
||||
* advertised data can be used for your preffered data.
|
||||
*/
|
||||
if (advertisedDevice->haveServiceData()) {
|
||||
/* If this is a device with data we want to capture, add it to the whitelist */
|
||||
if (advertisedDevice->getServiceData(NimBLEUUID("AABB")) != "") {
|
||||
Serial.printf("Adding %s to whitelist\n", std::string(advertisedDevice->getAddress()).c_str());
|
||||
NimBLEDevice::whiteListAdd(advertisedDevice->getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scanning...");
|
||||
|
||||
NimBLEDevice::init("");
|
||||
pBLEScan = NimBLEDevice::getScan();
|
||||
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
|
||||
pBLEScan->setActiveScan(true);
|
||||
pBLEScan->setInterval(100);
|
||||
pBLEScan->setFilterPolicy(BLE_HCI_SCAN_FILT_NO_WL);
|
||||
pBLEScan->setWindow(99);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
NimBLEScanResults foundDevices = pBLEScan->start(scanTime, false);
|
||||
Serial.print("Devices found: ");
|
||||
Serial.println(foundDevices.getCount());
|
||||
Serial.println("Scan done!");
|
||||
|
||||
Serial.println("Whitelist contains:");
|
||||
for (auto i=0; i<NimBLEDevice::getWhiteListCount(); ++i) {
|
||||
Serial.println(NimBLEDevice::getWhiteListAddress(i).toString().c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have addresses in the whitelist enable the filter unless no devices were found
|
||||
* then scan without so we can find any new devices that we want.
|
||||
*/
|
||||
if (NimBLEDevice::getWhiteListCount() > 0) {
|
||||
if (foundDevices.getCount() == 0) {
|
||||
pBLEScan->setFilterPolicy(BLE_HCI_SCAN_FILT_NO_WL);
|
||||
} else {
|
||||
pBLEScan->setFilterPolicy(BLE_HCI_SCAN_FILT_USE_WL);
|
||||
}
|
||||
}
|
||||
pBLEScan->clearResults();
|
||||
delay(2000);
|
||||
}
|
|
@ -39,6 +39,9 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
|||
Serial.println("Client disconnected - start advertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
};
|
||||
void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc) {
|
||||
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
|
||||
};
|
||||
|
||||
/********************* Security handled here **********************
|
||||
****** Note: these are the same return values as defaults ********/
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* NimBLE_Server_Whitelist demo
|
||||
*
|
||||
* Created May 17, 2021
|
||||
* Author: h2zero
|
||||
*/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
NimBLECharacteristic* pCharacteristic = nullptr;
|
||||
bool deviceConnected = false;
|
||||
bool oldDeviceConnected = false;
|
||||
uint32_t value = 0;
|
||||
|
||||
// See the following for generating UUIDs:
|
||||
// https://www.uuidgenerator.net/
|
||||
|
||||
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
|
||||
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
|
||||
|
||||
|
||||
class MyServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer) {
|
||||
deviceConnected = true;
|
||||
};
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||
// Peer disconnected, add them to the whitelist
|
||||
// This allows us to use the whitelist to filter connection attempts
|
||||
// which will minimize reconnection time.
|
||||
NimBLEDevice::whiteListAdd(NimBLEAddress(desc->peer_ota_addr));
|
||||
deviceConnected = false;
|
||||
}
|
||||
};
|
||||
|
||||
void onAdvComplete(NimBLEAdvertising *pAdvertising) {
|
||||
Serial.println("Advertising stopped");
|
||||
if (deviceConnected) {
|
||||
return;
|
||||
}
|
||||
// If advertising timed out without connection start advertising without whitelist filter
|
||||
pAdvertising->setScanFilter(false,false);
|
||||
pAdvertising->start();
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Create the BLE Device
|
||||
NimBLEDevice::init("ESP32");
|
||||
|
||||
// Create the BLE Server
|
||||
NimBLEServer* pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new MyServerCallbacks());
|
||||
pServer->advertiseOnDisconnect(false);
|
||||
|
||||
// Create the BLE Service
|
||||
NimBLEService *pService = pServer->createService(SERVICE_UUID);
|
||||
|
||||
// Create a BLE Characteristic
|
||||
pCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE |
|
||||
NIMBLE_PROPERTY::NOTIFY );
|
||||
|
||||
// Start the service
|
||||
pService->start();
|
||||
|
||||
// Start advertising
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||
pAdvertising->setScanResponse(false);
|
||||
pAdvertising->start();
|
||||
Serial.println("Waiting a client connection to notify...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// notify changed value
|
||||
if (deviceConnected) {
|
||||
pCharacteristic->setValue((uint8_t*)&value, 4);
|
||||
pCharacteristic->notify();
|
||||
value++;
|
||||
}
|
||||
// disconnecting
|
||||
if (!deviceConnected && oldDeviceConnected) {
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
if (NimBLEDevice::getWhiteListCount() > 0) {
|
||||
// Allow anyone to scan but only whitelisted can connect.
|
||||
pAdvertising->setScanFilter(false,true);
|
||||
}
|
||||
// advertise with whitelist for 30 seconds
|
||||
pAdvertising->start(30, onAdvComplete);
|
||||
Serial.println("start advertising");
|
||||
oldDeviceConnected = deviceConnected;
|
||||
}
|
||||
// connecting
|
||||
if (deviceConnected && !oldDeviceConnected) {
|
||||
// do stuff here on connecting
|
||||
oldDeviceConnected = deviceConnected;
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"name": "NimBLE-Arduino",
|
||||
"keywords": "esp32, bluetooth",
|
||||
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=NimBLE-Arduino
|
||||
version=1.2.0
|
||||
version=1.3.1
|
||||
author=h2zero
|
||||
maintainer=h2zero <powellperalta@gmail.com>
|
||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||
|
|
|
@ -1,316 +0,0 @@
|
|||
/*
|
||||
* FreeRTOS.cpp
|
||||
*
|
||||
* Created on: Feb 24, 2017
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h> // Include the base FreeRTOS definitions
|
||||
#include <freertos/task.h> // Include the task definitions
|
||||
#include <freertos/semphr.h> // Include the semaphore definitions
|
||||
#include <string>
|
||||
|
||||
static const char* LOG_TAG = "FreeRTOS";
|
||||
|
||||
|
||||
/**
|
||||
* Sleep for the specified number of milliseconds.
|
||||
* @param[in] ms The period in milliseconds for which to sleep.
|
||||
*/
|
||||
void FreeRTOS::sleep(uint32_t ms) {
|
||||
::vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
} // sleep
|
||||
|
||||
|
||||
/**
|
||||
* Start a new task.
|
||||
* @param[in] task The function pointer to the function to be run in the task.
|
||||
* @param[in] taskName A string identifier for the task.
|
||||
* @param[in] param An optional parameter to be passed to the started task.
|
||||
* @param[in] stackSize An optional paremeter supplying the size of the stack in which to run the task.
|
||||
*/
|
||||
void FreeRTOS::startTask(void task(void*), std::string taskName, void* param, uint32_t stackSize) {
|
||||
::xTaskCreate(task, taskName.data(), stackSize, param, 5, NULL);
|
||||
} // startTask
|
||||
|
||||
|
||||
/**
|
||||
* Delete the task.
|
||||
* @param[in] pTask An optional handle to the task to be deleted. If not supplied the calling task will be deleted.
|
||||
*/
|
||||
void FreeRTOS::deleteTask(TaskHandle_t pTask) {
|
||||
::vTaskDelete(pTask);
|
||||
} // deleteTask
|
||||
|
||||
|
||||
/**
|
||||
* Get the time in milliseconds since the %FreeRTOS scheduler started.
|
||||
* @return The time in milliseconds since the %FreeRTOS scheduler started.
|
||||
*/
|
||||
uint32_t FreeRTOS::getTimeSinceStart() {
|
||||
return (uint32_t) (xTaskGetTickCount() * portTICK_PERIOD_MS);
|
||||
} // getTimeSinceStart
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wait for a semaphore to be released by trying to take it and
|
||||
* then releasing it again.
|
||||
* @param [in] owner A debug tag.
|
||||
* @return The value associated with the semaphore.
|
||||
*/
|
||||
uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreTake(m_semaphore, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore released: %s", toString().c_str());
|
||||
return m_value;
|
||||
} // wait
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wait for a semaphore to be released in a given period of time by trying to take it and
|
||||
* then releasing it again. The value associated with the semaphore can be taken by value() call after return
|
||||
* @param [in] owner A debug tag.
|
||||
* @param [in] timeoutMs timeout to wait in ms.
|
||||
* @return True if we took the semaphore within timeframe.
|
||||
*/
|
||||
bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
|
||||
|
||||
if (m_usePthreads && timeoutMs != portMAX_DELAY) {
|
||||
assert(false); // We apparently don't have a timed wait for pthreads.
|
||||
}
|
||||
|
||||
auto ret = pdTRUE;
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
ret = xSemaphoreTake(m_semaphore, timeoutMs);
|
||||
}
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret);
|
||||
return ret;
|
||||
} // wait
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a semaphore, the semaphore is given when created.
|
||||
* @param [in] name A name string to provide debugging support.
|
||||
*/
|
||||
FreeRTOS::Semaphore::Semaphore(std::string name) {
|
||||
m_usePthreads = false; // Are we using pThreads or FreeRTOS?
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_init(&m_pthread_mutex, nullptr);
|
||||
} else {
|
||||
//m_semaphore = xSemaphoreCreateMutex();
|
||||
m_semaphore = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
|
||||
m_name = name;
|
||||
m_owner = std::string("<N/A>");
|
||||
m_value = 0;
|
||||
}
|
||||
|
||||
|
||||
FreeRTOS::Semaphore::~Semaphore() {
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_destroy(&m_pthread_mutex);
|
||||
} else {
|
||||
vSemaphoreDelete(m_semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Give the semaphore.
|
||||
*/
|
||||
void FreeRTOS::Semaphore::give() {
|
||||
NIMBLE_LOGD(LOG_TAG, "Semaphore giving: %s", toString().c_str());
|
||||
m_owner = std::string("<N/A>");
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
// #ifdef ARDUINO_ARCH_ESP32
|
||||
// FreeRTOS::sleep(10);
|
||||
// #endif
|
||||
|
||||
} // Semaphore::give
|
||||
|
||||
|
||||
/**
|
||||
* @brief Give a semaphore.
|
||||
* The Semaphore is given with an associated value.
|
||||
* @param [in] value The value to associate with the semaphore.
|
||||
*/
|
||||
void FreeRTOS::Semaphore::give(uint32_t value) {
|
||||
m_value = value;
|
||||
give();
|
||||
} // give
|
||||
|
||||
|
||||
/**
|
||||
* @brief Give a semaphore from an ISR.
|
||||
*/
|
||||
void FreeRTOS::Semaphore::giveFromISR() {
|
||||
BaseType_t higherPriorityTaskWoken;
|
||||
if (m_usePthreads) {
|
||||
assert(false);
|
||||
} else {
|
||||
xSemaphoreGiveFromISR(m_semaphore, &higherPriorityTaskWoken);
|
||||
}
|
||||
} // giveFromISR
|
||||
|
||||
|
||||
/**
|
||||
* @brief Take a semaphore.
|
||||
* Take a semaphore and wait indefinitely.
|
||||
* @param [in] owner The new owner (for debugging)
|
||||
* @return True if we took the semaphore.
|
||||
*/
|
||||
bool FreeRTOS::Semaphore::take(std::string owner) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
|
||||
bool rc = false;
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
rc = ::xSemaphoreTake(m_semaphore, portMAX_DELAY) == pdTRUE;
|
||||
}
|
||||
m_owner = owner;
|
||||
if (rc) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Semaphore taken: %s", toString().c_str());
|
||||
} else {
|
||||
NIMBLE_LOGE(LOG_TAG, "Semaphore NOT taken: %s", toString().c_str());
|
||||
}
|
||||
return rc;
|
||||
} // Semaphore::take
|
||||
|
||||
|
||||
/**
|
||||
* @brief Take a semaphore.
|
||||
* Take a semaphore but return if we haven't obtained it in the given period of milliseconds.
|
||||
* @param [in] timeoutMs Timeout in milliseconds.
|
||||
* @param [in] owner The new owner (for debugging)
|
||||
* @return True if we took the semaphore.
|
||||
*/
|
||||
bool FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
|
||||
bool rc = false;
|
||||
if (m_usePthreads) {
|
||||
assert(false); // We apparently don't have a timed wait for pthreads.
|
||||
} else {
|
||||
rc = ::xSemaphoreTake(m_semaphore, timeoutMs / portTICK_PERIOD_MS) == pdTRUE;
|
||||
}
|
||||
m_owner = owner;
|
||||
if (rc) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Semaphore taken: %s", toString().c_str());
|
||||
} else {
|
||||
NIMBLE_LOGE(LOG_TAG, "Semaphore NOT taken: %s", toString().c_str());
|
||||
}
|
||||
return rc;
|
||||
} // Semaphore::take
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a string representation of the semaphore.
|
||||
* @return A string representation of the semaphore.
|
||||
*/
|
||||
std::string FreeRTOS::Semaphore::toString() {
|
||||
char hex[9];
|
||||
std::string res = "name: " + m_name + " (0x";
|
||||
snprintf(hex, sizeof(hex), "%08x", (uint32_t)m_semaphore);
|
||||
res += hex;
|
||||
res += "), owner: " + m_owner;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the name of the semaphore.
|
||||
* @param [in] name The name of the semaphore.
|
||||
*/
|
||||
void FreeRTOS::Semaphore::setName(std::string name) {
|
||||
m_name = name;
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a ring buffer.
|
||||
* @param [in] length The amount of storage to allocate for the ring buffer.
|
||||
* @param [in] type The type of buffer. One of RINGBUF_TYPE_NOSPLIT, RINGBUF_TYPE_ALLOWSPLIT, RINGBUF_TYPE_BYTEBUF.
|
||||
*/
|
||||
#ifdef ESP_IDF_VERSION //Quick hack to detect if using IDF version that replaced ringbuf_type_t
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
|
||||
Ringbuffer::Ringbuffer(size_t length, RingbufferType_t type) {
|
||||
#else
|
||||
Ringbuffer::Ringbuffer(size_t length, ringbuf_type_t type) {
|
||||
#endif
|
||||
#else
|
||||
Ringbuffer::Ringbuffer(size_t length, ringbuf_type_t type) {
|
||||
#endif
|
||||
m_handle = ::xRingbufferCreate(length, type);
|
||||
} // Ringbuffer
|
||||
|
||||
|
||||
Ringbuffer::~Ringbuffer() {
|
||||
::vRingbufferDelete(m_handle);
|
||||
} // ~Ringbuffer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Receive data from the buffer.
|
||||
* @param [out] size On return, the size of data returned.
|
||||
* @param [in] wait How long to wait.
|
||||
* @return A pointer to the storage retrieved.
|
||||
*/
|
||||
void* Ringbuffer::receive(size_t* size, TickType_t wait) {
|
||||
return ::xRingbufferReceive(m_handle, size, wait);
|
||||
} // receive
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return an item.
|
||||
* @param [in] item The item to be returned/released.
|
||||
*/
|
||||
void Ringbuffer::returnItem(void* item) {
|
||||
::vRingbufferReturnItem(m_handle, item);
|
||||
} // returnItem
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send data to the buffer.
|
||||
* @param [in] data The data to place into the buffer.
|
||||
* @param [in] length The length of data to place into the buffer.
|
||||
* @param [in] wait How long to wait before giving up. The default is to wait indefinitely.
|
||||
* @return
|
||||
*/
|
||||
bool Ringbuffer::send(void* data, size_t length, TickType_t wait) {
|
||||
return ::xRingbufferSend(m_handle, data, length, wait) == pdTRUE;
|
||||
} // send
|
||||
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* FreeRTOS.h
|
||||
*
|
||||
* Created on: Feb 24, 2017
|
||||
* Author: kolban
|
||||
*/
|
||||
|
||||
#ifndef MAIN_FREERTOS_H_
|
||||
#define MAIN_FREERTOS_H_
|
||||
|
||||
#include <freertos/FreeRTOS.h> // Include the base FreeRTOS definitions.
|
||||
#include <freertos/task.h> // Include the task definitions.
|
||||
#include <freertos/semphr.h> // Include the semaphore definitions.
|
||||
#include <freertos/ringbuf.h> // Include the ringbuffer definitions.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interface to %FreeRTOS functions.
|
||||
*/
|
||||
class FreeRTOS {
|
||||
public:
|
||||
static void sleep(uint32_t ms);
|
||||
static void startTask(void task(void*), std::string taskName, void* param = nullptr, uint32_t stackSize = 2048);
|
||||
static void deleteTask(TaskHandle_t pTask = nullptr);
|
||||
|
||||
static uint32_t getTimeSinceStart();
|
||||
|
||||
/**
|
||||
* @brief A binary semaphore class that operates like a mutex, it is already given when constructed.
|
||||
*/
|
||||
class Semaphore {
|
||||
public:
|
||||
Semaphore(std::string owner = "<Unknown>");
|
||||
~Semaphore();
|
||||
void give();
|
||||
void give(uint32_t value);
|
||||
void giveFromISR();
|
||||
void setName(std::string name);
|
||||
bool take(std::string owner = "<Unknown>");
|
||||
bool take(uint32_t timeoutMs, std::string owner = "<Unknown>");
|
||||
std::string toString();
|
||||
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
|
||||
uint32_t wait(std::string owner = "<Unknown>");
|
||||
/**
|
||||
* @brief Get the value of the semaphore.
|
||||
* @return The value stored if the semaphore was given with give(value);
|
||||
*/
|
||||
uint32_t value(){ return m_value; };
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t m_semaphore;
|
||||
pthread_mutex_t m_pthread_mutex;
|
||||
std::string m_name;
|
||||
std::string m_owner;
|
||||
uint32_t m_value;
|
||||
bool m_usePthreads;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for a freeRTOS ringbuffer.
|
||||
*/
|
||||
class Ringbuffer {
|
||||
public:
|
||||
#ifdef ESP_IDF_VERSION //Quick hack to detect if using IDF version that replaced ringbuf_type_t
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
|
||||
Ringbuffer(size_t length, RingbufferType_t type = RINGBUF_TYPE_NOSPLIT);
|
||||
#else
|
||||
Ringbuffer(size_t length, ringbuf_type_t type = RINGBUF_TYPE_NOSPLIT);
|
||||
#endif
|
||||
#else
|
||||
Ringbuffer(size_t length, ringbuf_type_t type = RINGBUF_TYPE_NOSPLIT);
|
||||
#endif
|
||||
~Ringbuffer();
|
||||
|
||||
void* receive(size_t* size, TickType_t wait = portMAX_DELAY);
|
||||
void returnItem(void* item);
|
||||
bool send(void* data, size_t length, TickType_t wait = portMAX_DELAY);
|
||||
private:
|
||||
RingbufHandle_t m_handle;
|
||||
};
|
||||
|
||||
#endif /* MAIN_FREERTOS_H_ */
|
|
@ -42,6 +42,7 @@ struct BLE2904_Data {
|
|||
*/
|
||||
class NimBLE2904: public NimBLEDescriptor {
|
||||
public:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic = nullptr);
|
||||
static const uint8_t FORMAT_BOOLEAN = 1;
|
||||
static const uint8_t FORMAT_UINT2 = 2;
|
||||
static const uint8_t FORMAT_UINT4 = 3;
|
||||
|
@ -77,7 +78,6 @@ public:
|
|||
void setUnit(uint16_t unit);
|
||||
|
||||
private:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
BLE2904_Data m_data;
|
||||
}; // BLE2904
|
||||
|
|
|
@ -734,7 +734,7 @@ uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
|||
* @param [in] length The length of the payload in bytes.
|
||||
* @param [in] append Indicates if the the data should be appended (scan response).
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setPayload(uint8_t *payload, uint8_t length, bool append) {
|
||||
void NimBLEAdvertisedDevice::setPayload(const uint8_t *payload, uint8_t length, bool append) {
|
||||
if(!append) {
|
||||
m_advLength = length;
|
||||
m_payload.assign(payload, payload + length);
|
||||
|
|
|
@ -137,7 +137,7 @@ private:
|
|||
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setPayload(uint8_t *payload, uint8_t length, bool append);
|
||||
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
||||
void setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
|
|
|
@ -383,6 +383,7 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
|
|||
* @brief Start advertising.
|
||||
* @param [in] duration The duration, in seconds, to advertise, 0 == advertise forever.
|
||||
* @param [in] advCompleteCB A pointer to a callback to be invoked when advertising ends.
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdvertising *pAdv)) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d",
|
||||
|
@ -471,16 +472,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16,
|
||||
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids16[m_advData.num_uuids16].value,
|
||||
&it.getNative()->u16.value, 2);
|
||||
|
||||
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
|
||||
memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16],
|
||||
&it.getNative()->u16, sizeof(ble_uuid16_t));
|
||||
m_advData.uuids16_is_complete = 1;
|
||||
m_advData.num_uuids16++;
|
||||
}
|
||||
|
@ -492,16 +491,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32,
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32,
|
||||
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids32[m_advData.num_uuids32].value,
|
||||
&it.getNative()->u32.value, 4);
|
||||
|
||||
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
|
||||
memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32],
|
||||
&it.getNative()->u32, sizeof(ble_uuid32_t));
|
||||
m_advData.uuids32_is_complete = 1;
|
||||
m_advData.num_uuids32++;
|
||||
}
|
||||
|
@ -513,16 +510,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128,
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128,
|
||||
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids128[m_advData.num_uuids128].value,
|
||||
&it.getNative()->u128.value, 16);
|
||||
|
||||
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
|
||||
memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128],
|
||||
&it.getNative()->u128, sizeof(ble_uuid128_t));
|
||||
m_advData.uuids128_is_complete = 1;
|
||||
m_advData.num_uuids128++;
|
||||
}
|
||||
|
@ -599,19 +594,19 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||
}
|
||||
|
||||
if(m_advData.num_uuids128 > 0) {
|
||||
free(m_advData.uuids128);
|
||||
free((void*)m_advData.uuids128);
|
||||
m_advData.uuids128 = nullptr;
|
||||
m_advData.num_uuids128 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids32 > 0) {
|
||||
free(m_advData.uuids32);
|
||||
free((void*)m_advData.uuids32);
|
||||
m_advData.uuids32 = nullptr;
|
||||
m_advData.num_uuids32 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids16 > 0) {
|
||||
free(m_advData.uuids16);
|
||||
free((void*)m_advData.uuids16);
|
||||
m_advData.uuids16 = nullptr;
|
||||
m_advData.num_uuids16 = 0;
|
||||
}
|
||||
|
|
|
@ -45,15 +45,15 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties
|
|||
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
||||
*/
|
||||
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_properties = properties;
|
||||
m_pCallbacks = &defaultCallback;
|
||||
m_pService = pService;
|
||||
m_value = "";
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
m_pTaskData = nullptr;
|
||||
m_timestamp = 0;
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_properties = properties;
|
||||
m_pCallbacks = &defaultCallback;
|
||||
m_pService = pService;
|
||||
m_value = "";
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
m_timestamp = 0;
|
||||
m_removed = 0;
|
||||
} // NimBLECharacteristic
|
||||
|
||||
/**
|
||||
|
@ -95,9 +95,62 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
|||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
addDescriptor(pDescriptor);
|
||||
return pDescriptor;
|
||||
} // createCharacteristic
|
||||
} // createDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a descriptor to the characteristic.
|
||||
* @param [in] pDescriptor A pointer to the descriptor to add.
|
||||
*/
|
||||
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
|
||||
bool foundRemoved = false;
|
||||
|
||||
if(pDescriptor->m_removed > 0) {
|
||||
for(auto& it : m_dscVec) {
|
||||
if(it == pDescriptor) {
|
||||
foundRemoved = true;
|
||||
pDescriptor->m_removed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundRemoved) {
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
}
|
||||
|
||||
pDescriptor->setCharacteristic(this);
|
||||
NimBLEDevice::getServer()->serviceChanged();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a descriptor from the characterisitc.
|
||||
* @param[in] pDescriptor A pointer to the descriptor instance to remove from the characterisitc.
|
||||
* @param[in] deleteDsc If true it will delete the descriptor instance and free it's resources.
|
||||
*/
|
||||
void NimBLECharacteristic::removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc) {
|
||||
// Check if the descriptor was already removed and if so, check if this
|
||||
// is being called to delete the object and do so if requested.
|
||||
// Otherwise, ignore the call and return.
|
||||
if(pDescriptor->m_removed > 0) {
|
||||
if(deleteDsc) {
|
||||
for(auto it = m_dscVec.begin(); it != m_dscVec.end(); ++it) {
|
||||
if ((*it) == pDescriptor) {
|
||||
delete *it;
|
||||
m_dscVec.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pDescriptor->m_removed = deleteDsc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
||||
NimBLEDevice::getServer()->serviceChanged();
|
||||
} // removeDescriptor
|
||||
|
||||
|
||||
/**
|
||||
|
@ -165,6 +218,11 @@ NimBLEService* NimBLECharacteristic::getService() {
|
|||
} // getService
|
||||
|
||||
|
||||
void NimBLECharacteristic::setService(NimBLEService *pService) {
|
||||
m_pService = pService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of the characteristic.
|
||||
* @return The UUID of the characteristic.
|
||||
|
@ -301,16 +359,13 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
|||
subVal |= NIMBLE_SUB_INDICATE;
|
||||
}
|
||||
|
||||
if(m_pTaskData != nullptr) {
|
||||
m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 :
|
||||
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
||||
xTaskNotifyGive(m_pTaskData->task);
|
||||
}
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||
event->subscribe.conn_handle, subVal);
|
||||
event->subscribe.conn_handle, subVal);
|
||||
|
||||
if(!event->subscribe.cur_indicate && event->subscribe.prev_indicate) {
|
||||
NimBLEDevice::getServer()->clearIndicateWait(event->subscribe.conn_handle);
|
||||
}
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
|
||||
auto it = m_subscribedVec.begin();
|
||||
for(;it != m_subscribedVec.end(); ++it) {
|
||||
|
@ -322,16 +377,14 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
|||
if(subVal > 0) {
|
||||
if(it == m_subscribedVec.end()) {
|
||||
m_subscribedVec.push_back({event->subscribe.conn_handle, subVal});
|
||||
return;
|
||||
} else {
|
||||
(*it).second = subVal;
|
||||
}
|
||||
|
||||
(*it).second = subVal;
|
||||
|
||||
} else if(it != m_subscribedVec.end()) {
|
||||
m_subscribedVec.erase(it);
|
||||
m_subscribedVec.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,40 +469,20 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
// We also must create it in each loop iteration because it is consumed with each host call.
|
||||
os_mbuf *om = ble_hs_mbuf_from_flat((uint8_t*)value.data(), length);
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
||||
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "prior Indication in progress");
|
||||
os_mbuf_free_chain(om);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ble_gattc_indicate_custom(it.first, m_handle, om);
|
||||
if(rc != 0){
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
} else {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
rc = m_pTaskData->rc;
|
||||
}
|
||||
|
||||
m_pTaskData = nullptr;
|
||||
|
||||
if(rc == BLE_HS_EDONE) {
|
||||
rc = 0;
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
NimBLEDevice::getServer()->clearIndicateWait(it.first);
|
||||
}
|
||||
} else {
|
||||
rc = ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
if(rc == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
}
|
||||
|
||||
m_pCallbacks->onStatus(this, statusRC, rc);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify");
|
||||
|
@ -469,6 +502,13 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
|||
}
|
||||
} // setCallbacks
|
||||
|
||||
/**
|
||||
* @brief Get the callback handlers for this characteristic.
|
||||
*/
|
||||
NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() {
|
||||
return m_pCallbacks;
|
||||
} //getCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the characteristic.
|
||||
|
|
|
@ -59,12 +59,26 @@ class NimBLECharacteristicCallbacks;
|
|||
*/
|
||||
class NimBLECharacteristic {
|
||||
public:
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
NimBLECharacteristicCallbacks*
|
||||
getCallbacks();
|
||||
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
|
@ -81,9 +95,11 @@ public:
|
|||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
|
||||
void addDescriptor(NimBLEDescriptor *pDescriptor);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||
void removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc = false);
|
||||
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
size_t getDataLength();
|
||||
|
@ -115,30 +131,15 @@ public:
|
|||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
|
||||
private:
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
void setService(NimBLEService *pService);
|
||||
void setSubscribe(struct ble_gap_event *event);
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
@ -150,9 +151,9 @@ private:
|
|||
NimBLEService* m_pService;
|
||||
std::string m_value;
|
||||
std::vector<NimBLEDescriptor*> m_dscVec;
|
||||
ble_task_data_t *m_pTaskData;
|
||||
portMUX_TYPE m_valMux;
|
||||
time_t m_timestamp;
|
||||
uint8_t m_removed;
|
||||
|
||||
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
|
||||
}; // NimBLECharacteristic
|
||||
|
|
|
@ -436,6 +436,24 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
|||
} // updateConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get detailed information about the current peer connection.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEClient::getConnInfo() {
|
||||
NimBLEConnInfo connInfo;
|
||||
if (!isConnected()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Not connected");
|
||||
} else {
|
||||
int rc = ble_gap_conn_find(m_conn_id, &connInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||
}
|
||||
}
|
||||
|
||||
return connInfo;
|
||||
} // getConnInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the timeout to wait for connection attempt to complete.
|
||||
* @param [in] time The number of seconds before timeout.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLERemoteService.h"
|
||||
|
||||
|
@ -71,6 +72,7 @@ public:
|
|||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void discoverAttributes();
|
||||
NimBLEConnInfo getConnInfo();
|
||||
|
||||
private:
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef NIMBLECONNINFO_H_
|
||||
#define NIMBLECONNINFO_H_
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
|
||||
/**
|
||||
* @brief Connection information.
|
||||
*/
|
||||
class NimBLEConnInfo {
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEClient;
|
||||
ble_gap_conn_desc m_desc;
|
||||
NimBLEConnInfo() { m_desc = {}; }
|
||||
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
|
||||
public:
|
||||
/** @brief Gets the over-the-air address of the connected peer */
|
||||
NimBLEAddress getAddress() { return NimBLEAddress(m_desc.peer_ota_addr); }
|
||||
|
||||
/** @brief Gets the ID address of the connected peer */
|
||||
NimBLEAddress getIdAddress() { return NimBLEAddress(m_desc.peer_id_addr); }
|
||||
|
||||
/** @brief Gets the connection handle of the connected peer */
|
||||
uint16_t getConnHandle() { return m_desc.conn_handle; }
|
||||
|
||||
/** @brief Gets the connection interval for this connection (in 1.25ms units) */
|
||||
uint16_t getConnInterval() { return m_desc.conn_itvl; }
|
||||
|
||||
/** @brief Gets the supervision timeout for this connection (in 10ms units) */
|
||||
uint16_t getConnTimeout() { return m_desc.supervision_timeout; }
|
||||
|
||||
/** @brief Gets the allowable latency for this connection (unit = number of intervals) */
|
||||
uint16_t getConnLatency() { return m_desc.conn_latency; }
|
||||
|
||||
/** @brief Gets the maximum transmission unit size for this connection (in bytes) */
|
||||
uint16_t getMTU() { return ble_att_mtu(m_desc.conn_handle); }
|
||||
|
||||
/** @brief Check if we are in the master role in this connection */
|
||||
bool isMaster() { return (m_desc.role == BLE_GAP_ROLE_MASTER); }
|
||||
|
||||
/** @brief Check if we are in the slave role in this connection */
|
||||
bool isSlave() { return (m_desc.role == BLE_GAP_ROLE_SLAVE); }
|
||||
|
||||
/** @brief Check if we are connected to a bonded peer */
|
||||
bool isBonded() { return (m_desc.sec_state.bonded == 1); }
|
||||
|
||||
/** @brief Check if the connection in encrypted */
|
||||
bool isEncrypted() { return (m_desc.sec_state.encrypted == 1); }
|
||||
|
||||
/** @brief Check if the the connection has been authenticated */
|
||||
bool isAuthenticated() { return (m_desc.sec_state.authenticated == 1); }
|
||||
|
||||
/** @brief Gets the key size used to encrypt the connection */
|
||||
uint8_t getSecKeySize() { return m_desc.sec_state.key_size; }
|
||||
};
|
||||
#endif
|
|
@ -37,6 +37,7 @@ NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16
|
|||
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief NimBLEDescriptor constructor.
|
||||
*/
|
||||
|
@ -47,11 +48,12 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
|
|||
m_value.attr_len = 0; // Initial length is 0.
|
||||
m_value.attr_max_len = max_len; // Maximum length of the data.
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = nullptr; // No initial characteristic.
|
||||
m_pCharacteristic = pCharacteristic;
|
||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
m_properties = 0;
|
||||
m_removed = 0;
|
||||
|
||||
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
|
||||
m_properties |= BLE_ATT_F_READ;
|
||||
|
@ -122,6 +124,7 @@ uint8_t* NimBLEDescriptor::getValue() {
|
|||
return m_value.attr_value;
|
||||
} // getValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor as a string.
|
||||
* @return A std::string instance containing a copy of the descriptor's value.
|
||||
|
@ -130,9 +133,18 @@ std::string NimBLEDescriptor::getStringValue() {
|
|||
return std::string((char *) m_value.attr_value, m_value.attr_len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the characteristic this descriptor belongs to.
|
||||
* @return A pointer to the characteristic this descriptor belongs to.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() {
|
||||
return m_pCharacteristic;
|
||||
} // getCharacteristic
|
||||
|
||||
|
||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg) {
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
|
@ -169,7 +181,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||
if((len + next->om_len) > pDescriptor->m_value.attr_max_len) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
memcpy(&buf[len-1], next->om_data, next->om_len);
|
||||
memcpy(&buf[len], next->om_data, next->om_len);
|
||||
len += next->om_len;
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
|
@ -237,6 +249,14 @@ void NimBLEDescriptor::setValue(const std::string &value) {
|
|||
setValue((uint8_t*) value.data(), value.length());
|
||||
} // setValue
|
||||
|
||||
/**
|
||||
* @brief Set the characteristic this descriptor belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptior belongs to.
|
||||
*/
|
||||
void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
|
||||
m_pCharacteristic = pChar;
|
||||
} // setCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the descriptor.
|
||||
|
|
|
@ -43,46 +43,48 @@ class NimBLEDescriptorCallbacks;
|
|||
*/
|
||||
class NimBLEDescriptor {
|
||||
public:
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
~NimBLEDescriptor();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
NimBLECharacteristic* getCharacteristic();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
/**
|
||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLE2902;
|
||||
friend class NimBLE2904;
|
||||
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
~NimBLEDescriptor();
|
||||
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
void setHandle(uint16_t handle);
|
||||
void setCharacteristic(NimBLECharacteristic* pChar);
|
||||
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_handle;
|
||||
|
@ -91,6 +93,7 @@ private:
|
|||
uint8_t m_properties;
|
||||
attr_value_t m_value;
|
||||
portMUX_TYPE m_valMux;
|
||||
uint8_t m_removed;
|
||||
}; // NimBLEDescriptor
|
||||
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
||||
#include "esp32-hal-bt.h"
|
||||
#endif
|
||||
|
||||
|
@ -60,6 +60,7 @@ ble_gap_event_listener NimBLEDevice::m_listener;
|
|||
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||
#endif
|
||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||
std::vector<NimBLEAddress> NimBLEDevice::m_whiteList;
|
||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
||||
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
|
||||
|
@ -448,6 +449,211 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
|||
m_scanFilterMode = mode;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/**
|
||||
* @brief Gets the number of bonded peers stored
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEDevice::getNumBonds() {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc !=0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return num_peers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes all bonding information.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::deleteAllBonds() {
|
||||
ble_store_clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes a peer bond.
|
||||
* @param [in] address The address of the peer with which to delete bond info.
|
||||
* @returns true on success.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::deleteBond(const NimBLEAddress &address) {
|
||||
ble_addr_t delAddr;
|
||||
memcpy(&delAddr.val, address.getNative(),6);
|
||||
delAddr.type = address.getType();
|
||||
|
||||
int rc = ble_gap_unpair(&delAddr);
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is bonded.
|
||||
* @param [in] address The address to check for bonding.
|
||||
* @returns true if bonded.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::isBonded(const NimBLEAddress &address) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_peers; i++) {
|
||||
NimBLEAddress storedAddr(peer_id_addrs[i]);
|
||||
if(storedAddr == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the address of a bonded peer device by index.
|
||||
* @param [in] index The index to retrieve the peer address of.
|
||||
* @returns NimBLEAddress of the found bonded peer or nullptr if not found.
|
||||
*/
|
||||
/*STATIC*/
|
||||
NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (index > num_peers || index < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return NimBLEAddress(peer_id_addrs[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is whitelisted.
|
||||
* @param [in] address The address to check for in the whitelist.
|
||||
* @returns true if the address is in the whitelist.
|
||||
*/
|
||||
bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) {
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a peer address to the whitelist.
|
||||
* @param [in] address The address to add to the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
|
||||
if (NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_whiteList.push_back(address);
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a peer address from the whitelist.
|
||||
* @param [in] address The address to remove from the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) {
|
||||
if (!NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it != address) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't remove from the list unless NimBLE returned success
|
||||
for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) {
|
||||
if ((*it) == address) {
|
||||
m_whiteList.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the count of addresses in the whitelist.
|
||||
* @returns The number of addresses in the whitelist.
|
||||
*/
|
||||
size_t NimBLEDevice::getWhiteListCount() {
|
||||
return m_whiteList.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the address at the vector index.
|
||||
* @param [in] index The vector index to retrieve the address from.
|
||||
* @returns the NimBLEAddress at the whitelist index or nullptr if not found.
|
||||
*/
|
||||
NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
|
||||
if (index > m_whiteList.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index);
|
||||
return nullptr;
|
||||
}
|
||||
return m_whiteList[index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||
|
@ -534,7 +740,7 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
|||
int rc=0;
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
||||
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
|
||||
btStarted();
|
||||
#endif
|
||||
|
@ -551,8 +757,12 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
|||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
|
||||
#else
|
||||
bt_cfg.mode = ESP_BT_MODE_BLE;
|
||||
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
|
||||
#endif
|
||||
bt_cfg.normal_adv_size = m_scanDuplicateSize;
|
||||
bt_cfg.scan_duplicate_type = m_scanFilterMode;
|
||||
|
||||
|
@ -771,17 +981,23 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
|
||||
m_own_addr_type = own_addr_type;
|
||||
switch (own_addr_type) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
case BLE_OWN_ADDR_PUBLIC:
|
||||
ble_hs_pvcy_rpa_config(NIMBLE_HOST_DISABLE_PRIVACY);
|
||||
break;
|
||||
#endif
|
||||
case BLE_OWN_ADDR_RANDOM:
|
||||
setSecurityInitKey(BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ble_hs_pvcy_rpa_config(useNRPA ? NIMBLE_HOST_ENABLE_NRPA : NIMBLE_HOST_ENABLE_RPA);
|
||||
#endif
|
||||
break;
|
||||
case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
|
||||
case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
|
||||
setSecurityInitKey(BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ble_hs_pvcy_rpa_config(NIMBLE_HOST_ENABLE_RPA);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} // setOwnAddrType
|
||||
|
|
|
@ -95,6 +95,11 @@ public:
|
|||
static bool getInitialized();
|
||||
static NimBLEAddress getAddress();
|
||||
static std::string toString();
|
||||
static bool whiteListAdd(const NimBLEAddress & address);
|
||||
static bool whiteListRemove(const NimBLEAddress & address);
|
||||
static bool onWhiteList(const NimBLEAddress & address);
|
||||
static size_t getWhiteListCount();
|
||||
static NimBLEAddress getWhiteListAddress(size_t index);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* getScan();
|
||||
|
@ -142,6 +147,14 @@ public:
|
|||
static std::list<NimBLEClient*>* getClientList();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
static bool deleteBond(const NimBLEAddress &address);
|
||||
static int getNumBonds();
|
||||
static bool isBonded(const NimBLEAddress &address);
|
||||
static void deleteAllBonds();
|
||||
static NimBLEAddress getBondedAddress(int index);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
friend class NimBLEClient;
|
||||
|
@ -188,6 +201,7 @@ private:
|
|||
static uint8_t m_own_addr_type;
|
||||
static uint16_t m_scanDuplicateSize;
|
||||
static uint8_t m_scanFilterMode;
|
||||
static std::vector<NimBLEAddress> m_whiteList;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7,17 +7,19 @@
|
|||
*/
|
||||
#ifndef MAIN_NIMBLELOG_H_
|
||||
#define MAIN_NIMBLELOG_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "modlog/modlog.h"
|
||||
|
||||
|
||||
// If Arduino is being used, strip out the colors and ignore log printing below ui setting.
|
||||
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR
|
||||
// otherwise no messages will be printed above that level.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#ifndef CORE_DEBUG_LEVEL
|
||||
#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||
#endif
|
||||
|
@ -49,11 +51,15 @@
|
|||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "\033[0;31mE %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(WARN, "\033[0;33mW %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(INFO, "\033[0;32mI %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(DEBUG, "D %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "\033[1;31mCRIT %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#define NIMBLE_LOGE(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
|
||||
#endif /*ARDUINO_ARCH_ESP32*/
|
||||
|
||||
#endif /*CONFIG_BT_ENABLED*/
|
||||
|
|
|
@ -55,6 +55,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
|||
|
||||
m_handle = chr->val_handle;
|
||||
m_defHandle = chr->def_handle;
|
||||
m_endHandle = 0;
|
||||
m_charProp = chr->properties;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
|
@ -146,31 +147,25 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
const struct ble_gatt_dsc *dsc,
|
||||
void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovered >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? dsc->handle : -1);
|
||||
|
||||
desc_filter_t *filter = (desc_filter_t*)arg;
|
||||
const NimBLEUUID *uuid_filter = filter->uuid;
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)filter->task_data;
|
||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
int rc=0;
|
||||
|
||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
if (characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (error->status) {
|
||||
switch (rc) {
|
||||
case 0: {
|
||||
if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion");
|
||||
rc = BLE_HS_EDONE;
|
||||
break;
|
||||
}
|
||||
if(uuid_filter != nullptr) {
|
||||
if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
if (uuid_filter != nullptr) {
|
||||
if (ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Found");
|
||||
rc = BLE_HS_EDONE;
|
||||
}
|
||||
}
|
||||
|
@ -180,11 +175,10 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
/** If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
/* If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
||||
* If we get any other error code tell the application to abort by returning non-zero in the rc.
|
||||
*/
|
||||
|
@ -202,6 +196,38 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief callback from NimBLE when the next characteristic of the service is discovered.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::nextCharCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg)
|
||||
{
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Next Characteristic >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? chr->val_handle : -1);
|
||||
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||
NimBLERemoteCharacteristic *pChar = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
|
||||
if (pChar->getRemoteService()->getClient()->getConnId() != conn_handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
pChar->m_endHandle = chr->def_handle - 1;
|
||||
rc = BLE_HS_EDONE;
|
||||
} else if (rc == BLE_HS_EDONE) {
|
||||
pChar->m_endHandle = pChar->getRemoteService()->getEndHandle();
|
||||
} else {
|
||||
pTaskData->rc = rc;
|
||||
}
|
||||
|
||||
xTaskNotifyGive(pTaskData->task);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Populate the descriptors (if any) for this characteristic.
|
||||
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
||||
|
@ -209,35 +235,57 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||
|
||||
uint16_t endHandle = getRemoteService()->getEndHandle(this);
|
||||
if(m_handle >= endHandle) {
|
||||
return false;
|
||||
// If this is the last handle then there are no descriptors
|
||||
if (m_handle == getRemoteService()->getEndHandle()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
|
||||
// If we don't know the end handle of this characteristic retrieve the next one in the service
|
||||
// The end handle is the next characteristic definition handle -1.
|
||||
if (m_endHandle == 0) {
|
||||
rc = ble_gattc_disc_all_chrs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
getRemoteService()->getEndHandle(),
|
||||
NimBLERemoteCharacteristic::nextCharCB,
|
||||
&taskData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error getting end handle rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Could not retrieve end handle rc=%d", taskData.rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc_filter_t filter = {uuid_filter, &taskData};
|
||||
|
||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
endHandle,
|
||||
m_endHandle,
|
||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||
&filter);
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: startHandle:%d endHandle:%d taskData.rc=%d %s", m_handle, endHandle, taskData.rc, NimBLEUtils::returnCodeToString(0x0100+taskData.rc));
|
||||
return false;
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to retrieve descriptors; startHandle:%d endHandle:%d taskData.rc=%d",
|
||||
m_handle, m_endHandle, taskData.rc);
|
||||
}
|
||||
|
||||
return true;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size());
|
||||
return (taskData.rc == 0);
|
||||
} // retrieveDescriptors
|
||||
|
||||
|
||||
|
@ -664,7 +712,7 @@ std::string NimBLERemoteCharacteristic::toString() {
|
|||
* @return false if not connected or cant perform write for some reason.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
||||
return writeValue((uint8_t*)newValue.c_str(), newValue.length(), response);
|
||||
} // writeValue
|
||||
|
||||
|
||||
|
|
|
@ -148,12 +148,15 @@ private:
|
|||
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
static int nextCharCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg);
|
||||
|
||||
// Private properties
|
||||
NimBLEUUID m_uuid;
|
||||
uint8_t m_charProp;
|
||||
uint16_t m_handle;
|
||||
uint16_t m_defHandle;
|
||||
uint16_t m_endHandle;
|
||||
NimBLERemoteService* m_pRemoteService;
|
||||
std::string m_value;
|
||||
notify_callback m_notifyCallback;
|
||||
|
|
|
@ -223,6 +223,20 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
|||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc == 0){
|
||||
if (uuid_filter == nullptr) {
|
||||
if (m_characteristicVector.size() > 1) {
|
||||
for (auto it = m_characteristicVector.begin(); it != m_characteristicVector.end(); ++it ) {
|
||||
auto nx = std::next(it, 1);
|
||||
if (nx == m_characteristicVector.end()) {
|
||||
break;
|
||||
}
|
||||
(*it)->m_endHandle = (*nx)->m_defHandle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||
return true;
|
||||
}
|
||||
|
@ -249,23 +263,6 @@ uint16_t NimBLERemoteService::getEndHandle() {
|
|||
return m_endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
/**
|
||||
* @brief Get the end handle of specified NimBLERemoteCharacteristic.
|
||||
*/
|
||||
|
||||
uint16_t NimBLERemoteService::getEndHandle(NimBLERemoteCharacteristic *pCharacteristic) {
|
||||
uint16_t endHandle = m_endHandle;
|
||||
|
||||
for(auto &it: m_characteristicVector) {
|
||||
uint16_t defHandle = it->getDefHandle() - 1;
|
||||
if(defHandle > pCharacteristic->getDefHandle() && endHandle > defHandle) {
|
||||
endHandle = defHandle;
|
||||
}
|
||||
}
|
||||
|
||||
return endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service start handle.
|
||||
|
|
|
@ -70,7 +70,6 @@ private:
|
|||
|
||||
uint16_t getStartHandle();
|
||||
uint16_t getEndHandle();
|
||||
uint16_t getEndHandle(NimBLERemoteCharacteristic *pCharacteristic);
|
||||
void releaseSemaphores();
|
||||
|
||||
// Properties
|
||||
|
|
|
@ -110,7 +110,7 @@ NimBLEScan::~NimBLEScan() {
|
|||
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
|
@ -128,7 +128,7 @@ NimBLEScan::~NimBLEScan() {
|
|||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent) {
|
||||
pScan->erase(advertisedAddress);
|
||||
}
|
||||
|
@ -316,6 +316,8 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
|||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
// Clear the cache if already scanning in case an advertiser was missed.
|
||||
clearDuplicateCache();
|
||||
break;
|
||||
|
||||
case BLE_HS_EBUSY:
|
||||
|
@ -398,6 +400,16 @@ bool NimBLEScan::stop() {
|
|||
} // stop
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clears the duplicate scan filter cache.
|
||||
*/
|
||||
void NimBLEScan::clearDuplicateCache() {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32 // Not available for ESP32C3
|
||||
esp_ble_scan_dupilcate_list_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Delete peer device from the scan results vector.
|
||||
* @param [in] address The address of the device to delete from the results.
|
||||
|
@ -453,6 +465,7 @@ void NimBLEScan::clearResults() {
|
|||
delete it;
|
||||
}
|
||||
m_scanResults.m_advertisedDevicesVector.clear();
|
||||
clearDuplicateCache();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ public:
|
|||
void setDuplicateFilter(bool enabled);
|
||||
void setLimitedOnly(bool enabled);
|
||||
void setFilterPolicy(uint8_t filter);
|
||||
void clearDuplicateCache();
|
||||
bool stop();
|
||||
void clearResults();
|
||||
NimBLEScanResults getResults();
|
||||
|
|
|
@ -37,6 +37,7 @@ static NimBLEServerCallbacks defaultCallbacks;
|
|||
* the NimBLEDevice class.
|
||||
*/
|
||||
NimBLEServer::NimBLEServer() {
|
||||
memset(m_indWait, BLE_HS_CONN_HANDLE_NONE, sizeof(m_indWait));
|
||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
|
@ -90,12 +91,7 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
|
|||
|
||||
NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
|
||||
m_svcVec.push_back(pService); // Save a reference to this service being on this server.
|
||||
|
||||
if(m_gattsStarted) {
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
m_svcChanged = true;
|
||||
resetGATT();
|
||||
}
|
||||
serviceChanged();
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< createService");
|
||||
return pService;
|
||||
|
@ -156,6 +152,18 @@ NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
|||
} // getAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends a service changed notification and resets the GATT server.
|
||||
*/
|
||||
void NimBLEServer::serviceChanged() {
|
||||
if(m_gattsStarted) {
|
||||
m_svcChanged = true;
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start the GATT server. Required to be called after setup of all
|
||||
* services and characteristics / descriptors for the NimBLE host to register them.
|
||||
|
@ -253,6 +261,63 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
} // getConnectedCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the vector of the connected client ID's.
|
||||
*/
|
||||
std::vector<uint16_t> NimBLEServer::getPeerDevices() {
|
||||
return m_connectedPeersVec;
|
||||
} // getPeerDevices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by vector index.
|
||||
* @param [in] index The vector index of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(size_t index) {
|
||||
if (index >= m_connectedPeersVec.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "No peer at index %u", index);
|
||||
return NimBLEConnInfo();
|
||||
}
|
||||
|
||||
return getPeerIDInfo(m_connectedPeersVec[index]);
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by address.
|
||||
* @param [in] address The address of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) {
|
||||
ble_addr_t peerAddr;
|
||||
memcpy(&peerAddr.val, address.getNative(),6);
|
||||
peerAddr.type = address.getType();
|
||||
|
||||
NimBLEConnInfo peerInfo;
|
||||
int rc = ble_gap_conn_find_by_addr(&peerAddr, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by connection ID.
|
||||
* @param [in] id The connection id of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
NimBLEConnInfo peerInfo;
|
||||
|
||||
int rc = ble_gap_conn_find(id, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerIDInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle a GATT Server Event.
|
||||
*
|
||||
|
@ -280,7 +345,9 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->m_pServerCallbacks->onConnect(server);
|
||||
server->m_pServerCallbacks->onConnect(server, &desc);
|
||||
|
@ -335,7 +402,9 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
(it->getProperties() & BLE_GATT_CHR_F_READ_ENC))
|
||||
{
|
||||
rc = ble_gap_conn_find(event->subscribe.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!desc.sec_state.encrypted) {
|
||||
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
||||
|
@ -354,22 +423,54 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
|
||||
event->mtu.conn_handle,
|
||||
event->mtu.value);
|
||||
rc = ble_gap_conn_find(event->mtu.conn_handle, &desc);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->m_pServerCallbacks->onMTUChange(event->mtu.value, &desc);
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_MTU
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||
if(event->notify_tx.indication && event->notify_tx.status != 0) {
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
if(it->m_pTaskData != nullptr) {
|
||||
it->m_pTaskData->rc = event->notify_tx.status;
|
||||
xTaskNotifyGive(it->m_pTaskData->task);
|
||||
}
|
||||
break;
|
||||
}
|
||||
NimBLECharacteristic *pChar = nullptr;
|
||||
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
pChar = it;
|
||||
}
|
||||
}
|
||||
|
||||
if(pChar == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(event->notify_tx.indication) {
|
||||
if(event->notify_tx.status != 0) {
|
||||
if(event->notify_tx.status == BLE_HS_EDONE) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->clearIndicateWait(event->notify_tx.conn_handle);
|
||||
} else {
|
||||
if(event->notify_tx.status == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
}
|
||||
|
||||
pChar->m_pCallbacks->onStatus(pChar, statusRC, event->notify_tx.status);
|
||||
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
|
@ -392,7 +493,10 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
|
||||
/* Delete the old bond. */
|
||||
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0){
|
||||
return BLE_GAP_REPEAT_PAIRING_IGNORE;
|
||||
}
|
||||
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
|
||||
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
|
||||
|
@ -533,7 +637,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
|||
if(service->m_removed > 0) {
|
||||
if(deleteSvc) {
|
||||
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ++it) {
|
||||
if ((*it)->getUUID() == service->getUUID()) {
|
||||
if ((*it) == service) {
|
||||
delete *it;
|
||||
m_svcVec.erase(it);
|
||||
break;
|
||||
|
@ -549,32 +653,35 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
|||
return;
|
||||
}
|
||||
|
||||
service->m_removed = deleteSvc ? 2 : 1;
|
||||
m_svcChanged = true;
|
||||
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
||||
serviceChanged();
|
||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a service which was already created, but removed from availability.
|
||||
* @brief Adds a service which was either already created but removed from availability,\n
|
||||
* or created and later added to services list.
|
||||
* @param [in] service The service object to add.
|
||||
* @note If it is desired to advertise the service it must be added by
|
||||
* calling NimBLEAdvertising::addServiceUUID.
|
||||
*/
|
||||
void NimBLEServer::addService(NimBLEService* service) {
|
||||
// If adding a service that was not removed just return.
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if(getServiceByUUID(service->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
|
||||
std::string(service->getUUID()).c_str());
|
||||
}
|
||||
|
||||
// If adding a service that was not removed add it and return.
|
||||
// Else reset GATT and send service changed notification.
|
||||
if(service->m_removed == 0) {
|
||||
m_svcVec.push_back(service);
|
||||
return;
|
||||
}
|
||||
|
||||
service->m_removed = 0;
|
||||
m_svcChanged = true;
|
||||
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
serviceChanged();
|
||||
}
|
||||
|
||||
|
||||
|
@ -593,7 +700,7 @@ void NimBLEServer::resetGATT() {
|
|||
|
||||
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ) {
|
||||
if ((*it)->m_removed > 0) {
|
||||
if ((*it)->m_removed == 2) {
|
||||
if ((*it)->m_removed == NIMBLE_ATT_REMOVE_DELETE) {
|
||||
delete *it;
|
||||
it = m_svcVec.erase(it);
|
||||
} else {
|
||||
|
@ -668,6 +775,27 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
|||
}// updateConnParams
|
||||
|
||||
|
||||
bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEServer::clearIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
m_indWait[i] = BLE_HS_CONN_HANDLE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
|
||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) {
|
||||
|
@ -688,6 +816,10 @@ void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer, ble_gap_conn_des
|
|||
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
||||
} // onDisconnect
|
||||
|
||||
void NimBLEServerCallbacks::onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onMTUChange(): Default");
|
||||
} // onMTUChange
|
||||
|
||||
uint32_t NimBLEServerCallbacks::onPassKeyRequest(){
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyRequest: default: 123456");
|
||||
return 123456;
|
||||
|
|
|
@ -20,11 +20,15 @@
|
|||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#define NIMBLE_ATT_REMOVE_HIDE 1
|
||||
#define NIMBLE_ATT_REMOVE_DELETE 2
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEAdvertising.h"
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
|
||||
|
||||
class NimBLEService;
|
||||
|
@ -58,13 +62,17 @@ public:
|
|||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
uint16_t getPeerMTU(uint16_t conn_id);
|
||||
// std::vector<uint16_t> getPeerDevices();
|
||||
std::vector<uint16_t> getPeerDevices();
|
||||
NimBLEConnInfo getPeerInfo(size_t index);
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
void advertiseOnDisconnect(bool);
|
||||
|
||||
private:
|
||||
NimBLEServer();
|
||||
~NimBLEServer();
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEAdvertising;
|
||||
|
||||
|
@ -73,6 +81,7 @@ private:
|
|||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
uint16_t m_indWait[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||
std::vector<uint16_t> m_connectedPeersVec;
|
||||
|
||||
// uint16_t m_svcChgChrHdl; // Future use
|
||||
|
@ -81,7 +90,10 @@ private:
|
|||
std::vector<NimBLECharacteristic*> m_notifyChrVec;
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
void serviceChanged();
|
||||
void resetGATT();
|
||||
bool setIndicateWait(uint16_t conn_handle);
|
||||
void clearIndicateWait(uint16_t conn_handle);
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
|
@ -124,6 +136,14 @@ public:
|
|||
*/
|
||||
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Called when the connection MTU changes.
|
||||
* @param [in] MTU The new MTU value.
|
||||
* @param [in] desc A pointer to the connection description structure containig information
|
||||
* about the connection.
|
||||
*/
|
||||
virtual void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Called when a client requests a passkey for pairing.
|
||||
* @return The passkey to be sent to the client.
|
||||
|
|
|
@ -35,7 +35,7 @@ static const char* LOG_TAG = "NimBLEService"; // Tag for logging.
|
|||
* @brief Construct an instance of the NimBLEService
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param [in] numHandles The maximum number of handles associated with the service.
|
||||
* @param [in] a pointer to the server instance that this service belongs to.
|
||||
* @param [in] pServer A pointer to the server instance that this service belongs to.
|
||||
*/
|
||||
NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer)
|
||||
: NimBLEService(NimBLEUUID(uuid), numHandles, pServer) {
|
||||
|
@ -46,7 +46,7 @@ NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer
|
|||
* @brief Construct an instance of the BLEService
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param [in] numHandles The maximum number of handles associated with the service.
|
||||
* @param [in] a pointer to the server instance that this service belongs to.
|
||||
* @param [in] pServer A pointer to the server instance that this service belongs to.
|
||||
*/
|
||||
NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) {
|
||||
m_uuid = uuid;
|
||||
|
@ -118,7 +118,12 @@ NimBLEUUID NimBLEService::getUUID() {
|
|||
*/
|
||||
bool NimBLEService::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
int rc = 0;
|
||||
|
||||
// Rebuild the service definition if the server attributes have changed.
|
||||
if(getServer()->m_svcChanged && m_pSvcDef != nullptr) {
|
||||
delete(m_pSvcDef);
|
||||
m_pSvcDef = nullptr;
|
||||
}
|
||||
|
||||
if(m_pSvcDef == nullptr) {
|
||||
// Nimble requires an array of services to be sent to the api
|
||||
|
@ -132,8 +137,23 @@ bool NimBLEService::start() {
|
|||
svc[0].uuid = &m_uuid.getNative()->u;
|
||||
svc[0].includes = NULL;
|
||||
|
||||
size_t numChrs = m_chrVec.size();
|
||||
int removedCount = 0;
|
||||
for(auto it = m_chrVec.begin(); it != m_chrVec.end(); ) {
|
||||
if ((*it)->m_removed > 0) {
|
||||
if ((*it)->m_removed == NIMBLE_ATT_REMOVE_DELETE) {
|
||||
delete *it;
|
||||
it = m_chrVec.erase(it);
|
||||
} else {
|
||||
++removedCount;
|
||||
++it;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
size_t numChrs = m_chrVec.size() - removedCount;
|
||||
NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str());
|
||||
|
||||
if(!numChrs){
|
||||
|
@ -142,40 +162,60 @@ bool NimBLEService::start() {
|
|||
// Nimble requires the last characteristic to have it's uuid = 0 to indicate the end
|
||||
// of the characteristics for the service. We create 1 extra and set it to null
|
||||
// for this purpose.
|
||||
pChr_a = new ble_gatt_chr_def[numChrs+1];
|
||||
NimBLECharacteristic* pCharacteristic = *m_chrVec.begin();
|
||||
pChr_a = new ble_gatt_chr_def[numChrs + 1];
|
||||
uint8_t i = 0;
|
||||
for(auto chr_it = m_chrVec.begin(); chr_it != m_chrVec.end(); ++chr_it) {
|
||||
if((*chr_it)->m_removed > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(uint8_t i=0; i < numChrs;) {
|
||||
uint8_t numDscs = pCharacteristic->m_dscVec.size();
|
||||
removedCount = 0;
|
||||
for(auto it = (*chr_it)->m_dscVec.begin(); it != (*chr_it)->m_dscVec.end(); ) {
|
||||
if ((*it)->m_removed > 0) {
|
||||
if ((*it)->m_removed == NIMBLE_ATT_REMOVE_DELETE) {
|
||||
delete *it;
|
||||
it = (*chr_it)->m_dscVec.erase(it);
|
||||
} else {
|
||||
++removedCount;
|
||||
++it;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
size_t numDscs = (*chr_it)->m_dscVec.size() - removedCount;
|
||||
|
||||
if(!numDscs){
|
||||
pChr_a[i].descriptors = NULL;
|
||||
} else {
|
||||
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
||||
pDsc_a = new ble_gatt_dsc_def[numDscs+1];
|
||||
NimBLEDescriptor* pDescriptor = *pCharacteristic->m_dscVec.begin();
|
||||
for(uint8_t d=0; d < numDscs;) {
|
||||
pDsc_a[d].uuid = &pDescriptor->m_uuid.getNative()->u;
|
||||
pDsc_a[d].att_flags = pDescriptor->m_properties;
|
||||
uint8_t d = 0;
|
||||
for(auto dsc_it = (*chr_it)->m_dscVec.begin(); dsc_it != (*chr_it)->m_dscVec.end(); ++dsc_it ) {
|
||||
if((*dsc_it)->m_removed > 0) {
|
||||
continue;
|
||||
}
|
||||
pDsc_a[d].uuid = &(*dsc_it)->m_uuid.getNative()->u;
|
||||
pDsc_a[d].att_flags = (*dsc_it)->m_properties;
|
||||
pDsc_a[d].min_key_size = 0;
|
||||
pDsc_a[d].access_cb = NimBLEDescriptor::handleGapEvent;
|
||||
pDsc_a[d].arg = pDescriptor;
|
||||
d++;
|
||||
pDescriptor = *(pCharacteristic->m_dscVec.begin() + d);
|
||||
pDsc_a[d].arg = (*dsc_it);
|
||||
++d;
|
||||
}
|
||||
|
||||
pDsc_a[numDscs].uuid = NULL;
|
||||
pChr_a[i].descriptors = pDsc_a;
|
||||
}
|
||||
|
||||
pChr_a[i].uuid = &pCharacteristic->m_uuid.getNative()->u;
|
||||
pChr_a[i].uuid = &(*chr_it)->m_uuid.getNative()->u;
|
||||
pChr_a[i].access_cb = NimBLECharacteristic::handleGapEvent;
|
||||
pChr_a[i].arg = pCharacteristic;
|
||||
pChr_a[i].flags = pCharacteristic->m_properties;
|
||||
pChr_a[i].arg = (*chr_it);
|
||||
pChr_a[i].flags = (*chr_it)->m_properties;
|
||||
pChr_a[i].min_key_size = 0;
|
||||
pChr_a[i].val_handle = &pCharacteristic->m_handle;
|
||||
i++;
|
||||
pCharacteristic = *(m_chrVec.begin() + i);
|
||||
pChr_a[i].val_handle = &(*chr_it)->m_handle;
|
||||
++i;
|
||||
}
|
||||
|
||||
pChr_a[numChrs].uuid = NULL;
|
||||
|
@ -187,7 +227,7 @@ bool NimBLEService::start() {
|
|||
m_pSvcDef = svc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)m_pSvcDef);
|
||||
int rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)m_pSvcDef);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gatts_count_cfg failed, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
|
@ -239,13 +279,64 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
|||
std::string(uuid).c_str());
|
||||
}
|
||||
|
||||
// Remember this characteristic in our vector of characteristics.
|
||||
m_chrVec.push_back(pCharacteristic);
|
||||
|
||||
addCharacteristic(pCharacteristic);
|
||||
return pCharacteristic;
|
||||
} // createCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a characteristic to the service.
|
||||
* @param[in] pCharacteristic A pointer to the characteristic instance to add to the service.
|
||||
*/
|
||||
void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
|
||||
bool foundRemoved = false;
|
||||
|
||||
if(pCharacteristic->m_removed > 0) {
|
||||
for(auto& it : m_chrVec) {
|
||||
if(it == pCharacteristic) {
|
||||
foundRemoved = true;
|
||||
pCharacteristic->m_removed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundRemoved) {
|
||||
m_chrVec.push_back(pCharacteristic);
|
||||
}
|
||||
|
||||
pCharacteristic->setService(this);
|
||||
getServer()->serviceChanged();
|
||||
} // addCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a characteristic from the service.
|
||||
* @param[in] pCharacteristic A pointer to the characteristic instance to remove from the service.
|
||||
* @param[in] deleteChr If true it will delete the characteristic instance and free it's resources.
|
||||
*/
|
||||
void NimBLEService::removeCharacteristic(NimBLECharacteristic* pCharacteristic, bool deleteChr) {
|
||||
// Check if the characteristic was already removed and if so, check if this
|
||||
// is being called to delete the object and do so if requested.
|
||||
// Otherwise, ignore the call and return.
|
||||
if(pCharacteristic->m_removed > 0) {
|
||||
if(deleteChr) {
|
||||
for(auto it = m_chrVec.begin(); it != m_chrVec.end(); ++it) {
|
||||
if ((*it) == pCharacteristic) {
|
||||
m_chrVec.erase(it);
|
||||
delete *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pCharacteristic->m_removed = deleteChr ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
||||
getServer()->serviceChanged();
|
||||
} // removeCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
|
|
|
@ -36,6 +36,10 @@ class NimBLECharacteristic;
|
|||
class NimBLEService {
|
||||
public:
|
||||
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
NimBLEServer* getServer();
|
||||
|
||||
NimBLEUUID getUUID();
|
||||
|
@ -55,6 +59,8 @@ public:
|
|||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
|
||||
void removeCharacteristic(NimBLECharacteristic* pCharacteristic, bool deleteChr = false);
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||
|
@ -65,9 +71,6 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
|
|
|
@ -277,10 +277,6 @@ std::string NimBLEUUID::toString() const {
|
|||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Comparing UUIDs; type %u to %u; UUID %s to %s",
|
||||
m_uuid.u.type, rhs.m_uuid.u.type,
|
||||
this->toString().c_str(), rhs.toString().c_str());
|
||||
|
||||
if(m_uuid.u.type != rhs.m_uuid.u.type) {
|
||||
uint8_t uuidBase[16] = {
|
||||
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file has been modified by Ryan Powell, aka h2zero.
|
||||
* The modifications are for the purpose of improving performance and support
|
||||
* for Esprssif versions used by the ardruino-esp32 core that are less current
|
||||
* than the esp-idf releases.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "sysinit/sysinit.h"
|
||||
#include "nimble/hci_common.h"
|
||||
|
@ -44,6 +37,8 @@
|
|||
#endif
|
||||
|
||||
#define NIMBLE_VHCI_TIMEOUT_MS 2000
|
||||
#define BLE_HCI_EVENT_HDR_LEN (2)
|
||||
#define BLE_HCI_CMD_HDR_LEN (3)
|
||||
|
||||
static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb;
|
||||
static void *ble_hci_rx_cmd_hs_arg;
|
||||
|
@ -276,7 +271,9 @@ void ble_hci_trans_buf_free(uint8_t *buf)
|
|||
*/
|
||||
int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
ble_hci_acl_pool.mpe_put_cb = cb;
|
||||
ble_hci_acl_pool.mpe_put_arg = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_hci_trans_reset(void)
|
||||
|
@ -313,6 +310,7 @@ static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void)
|
|||
static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct os_mbuf *m;
|
||||
int rc;
|
||||
int sr;
|
||||
if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
|
||||
return;
|
||||
|
@ -321,9 +319,11 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
|||
m = ble_hci_trans_acl_buf_alloc();
|
||||
|
||||
if (!m) {
|
||||
ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__);
|
||||
return;
|
||||
}
|
||||
if (os_mbuf_append(m, data, len)) {
|
||||
if ((rc = os_mbuf_append(m, data, len)) != 0) {
|
||||
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
|
||||
os_mbuf_free_chain(m);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT
|
||||
#define MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT
|
||||
#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0)
|
||||
#endif
|
||||
|
@ -43,11 +47,15 @@
|
|||
|
||||
/*** nimble */
|
||||
#ifndef MYNEWT_VAL_BLE_EXT_ADV
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV (0)
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV (CONFIG_BT_NIMBLE_EXT_ADV)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
|
||||
|
@ -55,12 +63,20 @@
|
|||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
|
||||
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS
|
||||
#ifdef CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV
|
||||
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER
|
||||
#ifdef CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
|
@ -267,9 +283,25 @@
|
|||
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_HS_LOG_LVL CONFIG_BT_NIMBLE_LOG_LEVEL
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV
|
||||
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#define MYNEWT_VAL_BLE_PERIODIC_ADV (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_PERIODIC_ADV (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER
|
||||
#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_VERSION
|
||||
#define MYNEWT_VAL_BLE_VERSION (50)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
|
||||
|
@ -479,6 +511,18 @@
|
|||
#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN
|
||||
#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_SYSINIT_STAGE
|
||||
#define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM
|
||||
#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM
|
||||
#endif
|
||||
|
@ -547,8 +591,12 @@
|
|||
#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HOST_BASED_PRIVACY
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (1)
|
||||
#else
|
||||
#ifndef MYNEWT_VAL_BLE_HOST_BASED_PRIVACY
|
||||
#define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (CONFIG_BT_NIMBLE_HOST_BASED_PRIVACY)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT
|
||||
|
@ -615,6 +663,27 @@
|
|||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS CONFIG_BT_NIMBLE_MAX_CCCDS
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/mesh */
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD (10)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_ADV_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_ADV_LOG_MOD (11)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST
|
||||
#ifdef CONFIG_BT_NIMBLE_NVS_PERSIST
|
||||
#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (1)
|
||||
|
@ -645,6 +714,9 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (4)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/mesh */
|
||||
/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
|
||||
|
@ -758,6 +830,14 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_FRIEND_LOG_MOD (14)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT (2)
|
||||
#endif
|
||||
|
@ -802,6 +882,14 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_LABEL_COUNT (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_LOG_MOD (9)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER
|
||||
#ifdef CONFIG_BT_NIMBLE_MESH_LOW_POWER
|
||||
#define MYNEWT_VAL_BLE_MESH_LOW_POWER (1)
|
||||
|
@ -810,6 +898,14 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_MOD (15)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LPN_AUTO
|
||||
#define MYNEWT_VAL_BLE_MESH_LPN_AUTO (1)
|
||||
#endif
|
||||
|
@ -858,6 +954,10 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS
|
||||
#define MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT (1)
|
||||
#endif
|
||||
|
@ -866,10 +966,30 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_MODEL_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_MODEL_LOG_MOD (16)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE
|
||||
#define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NET_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_NET_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NET_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_NET_LOG_MOD (17)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NODE_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_NODE_COUNT CONFIG_BT_NIMBLE_MESH_NODE_COUNT
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT (60)
|
||||
#endif
|
||||
|
@ -915,6 +1035,22 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROVISIONER
|
||||
#ifdef CONFIG_BT_NIMBLE_MESH_PROVISIONER
|
||||
#define MYNEWT_VAL_BLE_MESH_PROVISIONER (1)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_MESH_PROVISIONER (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_PROV_LOG_MOD (18)
|
||||
#endif
|
||||
|
||||
/* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROXY
|
||||
#ifdef CONFIG_BT_NIMBLE_MESH_PROXY
|
||||
|
@ -928,6 +1064,13 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROXY_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_PROXY_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROXY_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_PROXY_LOG_MOD (19)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RELAY
|
||||
#ifdef CONFIG_BT_NIMBLE_MESH_RELAY
|
||||
|
@ -949,6 +1092,10 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS
|
||||
#define MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE
|
||||
#define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128)
|
||||
#endif
|
||||
|
@ -958,6 +1105,14 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_SETTINGS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_MOD (20)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SHELL
|
||||
#define MYNEWT_VAL_BLE_MESH_SHELL (0)
|
||||
#endif
|
||||
|
@ -974,10 +1129,26 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_SUBNET_COUNT (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SYSINIT_STAGE
|
||||
#define MYNEWT_VAL_BLE_MESH_SYSINIT_STAGE (500)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SYSINIT_STAGE_SHELL
|
||||
#define MYNEWT_VAL_BLE_MESH_SYSINIT_STAGE_SHELL (1000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TESTING
|
||||
#define MYNEWT_VAL_BLE_MESH_TESTING (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TRANS_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_TRANS_LOG_LVL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TRANS_LOG_MOD
|
||||
#define MYNEWT_VAL_BLE_MESH_TRANS_LOG_MOD (21)
|
||||
#endif
|
||||
|
||||
/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MAX
|
||||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_MAX (6)
|
||||
|
@ -987,6 +1158,103 @@
|
|||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_SYSINIT_STAGE
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_SYSINIT_STAGE (303)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT (0)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/bas */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE
|
||||
#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_BAS_SYSINIT_STAGE
|
||||
#define MYNEWT_VAL_BLE_SVC_BAS_SYSINIT_STAGE (303)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/dis */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_DEFAULT_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_DEFAULT_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT ("NimBLE")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_READ_PERM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSINIT_STAGE
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SYSINIT_STAGE (303)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT (NULL)
|
||||
#endif
|
||||
|
||||
/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (-1)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/gap */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE
|
||||
|
@ -1102,4 +1370,8 @@
|
|||
#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
|
||||
#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -128,6 +128,7 @@ struct hci_conn_update;
|
|||
#define BLE_GAP_EVENT_PERIODIC_REPORT 21
|
||||
#define BLE_GAP_EVENT_PERIODIC_SYNC_LOST 22
|
||||
#define BLE_GAP_EVENT_SCAN_REQ_RCVD 23
|
||||
#define BLE_GAP_EVENT_PERIODIC_TRANSFER 24
|
||||
|
||||
/*** Reason codes for the subscribe GAP event. */
|
||||
|
||||
|
@ -390,7 +391,7 @@ struct ble_gap_ext_disc_desc {
|
|||
uint8_t length_data;
|
||||
|
||||
/** Advertising data */
|
||||
uint8_t *data;
|
||||
const uint8_t *data;
|
||||
|
||||
/** Directed advertising address. Valid if BLE_HCI_ADV_DIRECT_MASK props is
|
||||
* set (BLE_ADDR_ANY otherwise).
|
||||
|
@ -420,7 +421,7 @@ struct ble_gap_disc_desc {
|
|||
int8_t rssi;
|
||||
|
||||
/** Advertising data */
|
||||
uint8_t *data;
|
||||
const uint8_t *data;
|
||||
|
||||
/** Directed advertising address. Valid for BLE_HCI_ADV_RPT_EVTYPE_DIR_IND
|
||||
* event type (BLE_ADDR_ANY otherwise).
|
||||
|
@ -890,7 +891,7 @@ struct ble_gap_event {
|
|||
uint8_t data_length;
|
||||
|
||||
/** Advertising data */
|
||||
uint8_t *data;
|
||||
const uint8_t *data;
|
||||
} periodic_report;
|
||||
|
||||
/**
|
||||
|
@ -924,6 +925,47 @@ struct ble_gap_event {
|
|||
/** Address of scanner */
|
||||
ble_addr_t scan_addr;
|
||||
} scan_req_rcvd;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
/**
|
||||
* Represents a periodic advertising sync transfer received. Valid for
|
||||
* the following event types:
|
||||
* o BLE_GAP_EVENT_PERIODIC_TRANSFER
|
||||
*/
|
||||
struct {
|
||||
/** BLE_ERR_SUCCESS on success or error code on failure. Sync handle
|
||||
* is valid only for success.
|
||||
*/
|
||||
uint8_t status;
|
||||
|
||||
/** Periodic sync handle */
|
||||
uint16_t sync_handle;
|
||||
|
||||
/** Connection handle */
|
||||
uint16_t conn_handle;
|
||||
|
||||
/** Service Data */
|
||||
uint16_t service_data;
|
||||
|
||||
/** Advertising Set ID */
|
||||
uint8_t sid;
|
||||
|
||||
/** Advertiser address */
|
||||
ble_addr_t adv_addr;
|
||||
|
||||
/** Advertising PHY, can be one of following constants:
|
||||
* - BLE_HCI_LE_PHY_1M
|
||||
* - LE_HCI_LE_PHY_2M
|
||||
* - BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
uint8_t adv_phy;
|
||||
|
||||
/** Periodic advertising interval */
|
||||
uint16_t per_adv_itvl;
|
||||
|
||||
/** Advertiser clock accuracy */
|
||||
uint8_t adv_clk_accuracy;
|
||||
} periodic_transfer;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
@ -1097,6 +1139,23 @@ int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields);
|
|||
*/
|
||||
int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);
|
||||
|
||||
/**
|
||||
* Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022).
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param tx_octets The preferred value of payload octets that the Controller
|
||||
* should use for a new connection (Range
|
||||
* 0x001B-0x00FB).
|
||||
* @param tx_time The preferred maximum number of microseconds that the local Controller
|
||||
* should use to transmit a single link layer packet
|
||||
* (Range 0x0148-0x4290).
|
||||
*
|
||||
* @return 0 on success,
|
||||
* other error code on failure.
|
||||
*/
|
||||
int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
|
||||
uint16_t tx_time);
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/** @brief Extended advertising parameters */
|
||||
struct ble_gap_ext_adv_params {
|
||||
|
@ -1203,8 +1262,8 @@ int ble_gap_ext_adv_set_addr(uint8_t instance, const ble_addr_t *addr);
|
|||
* @param instance Instance ID
|
||||
* @param duration The duration of the advertisement procedure. On
|
||||
* expiration, the procedure ends and
|
||||
* a BLE_HS_FOREVER event is reported.
|
||||
* Units are milliseconds. Specify 0 for no
|
||||
* a BLE_GAP_EVENT_ADV_COMPLETE event is reported.
|
||||
* Units are 10 milliseconds. Specify 0 for no
|
||||
* expiration.
|
||||
* @params max_events Number of advertising events that should be sent
|
||||
* before advertising ends and
|
||||
|
@ -1297,6 +1356,9 @@ struct ble_gap_periodic_sync_params {
|
|||
/** Synchronization timeout for the periodic advertising train in 10ms units
|
||||
*/
|
||||
uint16_t sync_timeout;
|
||||
|
||||
/** If reports should be initially disabled when sync is created */
|
||||
unsigned int reports_disabled:1;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1359,7 +1421,7 @@ int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data);
|
|||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_create_sync(const ble_addr_t *addr, uint8_t adv_sid,
|
||||
int ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid,
|
||||
const struct ble_gap_periodic_sync_params *params,
|
||||
ble_gap_event_fn *cb, void *cb_arg);
|
||||
|
||||
|
@ -1368,7 +1430,7 @@ int ble_gap_periodic_adv_create_sync(const ble_addr_t *addr, uint8_t adv_sid,
|
|||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_create_sync_cancel(void);
|
||||
int ble_gap_periodic_adv_sync_create_cancel(void);
|
||||
|
||||
/**
|
||||
* Terminate synchronization procedure.
|
||||
|
@ -1377,7 +1439,74 @@ int ble_gap_periodic_adv_create_sync_cancel(void);
|
|||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_terminate_sync(uint16_t sync_handle);
|
||||
int ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle);
|
||||
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
/**
|
||||
* Disable or enable periodic reports for specified sync.
|
||||
*
|
||||
* @param sync_handle Handle identifying synchronization.
|
||||
* @param enable If reports should be enabled.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable);
|
||||
|
||||
/**
|
||||
* Initialize sync transfer procedure for specified handles.
|
||||
*
|
||||
* This allows to transfer periodic sync to which host is synchronized.
|
||||
*
|
||||
* @param sync_handle Handle identifying synchronization.
|
||||
* @param conn_handle Handle identifying connection.
|
||||
* @param service_data Sync transfer service data
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_sync_transfer(uint16_t sync_handle,
|
||||
uint16_t conn_handle,
|
||||
uint16_t service_data);
|
||||
|
||||
/**
|
||||
* Initialize set info transfer procedure for specified handles.
|
||||
*
|
||||
* This allows to transfer periodic sync which is being advertised by host.
|
||||
*
|
||||
* @param instance Advertising instance with periodic adv enabled.
|
||||
* @param conn_handle Handle identifying connection.
|
||||
* @param service_data Sync transfer service data
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_sync_set_info(uint8_t instance,
|
||||
uint16_t conn_handle,
|
||||
uint16_t service_data);
|
||||
|
||||
/**
|
||||
* Enables or disables sync transfer reception on specified connection.
|
||||
* When sync transfer arrives, BLE_GAP_EVENT_PERIODIC_TRANSFER is sent to the user.
|
||||
* After that, sync transfer reception on that connection is terminated and user needs
|
||||
* to call this API again when expect to receive next sync transfers.
|
||||
*
|
||||
* Note: If ACL connection gets disconnected before sync transfer arrived, user will
|
||||
* not receive BLE_GAP_EVENT_PERIODIC_TRANSFER. Instead, sync transfer reception
|
||||
* is terminated by the host automatically.
|
||||
*
|
||||
* @param conn_handle Handle identifying connection.
|
||||
* @param params Parameters for enabled sync transfer reception.
|
||||
* Specify NULL to disable reception.
|
||||
* @param cb The callback to associate with this synchronization
|
||||
* procedure. BLE_GAP_EVENT_PERIODIC_REPORT events
|
||||
* are reported only by this callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_periodic_adv_sync_receive(uint16_t conn_handle,
|
||||
const struct ble_gap_periodic_sync_params *params,
|
||||
ble_gap_event_fn *cb, void *cb_arg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Add peer device to periodic synchronization list.
|
||||
|
@ -1435,7 +1564,8 @@ int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size);
|
|||
* On expiration, the procedure ends and a
|
||||
* BLE_GAP_EVENT_DISC_COMPLETE event is
|
||||
* reported. Units are milliseconds. Specify
|
||||
* BLE_HS_FOREVER for no expiration.
|
||||
* BLE_HS_FOREVER for no expiration. Specify
|
||||
* 0 to use stack defaults.
|
||||
* @param disc_params Additional arguments specifying the particulars
|
||||
* of the discovery procedure.
|
||||
* @param cb The callback to associate with this discovery
|
||||
|
@ -1661,6 +1791,15 @@ int ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason);
|
|||
*/
|
||||
int ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count);
|
||||
|
||||
/**
|
||||
* Removes the address from controller's white list.
|
||||
*
|
||||
* @param addrs The entry to be removed from the white list.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gap_wl_tx_rmv(const ble_addr_t *addrs);
|
||||
|
||||
/**
|
||||
* Initiates a connection parameter update procedure.
|
||||
*
|
||||
|
|
|
@ -35,7 +35,7 @@ extern "C" {
|
|||
struct ble_hs_adv_field {
|
||||
uint8_t length;
|
||||
uint8_t type;
|
||||
uint8_t value[];
|
||||
uint8_t value[0];
|
||||
};
|
||||
|
||||
typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *,
|
||||
|
@ -46,22 +46,22 @@ struct ble_hs_adv_fields {
|
|||
uint8_t flags;
|
||||
|
||||
/*** 0x02,0x03 - 16-bit service class UUIDs. */
|
||||
ble_uuid16_t *uuids16;
|
||||
const ble_uuid16_t *uuids16;
|
||||
uint8_t num_uuids16;
|
||||
unsigned uuids16_is_complete:1;
|
||||
|
||||
/*** 0x04,0x05 - 32-bit service class UUIDs. */
|
||||
ble_uuid32_t *uuids32;
|
||||
const ble_uuid32_t *uuids32;
|
||||
uint8_t num_uuids32;
|
||||
unsigned uuids32_is_complete:1;
|
||||
|
||||
/*** 0x06,0x07 - 128-bit service class UUIDs. */
|
||||
ble_uuid128_t *uuids128;
|
||||
const ble_uuid128_t *uuids128;
|
||||
uint8_t num_uuids128;
|
||||
unsigned uuids128_is_complete:1;
|
||||
|
||||
/*** 0x08,0x09 - Local name. */
|
||||
uint8_t *name;
|
||||
const uint8_t *name;
|
||||
uint8_t name_len;
|
||||
unsigned name_is_complete:1;
|
||||
|
||||
|
@ -70,14 +70,14 @@ struct ble_hs_adv_fields {
|
|||
unsigned tx_pwr_lvl_is_present:1;
|
||||
|
||||
/*** 0x0d - Slave connection interval range. */
|
||||
uint8_t *slave_itvl_range;
|
||||
const uint8_t *slave_itvl_range;
|
||||
|
||||
/*** 0x16 - Service data - 16-bit UUID. */
|
||||
uint8_t *svc_data_uuid16;
|
||||
const uint8_t *svc_data_uuid16;
|
||||
uint8_t svc_data_uuid16_len;
|
||||
|
||||
/*** 0x17 - Public target address. */
|
||||
uint8_t *public_tgt_addr;
|
||||
const uint8_t *public_tgt_addr;
|
||||
uint8_t num_public_tgt_addrs;
|
||||
|
||||
/*** 0x19 - Appearance. */
|
||||
|
@ -89,19 +89,19 @@ struct ble_hs_adv_fields {
|
|||
unsigned adv_itvl_is_present:1;
|
||||
|
||||
/*** 0x20 - Service data - 32-bit UUID. */
|
||||
uint8_t *svc_data_uuid32;
|
||||
const uint8_t *svc_data_uuid32;
|
||||
uint8_t svc_data_uuid32_len;
|
||||
|
||||
/*** 0x21 - Service data - 128-bit UUID. */
|
||||
uint8_t *svc_data_uuid128;
|
||||
const uint8_t *svc_data_uuid128;
|
||||
uint8_t svc_data_uuid128_len;
|
||||
|
||||
/*** 0x24 - URI. */
|
||||
uint8_t *uri;
|
||||
const uint8_t *uri;
|
||||
uint8_t uri_len;
|
||||
|
||||
/*** 0xff - Manufacturer specific data. */
|
||||
uint8_t *mfg_data;
|
||||
const uint8_t *mfg_data;
|
||||
uint8_t mfg_data_len;
|
||||
};
|
||||
|
||||
|
@ -164,8 +164,8 @@ int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
|
|||
int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
|
||||
uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
|
||||
|
||||
int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src,
|
||||
uint8_t src_len);
|
||||
int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields,
|
||||
const uint8_t *src, uint8_t src_len);
|
||||
|
||||
int ble_hs_adv_parse(const uint8_t *data, uint8_t length,
|
||||
ble_hs_adv_parse_func_t func, void *user_data);
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
#include "modlog/modlog.h"
|
||||
|
||||
/* Only include the logcfg header if this version of newt can generate it. */
|
||||
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
|
||||
#include "logcfg/logcfg.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -29,13 +34,13 @@ extern "C" {
|
|||
struct os_mbuf;
|
||||
|
||||
#define BLE_HS_LOG(lvl, ...) \
|
||||
MODLOG_ ## lvl(LOG_MODULE_NIMBLE_HOST, __VA_ARGS__)
|
||||
BLE_HS_LOG_ ## lvl(__VA_ARGS__)
|
||||
|
||||
#define BLE_HS_LOG_ADDR(lvl, addr) \
|
||||
MODLOG_ ## lvl(LOG_MODULE_NIMBLE_HOST, \
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x", \
|
||||
(addr)[5], (addr)[4], (addr)[3], \
|
||||
(addr)[2], (addr)[1], (addr)[0])
|
||||
BLE_HS_LOG_ ## lvl("%02x:%02x:%02x:%02x:%02x:%02x", \
|
||||
(addr)[5], (addr)[4], (addr)[3], \
|
||||
(addr)[2], (addr)[1], (addr)[0])
|
||||
|
||||
|
||||
void ble_hs_log_mbuf(const struct os_mbuf *om);
|
||||
void ble_hs_log_flat_buf(const void *data, int len);
|
||||
|
|
|
@ -51,10 +51,14 @@ struct ble_hs_conn;
|
|||
#define BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_RSP 0x11
|
||||
#define BLE_L2CAP_SIG_OP_UPDATE_REQ 0x12
|
||||
#define BLE_L2CAP_SIG_OP_UPDATE_RSP 0x13
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ 0x14
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP 0x15
|
||||
#define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_REQ 0x14
|
||||
#define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP 0x15
|
||||
#define BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT 0x16
|
||||
#define BLE_L2CAP_SIG_OP_MAX 0x17
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ 0x17
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP 0x18
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_REQ 0x19
|
||||
#define BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP 0x1A
|
||||
#define BLE_L2CAP_SIG_OP_MAX 0x1B
|
||||
|
||||
#define BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD 0x0000
|
||||
#define BLE_L2CAP_SIG_ERR_MTU_EXCEEDED 0x0001
|
||||
|
@ -70,12 +74,21 @@ struct ble_hs_conn;
|
|||
#define BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID 0x0009
|
||||
#define BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED 0x000A
|
||||
#define BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS 0x000B
|
||||
#define BLE_L2CAP_COC_ERR_INVALID_PARAMETERS 0x000C
|
||||
|
||||
#define BLE_L2CAP_ERR_RECONFIG_SUCCEED 0x0000
|
||||
#define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED 0x0001
|
||||
#define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED 0x0002
|
||||
#define BLE_L2CAP_ERR_RECONFIG_INVALID_DCID 0x0003
|
||||
#define BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM 0x0004
|
||||
|
||||
#define BLE_L2CAP_EVENT_COC_CONNECTED 0
|
||||
#define BLE_L2CAP_EVENT_COC_DISCONNECTED 1
|
||||
#define BLE_L2CAP_EVENT_COC_ACCEPT 2
|
||||
#define BLE_L2CAP_EVENT_COC_DATA_RECEIVED 3
|
||||
#define BLE_L2CAP_EVENT_COC_TX_UNSTALLED 4
|
||||
#define BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED 5
|
||||
#define BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED 6
|
||||
|
||||
typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
|
||||
void *arg);
|
||||
|
@ -196,11 +209,44 @@ struct ble_l2cap_event {
|
|||
*/
|
||||
int status;
|
||||
} tx_unstalled;
|
||||
|
||||
/**
|
||||
* Represents reconfiguration done. Valid for the following event
|
||||
* types:
|
||||
* o BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED
|
||||
* o BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* The status of the reconfiguration attempt;
|
||||
* o 0: the reconfiguration was successfully done.
|
||||
* o BLE host error code: the reconfiguration attempt failed for
|
||||
* the specified reason.
|
||||
*/
|
||||
int status;
|
||||
|
||||
/** Connection handle of the relevant connection */
|
||||
uint16_t conn_handle;
|
||||
|
||||
/** The L2CAP channel of the relevant L2CAP connection. */
|
||||
struct ble_l2cap_chan *chan;
|
||||
} reconfigured;
|
||||
};
|
||||
};
|
||||
|
||||
struct ble_l2cap_chan_info {
|
||||
uint16_t scid;
|
||||
uint16_t dcid;
|
||||
uint16_t our_l2cap_mtu;
|
||||
uint16_t peer_l2cap_mtu;
|
||||
uint16_t psm;
|
||||
uint16_t our_coc_mtu;
|
||||
uint16_t peer_coc_mtu;
|
||||
};
|
||||
|
||||
typedef int ble_l2cap_event_fn(struct ble_l2cap_event *event, void *arg);
|
||||
|
||||
|
||||
uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_create_server(uint16_t psm, uint16_t mtu,
|
||||
ble_l2cap_event_fn *cb, void *cb_arg);
|
||||
|
@ -211,10 +257,7 @@ int ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
|
|||
int ble_l2cap_disconnect(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx);
|
||||
int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx);
|
||||
int ble_l2cap_get_scid(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_get_dcid(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_get_our_mtu(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_get_peer_mtu(struct ble_l2cap_chan *chan);
|
||||
int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -84,7 +84,16 @@ extern "C" {
|
|||
#define BLE_SM_IOACT_INPUT 2
|
||||
#define BLE_SM_IOACT_DISP 3
|
||||
#define BLE_SM_IOACT_NUMCMP 4
|
||||
#define BLE_SM_IOACT_MAX_PLUS_ONE 5
|
||||
#define BLE_SM_IOACT_OOB_SC 5
|
||||
#define BLE_SM_IOACT_MAX_PLUS_ONE 6
|
||||
|
||||
struct ble_sm_sc_oob_data {
|
||||
/** Random Number. */
|
||||
uint8_t r[16];
|
||||
|
||||
/** Confirm Value. */
|
||||
uint8_t c[16];
|
||||
};
|
||||
|
||||
struct ble_sm_io {
|
||||
uint8_t action;
|
||||
|
@ -92,9 +101,15 @@ struct ble_sm_io {
|
|||
uint32_t passkey;
|
||||
uint8_t oob[16];
|
||||
uint8_t numcmp_accept;
|
||||
struct {
|
||||
struct ble_sm_sc_oob_data *local;
|
||||
struct ble_sm_sc_oob_data *remote;
|
||||
} oob_sc_data;
|
||||
};
|
||||
};
|
||||
|
||||
int ble_sm_sc_oob_generate_data(struct ble_sm_sc_oob_data *oob_data);
|
||||
|
||||
#if NIMBLE_BLE_SM
|
||||
int ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey);
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_IGNORE_
|
||||
#define H_IGNORE_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* These macros prevent the "set but not used" warnings for log writes below
|
||||
* the log level.
|
||||
*/
|
||||
|
||||
#define IGN_1(X) ((void)(X))
|
||||
#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
|
||||
#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
|
||||
#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
|
||||
#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
|
||||
#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
|
||||
#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
|
||||
#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
|
||||
#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
|
||||
#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
|
||||
#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
|
||||
#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
|
||||
#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
|
||||
#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
|
||||
#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
|
||||
#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
|
||||
#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
|
||||
#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
|
||||
#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
|
||||
#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
|
||||
|
||||
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
|
||||
_13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
|
||||
#define IGNORE(...) \
|
||||
GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
|
||||
IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
|
||||
IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -17,18 +17,26 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HS_DBG_PRIV_
|
||||
#define H_BLE_HS_DBG_PRIV_
|
||||
#ifndef H_LOG_COMMON_
|
||||
#define H_LOG_COMMON_
|
||||
|
||||
#include "log_common/ignore.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ble_hs_dbg_event_disp(uint8_t *evbuf);
|
||||
void ble_hs_dbg_set_sync_state(uint8_t sync_state);
|
||||
#define LOG_LEVEL_DEBUG (0)
|
||||
#define LOG_LEVEL_INFO (1)
|
||||
#define LOG_LEVEL_WARN (2)
|
||||
#define LOG_LEVEL_ERROR (3)
|
||||
#define LOG_LEVEL_CRITICAL (4)
|
||||
#define LOG_LEVEL_NONE (5)
|
||||
/* Up to 7 custom log levels. */
|
||||
#define LOG_LEVEL_MAX (15)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_HOST_DBG_ */
|
||||
#endif
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* This file was generated by Apache newt version: 1.8.0-dev
|
||||
*/
|
||||
|
||||
#ifndef H_MYNEWT_LOGCFG_
|
||||
#define H_MYNEWT_LOGCFG_
|
||||
|
||||
#include "modlog/modlog.h"
|
||||
#include "log_common/log_common.h"
|
||||
|
||||
#if (MYNEWT_VAL(BLE_HS_LOG_LVL) == LOG_LEVEL_DEBUG)
|
||||
#define BLE_HS_LOG_DEBUG(...) MODLOG_DEBUG(4, __VA_ARGS__)
|
||||
#else
|
||||
#define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LEVEL_INFO)
|
||||
#define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__)
|
||||
#else
|
||||
#define BLE_HS_LOG_INFO(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LEVEL_WARN)
|
||||
#define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__)
|
||||
#else
|
||||
#define BLE_HS_LOG_WARN(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LEVEL_ERROR)
|
||||
#define BLE_HS_LOG_ERROR(...) MODLOG_ERROR(4, __VA_ARGS__)
|
||||
#else
|
||||
#define BLE_HS_LOG_ERROR(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LEVEL_CRITICAL)
|
||||
#define BLE_HS_LOG_CRITICAL(...) MODLOG_CRITICAL(4, __VA_ARGS__)
|
||||
#else
|
||||
#define BLE_HS_LOG_CRITICAL(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define BLE_HS_LOG_DISABLED(...) MODLOG_DISABLED(4, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_ACCESS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_ACCESS_LOG_INFO(...) MODLOG_INFO(10, __VA_ARGS__)
|
||||
#define BLE_MESH_ACCESS_LOG_WARN(...) MODLOG_WARN(10, __VA_ARGS__)
|
||||
#define BLE_MESH_ACCESS_LOG_ERROR(...) MODLOG_ERROR(10, __VA_ARGS__)
|
||||
#define BLE_MESH_ACCESS_LOG_CRITICAL(...) MODLOG_CRITICAL(10, __VA_ARGS__)
|
||||
#define BLE_MESH_ACCESS_LOG_DISABLED(...) MODLOG_DISABLED(10, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_ADV_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_ADV_LOG_INFO(...) MODLOG_INFO(11, __VA_ARGS__)
|
||||
#define BLE_MESH_ADV_LOG_WARN(...) MODLOG_WARN(11, __VA_ARGS__)
|
||||
#define BLE_MESH_ADV_LOG_ERROR(...) MODLOG_ERROR(11, __VA_ARGS__)
|
||||
#define BLE_MESH_ADV_LOG_CRITICAL(...) MODLOG_CRITICAL(11, __VA_ARGS__)
|
||||
#define BLE_MESH_ADV_LOG_DISABLED(...) MODLOG_DISABLED(11, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_BEACON_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_BEACON_LOG_INFO(...) MODLOG_INFO(12, __VA_ARGS__)
|
||||
#define BLE_MESH_BEACON_LOG_WARN(...) MODLOG_WARN(12, __VA_ARGS__)
|
||||
#define BLE_MESH_BEACON_LOG_ERROR(...) MODLOG_ERROR(12, __VA_ARGS__)
|
||||
#define BLE_MESH_BEACON_LOG_CRITICAL(...) MODLOG_CRITICAL(12, __VA_ARGS__)
|
||||
#define BLE_MESH_BEACON_LOG_DISABLED(...) MODLOG_DISABLED(12, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_CRYPTO_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_CRYPTO_LOG_INFO(...) MODLOG_INFO(13, __VA_ARGS__)
|
||||
#define BLE_MESH_CRYPTO_LOG_WARN(...) MODLOG_WARN(13, __VA_ARGS__)
|
||||
#define BLE_MESH_CRYPTO_LOG_ERROR(...) MODLOG_ERROR(13, __VA_ARGS__)
|
||||
#define BLE_MESH_CRYPTO_LOG_CRITICAL(...) MODLOG_CRITICAL(13, __VA_ARGS__)
|
||||
#define BLE_MESH_CRYPTO_LOG_DISABLED(...) MODLOG_DISABLED(13, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_FRIEND_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_FRIEND_LOG_INFO(...) MODLOG_INFO(14, __VA_ARGS__)
|
||||
#define BLE_MESH_FRIEND_LOG_WARN(...) MODLOG_WARN(14, __VA_ARGS__)
|
||||
#define BLE_MESH_FRIEND_LOG_ERROR(...) MODLOG_ERROR(14, __VA_ARGS__)
|
||||
#define BLE_MESH_FRIEND_LOG_CRITICAL(...) MODLOG_CRITICAL(14, __VA_ARGS__)
|
||||
#define BLE_MESH_FRIEND_LOG_DISABLED(...) MODLOG_DISABLED(14, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_LOG_INFO(...) MODLOG_INFO(9, __VA_ARGS__)
|
||||
#define BLE_MESH_LOG_WARN(...) MODLOG_WARN(9, __VA_ARGS__)
|
||||
#define BLE_MESH_LOG_ERROR(...) MODLOG_ERROR(9, __VA_ARGS__)
|
||||
#define BLE_MESH_LOG_CRITICAL(...) MODLOG_CRITICAL(9, __VA_ARGS__)
|
||||
#define BLE_MESH_LOG_DISABLED(...) MODLOG_DISABLED(9, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_LOW_POWER_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_LOW_POWER_LOG_INFO(...) MODLOG_INFO(15, __VA_ARGS__)
|
||||
#define BLE_MESH_LOW_POWER_LOG_WARN(...) MODLOG_WARN(15, __VA_ARGS__)
|
||||
#define BLE_MESH_LOW_POWER_LOG_ERROR(...) MODLOG_ERROR(15, __VA_ARGS__)
|
||||
#define BLE_MESH_LOW_POWER_LOG_CRITICAL(...) MODLOG_CRITICAL(15, __VA_ARGS__)
|
||||
#define BLE_MESH_LOW_POWER_LOG_DISABLED(...) MODLOG_DISABLED(15, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_MODEL_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_MODEL_LOG_INFO(...) MODLOG_INFO(16, __VA_ARGS__)
|
||||
#define BLE_MESH_MODEL_LOG_WARN(...) MODLOG_WARN(16, __VA_ARGS__)
|
||||
#define BLE_MESH_MODEL_LOG_ERROR(...) MODLOG_ERROR(16, __VA_ARGS__)
|
||||
#define BLE_MESH_MODEL_LOG_CRITICAL(...) MODLOG_CRITICAL(16, __VA_ARGS__)
|
||||
#define BLE_MESH_MODEL_LOG_DISABLED(...) MODLOG_DISABLED(16, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_NET_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_NET_LOG_INFO(...) MODLOG_INFO(17, __VA_ARGS__)
|
||||
#define BLE_MESH_NET_LOG_WARN(...) MODLOG_WARN(17, __VA_ARGS__)
|
||||
#define BLE_MESH_NET_LOG_ERROR(...) MODLOG_ERROR(17, __VA_ARGS__)
|
||||
#define BLE_MESH_NET_LOG_CRITICAL(...) MODLOG_CRITICAL(17, __VA_ARGS__)
|
||||
#define BLE_MESH_NET_LOG_DISABLED(...) MODLOG_DISABLED(17, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_PROV_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_PROV_LOG_INFO(...) MODLOG_INFO(18, __VA_ARGS__)
|
||||
#define BLE_MESH_PROV_LOG_WARN(...) MODLOG_WARN(18, __VA_ARGS__)
|
||||
#define BLE_MESH_PROV_LOG_ERROR(...) MODLOG_ERROR(18, __VA_ARGS__)
|
||||
#define BLE_MESH_PROV_LOG_CRITICAL(...) MODLOG_CRITICAL(18, __VA_ARGS__)
|
||||
#define BLE_MESH_PROV_LOG_DISABLED(...) MODLOG_DISABLED(18, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_PROXY_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_PROXY_LOG_INFO(...) MODLOG_INFO(19, __VA_ARGS__)
|
||||
#define BLE_MESH_PROXY_LOG_WARN(...) MODLOG_WARN(19, __VA_ARGS__)
|
||||
#define BLE_MESH_PROXY_LOG_ERROR(...) MODLOG_ERROR(19, __VA_ARGS__)
|
||||
#define BLE_MESH_PROXY_LOG_CRITICAL(...) MODLOG_CRITICAL(19, __VA_ARGS__)
|
||||
#define BLE_MESH_PROXY_LOG_DISABLED(...) MODLOG_DISABLED(19, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_SETTINGS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_SETTINGS_LOG_INFO(...) MODLOG_INFO(20, __VA_ARGS__)
|
||||
#define BLE_MESH_SETTINGS_LOG_WARN(...) MODLOG_WARN(20, __VA_ARGS__)
|
||||
#define BLE_MESH_SETTINGS_LOG_ERROR(...) MODLOG_ERROR(20, __VA_ARGS__)
|
||||
#define BLE_MESH_SETTINGS_LOG_CRITICAL(...) MODLOG_CRITICAL(20, __VA_ARGS__)
|
||||
#define BLE_MESH_SETTINGS_LOG_DISABLED(...) MODLOG_DISABLED(20, __VA_ARGS__)
|
||||
|
||||
#define BLE_MESH_TRANS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define BLE_MESH_TRANS_LOG_INFO(...) MODLOG_INFO(21, __VA_ARGS__)
|
||||
#define BLE_MESH_TRANS_LOG_WARN(...) MODLOG_WARN(21, __VA_ARGS__)
|
||||
#define BLE_MESH_TRANS_LOG_ERROR(...) MODLOG_ERROR(21, __VA_ARGS__)
|
||||
#define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__)
|
||||
#define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__)
|
||||
#define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__)
|
||||
#define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__)
|
||||
#define DFLT_LOG_ERROR(...) MODLOG_ERROR(0, __VA_ARGS__)
|
||||
#define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__)
|
||||
#define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__)
|
||||
|
||||
#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
|
||||
#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__)
|
||||
#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__)
|
||||
#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__)
|
||||
#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__)
|
||||
#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__)
|
||||
|
||||
#endif
|
|
@ -29,6 +29,12 @@ extern "C" {
|
|||
|
||||
#define BT_MESH_KEY_UNUSED 0xffff
|
||||
#define BT_MESH_KEY_DEV 0xfffe
|
||||
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
|
||||
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
|
||||
#define BT_MESH_KEY_DEV_ANY 0xfffc
|
||||
|
||||
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
|
||||
key == BT_MESH_KEY_DEV_REMOTE)
|
||||
|
||||
/** Helper to define a mesh element within an array.
|
||||
*
|
||||
|
@ -137,11 +143,14 @@ struct bt_mesh_msg_ctx {
|
|||
/** Destination address of a received message. Not used for sending. */
|
||||
u16_t recv_dst;
|
||||
|
||||
/** RSSI of received packet. Not used for sending. */
|
||||
s8_t recv_rssi;
|
||||
|
||||
/** Received TTL value. Not used for sending. */
|
||||
u8_t recv_ttl:7;
|
||||
u8_t recv_ttl;
|
||||
|
||||
/** Force sending reliably by using segment acknowledgement */
|
||||
u8_t send_rel:1;
|
||||
bool send_rel;
|
||||
|
||||
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
|
||||
u8_t send_ttl;
|
||||
|
@ -171,7 +180,66 @@ struct bt_mesh_model_op {
|
|||
/** Helper to define an empty model array */
|
||||
#define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){})
|
||||
|
||||
#define BT_MESH_MODEL(_id, _op, _pub, _user_data) \
|
||||
/** Length of a short Mesh MIC. */
|
||||
#define BT_MESH_MIC_SHORT 4
|
||||
/** Length of a long Mesh MIC. */
|
||||
#define BT_MESH_MIC_LONG 8
|
||||
|
||||
/** @def BT_MESH_MODEL_OP_LEN
|
||||
*
|
||||
* @brief Helper to determine the length of an opcode.
|
||||
*
|
||||
* @param _op Opcode.
|
||||
*/
|
||||
#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
|
||||
|
||||
/** @def BT_MESH_MODEL_BUF_LEN
|
||||
*
|
||||
* @brief Helper for model message buffer length.
|
||||
*
|
||||
* Returns the length of a Mesh model message buffer, including the opcode
|
||||
* length and a short MIC.
|
||||
*
|
||||
* @param _op Opcode of the message.
|
||||
* @param _payload_len Length of the model payload.
|
||||
*/
|
||||
#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \
|
||||
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT)
|
||||
|
||||
/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC
|
||||
*
|
||||
* @brief Helper for model message buffer length.
|
||||
*
|
||||
* Returns the length of a Mesh model message buffer, including the opcode
|
||||
* length and a long MIC.
|
||||
*
|
||||
* @param _op Opcode of the message.
|
||||
* @param _payload_len Length of the model payload.
|
||||
*/
|
||||
#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \
|
||||
(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG)
|
||||
|
||||
/** @def BT_MESH_MODEL_BUF_DEFINE
|
||||
*
|
||||
* @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE.
|
||||
*
|
||||
* @param _op Opcode of the message.
|
||||
* @param _payload_len Length of the model message payload.
|
||||
*/
|
||||
#define BT_MESH_MODEL_BUF(_op, _payload_len) \
|
||||
NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
|
||||
|
||||
/** @def BT_MESH_MODEL_CB
|
||||
*
|
||||
* @brief Composition data SIG model entry with callback functions.
|
||||
*
|
||||
* @param _id Model ID.
|
||||
* @param _op Array of model opcode handlers.
|
||||
* @param _pub Model publish parameters.
|
||||
* @param _user_data User data for the model.
|
||||
* @param _cb Callback structure, or NULL to keep no callbacks.
|
||||
*/
|
||||
#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb) \
|
||||
{ \
|
||||
.id = (_id), \
|
||||
.op = _op, \
|
||||
|
@ -181,9 +249,21 @@ struct bt_mesh_model_op {
|
|||
.groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \
|
||||
BT_MESH_ADDR_UNASSIGNED }, \
|
||||
.user_data = _user_data, \
|
||||
.cb = _cb, \
|
||||
}
|
||||
|
||||
#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data) \
|
||||
/** @def BT_MESH_MODEL_VND_CB
|
||||
*
|
||||
* @brief Composition data vendor model entry with callback functions.
|
||||
*
|
||||
* @param _company Company ID.
|
||||
* @param _id Model ID.
|
||||
* @param _op Array of model opcode handlers.
|
||||
* @param _pub Model publish parameters.
|
||||
* @param _user_data User data for the model.
|
||||
* @param _cb Callback structure, or NULL to keep no callbacks.
|
||||
*/
|
||||
#define BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb) \
|
||||
{ \
|
||||
.vnd.company = (_company), \
|
||||
.vnd.id = (_id), \
|
||||
|
@ -194,8 +274,35 @@ struct bt_mesh_model_op {
|
|||
.groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \
|
||||
BT_MESH_ADDR_UNASSIGNED }, \
|
||||
.user_data = _user_data, \
|
||||
.cb = _cb, \
|
||||
}
|
||||
|
||||
|
||||
/** @def BT_MESH_MODEL
|
||||
*
|
||||
* @brief Composition data SIG model entry.
|
||||
*
|
||||
* @param _id Model ID.
|
||||
* @param _op Array of model opcode handlers.
|
||||
* @param _pub Model publish parameters.
|
||||
* @param _user_data User data for the model.
|
||||
*/
|
||||
#define BT_MESH_MODEL(_id, _op, _pub, _user_data) \
|
||||
BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, NULL)
|
||||
|
||||
/** @def BT_MESH_MODEL_VND
|
||||
*
|
||||
* @brief Composition data vendor model entry.
|
||||
*
|
||||
* @param _company Company ID.
|
||||
* @param _id Model ID.
|
||||
* @param _op Array of model opcode handlers.
|
||||
* @param _pub Model publish parameters.
|
||||
* @param _user_data User data for the model.
|
||||
*/
|
||||
#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data) \
|
||||
BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, NULL)
|
||||
|
||||
/** @def BT_MESH_TRANSMIT
|
||||
*
|
||||
* @brief Encode transmission count & interval steps.
|
||||
|
@ -276,6 +383,7 @@ struct bt_mesh_model_pub {
|
|||
u8_t period; /**< Publish Period. */
|
||||
u8_t period_div:4, /**< Divisor for the Period. */
|
||||
cred:1, /**< Friendship Credentials Flag. */
|
||||
fast_period:1,/**< Use FastPeriodDivisor */
|
||||
count:3; /**< Retransmissions left. */
|
||||
|
||||
u32_t period_start; /**< Start of the current period. */
|
||||
|
@ -317,6 +425,52 @@ struct bt_mesh_model_pub {
|
|||
struct k_delayed_work timer;
|
||||
};
|
||||
|
||||
/** Model callback functions. */
|
||||
struct bt_mesh_model_cb {
|
||||
/** @brief Set value handler of user data tied to the model.
|
||||
*
|
||||
* @sa settings_handler::h_set
|
||||
*
|
||||
* @param model Model to set the persistent data of.
|
||||
* @param val Data from the backend.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_set)(struct bt_mesh_model *model, char *val);
|
||||
|
||||
/** @brief Callback called when all settings have been loaded.
|
||||
*
|
||||
* This handler gets called after the settings have been loaded in
|
||||
* full.
|
||||
*
|
||||
* @sa settings_handler::h_commit
|
||||
*
|
||||
* @param model Model this callback belongs to.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_commit)(struct bt_mesh_model *model);
|
||||
|
||||
/** @brief Model init callback.
|
||||
*
|
||||
* Called on every model instance during mesh initialization.
|
||||
*
|
||||
* @param model Model to be initialized.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const init)(struct bt_mesh_model *model);
|
||||
|
||||
/** @brief Model reset callback.
|
||||
*
|
||||
* Called when the mesh node is reset. All model data is deleted on
|
||||
* reset, and the model should clear its state.
|
||||
*
|
||||
* @param model Model this callback belongs to.
|
||||
*/
|
||||
void (*const reset)(struct bt_mesh_model *model);
|
||||
};
|
||||
|
||||
/** Abstraction that describes a Mesh Model instance */
|
||||
struct bt_mesh_model {
|
||||
union {
|
||||
|
@ -330,7 +484,7 @@ struct bt_mesh_model {
|
|||
/* Internal information, mainly for persistent storage */
|
||||
u8_t elem_idx; /* Belongs to Nth element */
|
||||
u8_t mod_idx; /* Is the Nth model in the element */
|
||||
u16_t flags; /* Information about what has changed */
|
||||
u16_t flags; /* Model flags for internal bookkeeping */
|
||||
|
||||
/* Model Publication */
|
||||
struct bt_mesh_model_pub * const pub;
|
||||
|
@ -343,6 +497,15 @@ struct bt_mesh_model {
|
|||
|
||||
const struct bt_mesh_model_op * const op;
|
||||
|
||||
/* Model callback structure. */
|
||||
const struct bt_mesh_model_cb * const cb;
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
/* Pointer to the next model in a model extension tree. */
|
||||
struct bt_mesh_model *next;
|
||||
/* Pointer to the first model this model extends. */
|
||||
struct bt_mesh_model *extends;
|
||||
#endif
|
||||
/* Model-specific user data */
|
||||
void *user_data;
|
||||
};
|
||||
|
@ -402,6 +565,76 @@ int bt_mesh_model_publish(struct bt_mesh_model *model);
|
|||
*/
|
||||
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
|
||||
|
||||
/** @brief Find a SIG model.
|
||||
*
|
||||
* @param elem Element to search for the model in.
|
||||
* @param id Model ID of the model.
|
||||
*
|
||||
* @return A pointer to the Mesh model matching the given parameters, or NULL
|
||||
* if no SIG model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id);
|
||||
|
||||
/** @brief Find a vendor model.
|
||||
*
|
||||
* @param elem Element to search for the model in.
|
||||
* @param company Company ID of the model.
|
||||
* @param id Model ID of the model.
|
||||
*
|
||||
* @return A pointer to the Mesh model matching the given parameters, or NULL
|
||||
* if no vendor model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id);
|
||||
|
||||
/** @brief Get whether the model is in the primary element of the device.
|
||||
*
|
||||
* @param mod Mesh model.
|
||||
*
|
||||
* @return true if the model is on the primary element, false otherwise.
|
||||
*/
|
||||
static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
|
||||
{
|
||||
return (mod->elem_idx == 0);
|
||||
}
|
||||
|
||||
/** @brief Immediately store the model's user data in persistent storage.
|
||||
*
|
||||
* @param mod Mesh model.
|
||||
* @param vnd This is a vendor model.
|
||||
* @param data Model data to store, or NULL to delete any model data.
|
||||
* @param data_len Length of the model data.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
|
||||
const void *data, size_t data_len);
|
||||
|
||||
/** @brief Let a model extend another.
|
||||
*
|
||||
* Mesh models may be extended to reuse their functionality, forming a more
|
||||
* complex model. A Mesh model may extend any number of models, in any element.
|
||||
* The extensions may also be nested, ie a model that extends another may itself
|
||||
* be extended. Extensions may not be cyclical, and a model can only be extended
|
||||
* by one other model.
|
||||
*
|
||||
* A set of models that extend each other form a model extension tree.
|
||||
*
|
||||
* All models in an extension tree share one subscription list per element. The
|
||||
* access layer will utilize the combined subscription list of all models in an
|
||||
* extension tree and element, giving the models extended subscription list
|
||||
* capacity.
|
||||
*
|
||||
* @param[in] mod Mesh model.
|
||||
* @param[in] base_mod The model being extended.
|
||||
*
|
||||
* @retval 0 Successfully extended the base_mod model.
|
||||
* @retval -EALREADY The base_mod model is already extended.
|
||||
*/
|
||||
int bt_mesh_model_extend(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_model *base_mod);
|
||||
|
||||
/** Node Composition */
|
||||
struct bt_mesh_comp {
|
||||
u16_t cid;
|
||||
|
|
|
@ -31,10 +31,11 @@ struct bt_mesh_cfg_cli {
|
|||
};
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
|
||||
|
||||
#define BT_MESH_MODEL_CFG_CLI(cli_data) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_CFG_CLI, \
|
||||
bt_mesh_cfg_cli_op, NULL, cli_data)
|
||||
#define BT_MESH_MODEL_CFG_CLI(cli_data) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
|
||||
cli_data, &bt_mesh_cfg_cli_cb)
|
||||
|
||||
int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
|
||||
u8_t *status, struct os_mbuf *comp);
|
||||
|
|
|
@ -61,10 +61,11 @@ struct bt_mesh_cfg_srv {
|
|||
};
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_CFG_SRV(srv_data) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_CFG_SRV, \
|
||||
bt_mesh_cfg_srv_op, NULL, srv_data)
|
||||
#define BT_MESH_MODEL_CFG_SRV(srv_data) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
|
||||
srv_data, &bt_mesh_cfg_srv_cb)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "logcfg/logcfg.h"
|
||||
#include "modlog/modlog.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
|
@ -179,13 +181,19 @@ extern "C" {
|
|||
#define BT_GAP_ADV_SLOW_INT_MIN 0x0640 /* 1 s */
|
||||
#define BT_GAP_ADV_SLOW_INT_MAX 0x0780 /* 1.2 s */
|
||||
|
||||
#define BT_DBG(fmt, ...) \
|
||||
if (BT_DBG_ENABLED) { \
|
||||
BLE_HS_LOG(DEBUG, "%s: " fmt "\n", __func__, ## __VA_ARGS__); \
|
||||
}
|
||||
#define BT_INFO(fmt, ...) BLE_HS_LOG(INFO, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_WARN(fmt, ...) BLE_HS_LOG(WARN, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_ERR(fmt, ...) BLE_HS_LOG(ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#ifndef MESH_LOG_MODULE
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
#endif
|
||||
|
||||
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
|
||||
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
|
||||
|
||||
#define BLE_MESH_LOG(lvl, ...) CAT(MESH_LOG_MODULE, CAT(_, lvl))(__VA_ARGS__)
|
||||
|
||||
#define BT_DBG(fmt, ...) BLE_MESH_LOG(DEBUG, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_INFO(fmt, ...) BLE_MESH_LOG(INFO, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_WARN(fmt, ...) BLE_MESH_LOG(WARN, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_ERR(fmt, ...) BLE_MESH_LOG(ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__);
|
||||
#define BT_GATT_ERR(_att_err) (-(_att_err))
|
||||
|
||||
typedef ble_addr_t bt_addr_le_t;
|
||||
|
@ -217,6 +225,20 @@ static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
|
|||
#define K_NO_WAIT (0)
|
||||
#define K_FOREVER (-1)
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
#define BT_MESH_ADV_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES))
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROXY)
|
||||
/* Note that BLE_MULTI_ADV_INSTANCES contains number of additional instances.
|
||||
* Instance 0 is always there
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) < 1
|
||||
#error "Mesh needs at least BLE_MULTI_ADV_INSTANCES set to 1"
|
||||
#endif
|
||||
#define BT_MESH_ADV_GATT_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) - 1)
|
||||
#endif /* BLE_MESH_PROXY */
|
||||
#endif /* BLE_EXT_ADV */
|
||||
|
||||
/* This is by purpose */
|
||||
static inline void net_buf_simple_init(struct os_mbuf *buf,
|
||||
size_t reserve_head)
|
||||
|
@ -260,6 +282,11 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
|||
#define net_buf_clone(a, b) os_mbuf_dup(a)
|
||||
#define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b)
|
||||
#define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b)
|
||||
#define net_buf_pull(a, b) net_buf_simple_pull(a, b)
|
||||
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
|
||||
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
|
||||
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
|
||||
#define net_buf_skip(a, b) net_buf_simple_pull_mem(a, b)
|
||||
|
||||
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
|
||||
|
||||
|
@ -370,9 +397,11 @@ static inline unsigned int find_msb_set(u32_t op)
|
|||
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
|
||||
#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
|
||||
#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
|
||||
#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
|
||||
#define CONFIG_BT_TESTING BLE_MESH_TESTING
|
||||
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
|
||||
|
||||
/* Above flags are used with IS_ENABLED macro */
|
||||
#define IS_ENABLED(config) MYNEWT_VAL(config)
|
||||
|
@ -394,6 +423,8 @@ static inline unsigned int find_msb_set(u32_t op)
|
|||
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
|
||||
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
|
||||
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
|
||||
|
||||
#define printk console_printf
|
||||
|
||||
|
@ -459,7 +490,8 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
|
|||
|
||||
#define settings_load conf_load
|
||||
int settings_bytes_from_str(char *val_str, void *vp, int *len);
|
||||
char *settings_str_from_bytes(void *vp, int vp_len, char *buf, int buf_len);
|
||||
char *settings_str_from_bytes(const void *vp, int vp_len,
|
||||
char *buf, int buf_len);
|
||||
|
||||
#define snprintk snprintf
|
||||
#define BT_SETTINGS_SIZE(in_size) ((((((in_size) - 1) / 3) * 4) + 4) + 1)
|
||||
|
|
|
@ -35,10 +35,11 @@ struct bt_mesh_health_cli {
|
|||
};
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_health_cli_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
|
||||
|
||||
#define BT_MESH_MODEL_HEALTH_CLI(cli_data) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_HEALTH_CLI, \
|
||||
bt_mesh_health_cli_op, NULL, cli_data)
|
||||
#define BT_MESH_MODEL_HEALTH_CLI(cli_data) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_op, \
|
||||
NULL, cli_data, &bt_mesh_health_cli_cb)
|
||||
|
||||
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ struct bt_mesh_health_srv {
|
|||
int bt_mesh_fault_update(struct bt_mesh_elem *elem);
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_health_srv_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_health_srv_cb;
|
||||
|
||||
/** @def BT_MESH_MODEL_HEALTH_SRV
|
||||
*
|
||||
|
@ -84,9 +85,9 @@ extern const struct bt_mesh_model_op bt_mesh_health_srv_op[];
|
|||
*
|
||||
* @return New mesh model instance.
|
||||
*/
|
||||
#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_HEALTH_SRV, \
|
||||
bt_mesh_health_srv_op, pub, srv)
|
||||
#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op, \
|
||||
pub, srv, &bt_mesh_health_srv_cb)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -128,6 +128,28 @@ struct bt_mesh_prov {
|
|||
*/
|
||||
int (*input)(bt_mesh_input_action_t act, u8_t size);
|
||||
|
||||
/** @brief The other device finished their OOB input.
|
||||
*
|
||||
* This callback notifies the application that it should stop
|
||||
* displaying its output OOB value, as the other party finished their
|
||||
* OOB input.
|
||||
*/
|
||||
void (*input_complete)(void);
|
||||
|
||||
/** @brief Unprovisioned beacon has been received.
|
||||
*
|
||||
* This callback notifies the application that an unprovisioned
|
||||
* beacon has been received.
|
||||
*
|
||||
* @param uuid UUID
|
||||
* @param oob_info OOB Information
|
||||
* @param uri_hash Pointer to URI Hash value. NULL if no hash was
|
||||
* present in the beacon.
|
||||
*/
|
||||
void (*unprovisioned_beacon)(u8_t uuid[16],
|
||||
bt_mesh_prov_oob_info_t oob_info,
|
||||
u32_t *uri_hash);
|
||||
|
||||
/** @brief Provisioning link has been opened.
|
||||
*
|
||||
* This callback notifies the application that a provisioning
|
||||
|
@ -157,6 +179,18 @@ struct bt_mesh_prov {
|
|||
*/
|
||||
void (*complete)(u16_t net_idx, u16_t addr);
|
||||
|
||||
/** @brief A new node has been added to the provisioning database.
|
||||
*
|
||||
* This callback notifies the application that provisioning has
|
||||
* been successfully completed, and that a node has been assigned
|
||||
* the specified NetKeyIndex and primary element address.
|
||||
*
|
||||
* @param net_idx NetKeyIndex given during provisioning.
|
||||
* @param addr Primary element address.
|
||||
* @param num_elem Number of elements that this node has.
|
||||
*/
|
||||
void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
|
||||
|
||||
/** @brief Node has been reset.
|
||||
*
|
||||
* This callback notifies the application that the local node
|
||||
|
@ -321,6 +355,19 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
|||
u8_t flags, u32_t iv_index, u16_t addr,
|
||||
const u8_t dev_key[16]);
|
||||
|
||||
/** @brief Provision a Mesh Node using PB-ADV
|
||||
*
|
||||
* @param uuid UUID
|
||||
* @param net_idx Network Key Index
|
||||
* @param addr Address to assign to remote device. If addr is 0, the lowest
|
||||
* available address will be chosen.
|
||||
* @param attention_duration The attention duration to be send to remote device
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration);
|
||||
|
||||
/** @brief Check if the local node has been provisioned.
|
||||
*
|
||||
* This API can be used to check if the local node has been provisioned
|
||||
|
|
|
@ -19,20 +19,19 @@ struct bt_mesh_gen_model_cli {
|
|||
void *op_param;
|
||||
};
|
||||
|
||||
extern struct bt_mesh_gen_model_cli gen_onoff_cli;
|
||||
extern const struct bt_mesh_model_op gen_onoff_cli_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_gen_onoff_cli_cb;
|
||||
|
||||
#define BT_MESH_MODEL_GEN_ONOFF_CLI() \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, \
|
||||
gen_onoff_cli_op, NULL, &gen_onoff_cli)
|
||||
#define BT_MESH_MODEL_GEN_ONOFF_CLI(cli_data, pub) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, pub,\
|
||||
cli_data, &bt_mesh_gen_onoff_cli_cb)
|
||||
|
||||
extern struct bt_mesh_gen_model_cli gen_level_cli;
|
||||
extern const struct bt_mesh_model_op gen_level_cli_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb;
|
||||
|
||||
#define BT_MESH_MODEL_GEN_LEVEL_CLI(pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, \
|
||||
gen_level_cli_op, NULL, &gen_level_cli)
|
||||
|
||||
#define BT_MESH_MODEL_GEN_LEVEL_CLI(cli_data, pub) \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\
|
||||
cli_data, &bt_mesh_gen_level_cli_cb)
|
||||
|
||||
int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *state);
|
||||
|
@ -42,7 +41,6 @@ int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
s16_t *level);
|
||||
int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t val, s16_t *state);
|
||||
int bt_mesh_gen_model_cli_init(struct bt_mesh_model *model, bool primary);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -11,43 +11,54 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bt_mesh_gen_onoff_srv_cb {
|
||||
struct bt_mesh_gen_onoff_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, u8_t *state);
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_onoff_srv_op[];
|
||||
extern const struct bt_mesh_model_cb gen_onoff_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_GEN_ONOFF_SRV(srv, pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, \
|
||||
gen_onoff_srv_op, pub, srv)
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, \
|
||||
gen_onoff_srv_op, pub, srv, &gen_onoff_srv_cb)
|
||||
|
||||
struct bt_mesh_gen_level_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct bt_mesh_gen_level_srv_cb {
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_level_srv_op[];
|
||||
extern const struct bt_mesh_model_cb gen_level_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_GEN_LEVEL_SRV(srv, pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, \
|
||||
gen_level_srv_op, pub, srv)
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, \
|
||||
gen_level_srv_op, pub, srv, &gen_level_srv_cb)
|
||||
|
||||
struct bt_mesh_light_lightness_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct bt_mesh_light_lightness_srv_cb {
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op light_lightness_srv_op[];
|
||||
extern const struct bt_mesh_model_cb light_lightness_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(srv, pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
|
||||
light_lightness_srv_op, pub, srv)
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
|
||||
light_lightness_srv_op, pub, srv, &light_lightness_srv_cb)
|
||||
|
||||
|
||||
void bt_mesh_set_gen_onoff_srv_cb(struct bt_mesh_gen_onoff_srv_cb *gen_onoff_cb);
|
||||
void bt_mesh_set_gen_level_srv_cb(struct bt_mesh_gen_level_srv_cb *gen_level_cb);
|
||||
void bt_mesh_set_light_lightness_srv_cb(struct bt_mesh_light_lightness_srv_cb *light_lightness_cb);
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state));
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -73,13 +73,19 @@ struct ble_mbuf_hdr_rxinfo
|
|||
/* XXX: we could just use single phy_mode field */
|
||||
int8_t phy;
|
||||
uint8_t phy_mode;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
int8_t rpa_index;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void *user_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Flag definitions for rxinfo */
|
||||
#define BLE_MBUF_HDR_F_IGNORED (0x8000)
|
||||
#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000)
|
||||
#define BLE_MBUF_HDR_F_INITA_RESOLVED (0x2000)
|
||||
#define BLE_MBUF_HDR_F_TARGETA_RESOLVED (0x2000)
|
||||
#define BLE_MBUF_HDR_F_EXT_ADV_SEC (0x1000)
|
||||
#define BLE_MBUF_HDR_F_EXT_ADV (0x0800)
|
||||
#define BLE_MBUF_HDR_F_RESOLVED (0x0400)
|
||||
|
@ -89,7 +95,7 @@ struct ble_mbuf_hdr_rxinfo
|
|||
#define BLE_MBUF_HDR_F_DEVMATCH (0x0040)
|
||||
#define BLE_MBUF_HDR_F_MIC_FAILURE (0x0020)
|
||||
#define BLE_MBUF_HDR_F_SCAN_RSP_TXD (0x0010)
|
||||
#define BLE_MBUF_HDR_F_SCAN_RSP_CHK (0x0008)
|
||||
#define BLE_MBUF_HDR_F_SCAN_RSP_RXD (0x0008)
|
||||
#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x0007)
|
||||
|
||||
/* Transmit info. NOTE: no flags defined */
|
||||
|
@ -111,6 +117,12 @@ struct ble_mbuf_hdr
|
|||
uint32_t rem_usecs;
|
||||
};
|
||||
|
||||
#define BLE_MBUF_HDR_IGNORED(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_IGNORED))
|
||||
|
||||
#define BLE_MBUF_HDR_SCAN_REQ_TXD(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD))
|
||||
|
||||
#define BLE_MBUF_HDR_EXT_ADV_SEC(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV_SEC))
|
||||
|
||||
|
@ -120,8 +132,8 @@ struct ble_mbuf_hdr
|
|||
#define BLE_MBUF_HDR_DEVMATCH(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH))
|
||||
|
||||
#define BLE_MBUF_HDR_SCAN_RSP_RCV(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_CHK))
|
||||
#define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD))
|
||||
|
||||
#define BLE_MBUF_HDR_AUX_INVALID(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID))
|
||||
|
@ -141,6 +153,9 @@ struct ble_mbuf_hdr
|
|||
#define BLE_MBUF_HDR_INITA_RESOLVED(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_INITA_RESOLVED))
|
||||
|
||||
#define BLE_MBUF_HDR_TARGETA_RESOLVED(hdr) \
|
||||
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED))
|
||||
|
||||
#define BLE_MBUF_HDR_RX_STATE(hdr) \
|
||||
((uint8_t)((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK))
|
||||
|
||||
|
@ -235,11 +250,10 @@ enum ble_error_codes
|
|||
BLE_ERR_UNK_ADV_INDENT = 0x42,
|
||||
BLE_ERR_LIMIT_REACHED = 0x43,
|
||||
BLE_ERR_OPERATION_CANCELLED = 0x44,
|
||||
BLE_ERR_PACKET_TOO_LONG = 0x45,
|
||||
BLE_ERR_MAX = 0xff
|
||||
};
|
||||
|
||||
int ble_err_from_os(int os_err);
|
||||
|
||||
/* HW error codes */
|
||||
#define BLE_HW_ERR_DO_NOT_USE (0) /* XXX: reserve this one for now */
|
||||
#define BLE_HW_ERR_HCI_SYNC_LOSS (1)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,14 +6,13 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <os/os_mbuf.h>
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_ACCESS))
|
||||
#include "host/ble_hs_log.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG
|
||||
|
||||
#include <errno.h>
|
||||
#include <os/os_mbuf.h>
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
|
@ -29,24 +28,6 @@
|
|||
static const struct bt_mesh_comp *dev_comp;
|
||||
static u16_t dev_primary_addr;
|
||||
|
||||
static const struct {
|
||||
const u16_t id;
|
||||
int (*const init)(struct bt_mesh_model *model, bool primary);
|
||||
} model_init[] = {
|
||||
{ BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_init },
|
||||
{ BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_init },
|
||||
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
|
||||
{ BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_init },
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
|
||||
{ BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_init },
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
|
||||
{ BT_MESH_MODEL_ID_GEN_ONOFF_CLI, bt_mesh_gen_model_cli_init },
|
||||
{ BT_MESH_MODEL_ID_GEN_LEVEL_CLI, bt_mesh_gen_model_cli_init },
|
||||
#endif
|
||||
};
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary,
|
||||
|
@ -101,7 +82,11 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
|||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
return period >> mod->pub->period_div;
|
||||
if (mod->pub->fast_period) {
|
||||
return period >> mod->pub->period_div;
|
||||
} else {
|
||||
return period;
|
||||
}
|
||||
}
|
||||
|
||||
static s32_t next_period(struct bt_mesh_model *mod)
|
||||
|
@ -146,7 +131,24 @@ static void publish_sent(int err, void *user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static void publish_start(u16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
|
||||
if (err) {
|
||||
BT_ERR("Failed to publish: err %d", err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the timestamp for the beginning of a new period */
|
||||
if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) {
|
||||
pub->period_start = k_uptime_get_32();
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bt_mesh_send_cb pub_sent_cb = {
|
||||
.start = publish_start,
|
||||
.end = publish_sent,
|
||||
};
|
||||
|
||||
|
@ -223,8 +225,6 @@ static void mod_publish(struct ble_npl_event *work)
|
|||
|
||||
__ASSERT_NO_MSG(pub->update != NULL);
|
||||
|
||||
pub->period_start = k_uptime_get_32();
|
||||
|
||||
err = pub->update(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to update publication message");
|
||||
|
@ -235,11 +235,6 @@ static void mod_publish(struct ble_npl_event *work)
|
|||
if (err) {
|
||||
BT_ERR("Publishing failed (err %d)", err);
|
||||
}
|
||||
|
||||
if (pub->count) {
|
||||
/* Retransmissions also control the timer */
|
||||
k_delayed_work_cancel(&pub->timer);
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
|
||||
|
@ -297,14 +292,8 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
|||
mod->mod_idx = mod - elem->models;
|
||||
}
|
||||
|
||||
if (vnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(model_init); i++) {
|
||||
if (model_init[i].id == mod->id) {
|
||||
model_init[i].init(mod, primary);
|
||||
}
|
||||
if (mod->cb && mod->cb->init) {
|
||||
mod->cb->init(mod);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,7 +343,7 @@ u16_t bt_mesh_primary_addr(void)
|
|||
return dev_primary_addr;
|
||||
}
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr)
|
||||
static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -367,6 +356,45 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct find_group_visitor_ctx {
|
||||
u16_t *entry;
|
||||
struct bt_mesh_model *mod;
|
||||
u16_t addr;
|
||||
};
|
||||
|
||||
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
|
||||
u32_t depth, void *user_data)
|
||||
{
|
||||
struct find_group_visitor_ctx *ctx = user_data;
|
||||
|
||||
if (mod->elem_idx != ctx->mod->elem_idx) {
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
ctx->entry = model_group_get(mod, ctx->addr);
|
||||
if (ctx->entry) {
|
||||
ctx->mod = mod;
|
||||
return BT_MESH_WALK_STOP;
|
||||
}
|
||||
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
|
||||
{
|
||||
struct find_group_visitor_ctx ctx = {
|
||||
.mod = *mod,
|
||||
.entry = NULL,
|
||||
.addr = addr,
|
||||
};
|
||||
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(*mod),
|
||||
find_group_mod_visitor, &ctx);
|
||||
|
||||
*mod = ctx.mod;
|
||||
return ctx.entry;
|
||||
}
|
||||
|
||||
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
u16_t group_addr)
|
||||
{
|
||||
|
@ -377,7 +405,7 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
|||
for (i = 0; i < elem->model_count; i++) {
|
||||
model = &elem->models[i];
|
||||
|
||||
match = bt_mesh_model_find_group(model, group_addr);
|
||||
match = model_group_get(model, group_addr);
|
||||
if (match) {
|
||||
return model;
|
||||
}
|
||||
|
@ -386,7 +414,7 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
|||
for (i = 0; i < elem->vnd_model_count; i++) {
|
||||
model = &elem->vnd_models[i];
|
||||
|
||||
match = bt_mesh_model_find_group(model, group_addr);
|
||||
match = model_group_get(model, group_addr);
|
||||
if (match) {
|
||||
return model;
|
||||
}
|
||||
|
@ -397,17 +425,21 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
|||
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
{
|
||||
int i;
|
||||
u16_t index;
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
index = (addr - dev_comp->elem[0].addr);
|
||||
if (index < dev_comp->elem_count) {
|
||||
return &dev_comp->elem[index];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (BT_MESH_ADDR_IS_GROUP(addr) ||
|
||||
BT_MESH_ADDR_IS_VIRTUAL(addr)) {
|
||||
if (bt_mesh_elem_find_group(elem, addr)) {
|
||||
return elem;
|
||||
}
|
||||
} else if (elem->addr == addr) {
|
||||
for (index = 0; index < dev_comp->elem_count; index++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[index];
|
||||
|
||||
if (bt_mesh_elem_find_group(elem, addr)) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +457,9 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
|
||||
if (mod->keys[i] == key) {
|
||||
if (mod->keys[i] == key ||
|
||||
(mod->keys[i] == BT_MESH_KEY_DEV_ANY &&
|
||||
BT_MESH_IS_DEV_KEY(key))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -433,9 +467,19 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
|
||||
{
|
||||
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
|
||||
return (dev_comp->elem[mod->elem_idx].addr == dst);
|
||||
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
|
||||
return bt_mesh_model_find_group(&mod, dst);
|
||||
}
|
||||
|
||||
return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
|
||||
}
|
||||
|
||||
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
u8_t model_count, u16_t dst,
|
||||
u16_t app_idx, u32_t opcode,
|
||||
u8_t model_count, u32_t opcode,
|
||||
struct bt_mesh_model **model)
|
||||
{
|
||||
u8_t i;
|
||||
|
@ -445,17 +489,6 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
|||
|
||||
*model = &models[i];
|
||||
|
||||
if (BT_MESH_ADDR_IS_GROUP(dst) ||
|
||||
BT_MESH_ADDR_IS_VIRTUAL(dst)) {
|
||||
if (!bt_mesh_model_find_group(*model, dst)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!model_has_key(*model, app_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (op = (*model)->op; op->func; op++) {
|
||||
if (op->opcode == opcode) {
|
||||
return op;
|
||||
|
@ -508,8 +541,7 @@ bool bt_mesh_fixed_group_match(u16_t addr)
|
|||
case BT_MESH_ADDR_ALL_NODES:
|
||||
return true;
|
||||
case BT_MESH_ADDR_PROXIES:
|
||||
/* TODO: Proxy not yet supported */
|
||||
return false;
|
||||
return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
|
||||
case BT_MESH_ADDR_FRIENDS:
|
||||
return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
|
||||
case BT_MESH_ADDR_RELAYS:
|
||||
|
@ -540,24 +572,13 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
|||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
|
||||
if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
|
||||
if (elem->addr != rx->ctx.recv_dst) {
|
||||
continue;
|
||||
}
|
||||
} else if (BT_MESH_ADDR_IS_GROUP(rx->ctx.recv_dst) ||
|
||||
BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
|
||||
/* find_op() will do proper model/group matching */
|
||||
} else if (i != 0 ||
|
||||
!bt_mesh_fixed_group_match(rx->ctx.recv_dst)) {
|
||||
continue;
|
||||
}
|
||||
struct net_buf_simple_state state;
|
||||
|
||||
/* SIG models cannot contain 3-byte (vendor) OpCodes, and
|
||||
* vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
|
||||
* we only need to do the lookup in one of the model lists.
|
||||
*/
|
||||
if (opcode < 0x10000) {
|
||||
if (BT_MESH_MODEL_OP_LEN(opcode) < 3) {
|
||||
models = elem->models;
|
||||
count = elem->model_count;
|
||||
} else {
|
||||
|
@ -565,29 +586,32 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
|||
count = elem->vnd_model_count;
|
||||
}
|
||||
|
||||
op = find_op(models, count, rx->ctx.recv_dst, rx->ctx.app_idx,
|
||||
opcode, &model);
|
||||
if (op) {
|
||||
struct net_buf_simple_state state;
|
||||
op = find_op(models, count, opcode, &model);
|
||||
if (!op) {
|
||||
BT_DBG("No OpCode 0x%08x for elem %d", opcode, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf->om_len < op->min_len) {
|
||||
BT_ERR("Too short message for OpCode 0x%08x",
|
||||
(unsigned) opcode);
|
||||
if (!model_has_key(model, rx->ctx.app_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The callback will likely parse the buffer, so
|
||||
* store the parsing state in case multiple models
|
||||
* receive the message.
|
||||
*/
|
||||
net_buf_simple_save(buf, &state);
|
||||
op->func(model, &rx->ctx, buf);
|
||||
net_buf_simple_restore(buf, &state);
|
||||
|
||||
} else {
|
||||
BT_DBG("No OpCode 0x%08x for elem %d",
|
||||
(unsigned) opcode, i);
|
||||
if (!model_has_dst(model, rx->ctx.recv_dst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf->om_len < op->min_len) {
|
||||
BT_ERR("Too short message for OpCode 0x%08x", opcode);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The callback will likely parse the buffer, so
|
||||
* store the parsing state in case multiple models
|
||||
* receive the message.
|
||||
*/
|
||||
net_buf_simple_save(buf, &state);
|
||||
op->func(model, &rx->ctx, buf);
|
||||
net_buf_simple_restore(buf, &state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -595,21 +619,21 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
|
|||
{
|
||||
net_buf_simple_init(msg, 0);
|
||||
|
||||
if (opcode < 0x100) {
|
||||
/* 1-byte OpCode */
|
||||
switch (BT_MESH_MODEL_OP_LEN(opcode)) {
|
||||
case 1:
|
||||
net_buf_simple_add_u8(msg, opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode < 0x10000) {
|
||||
/* 2-byte OpCode */
|
||||
break;
|
||||
case 2:
|
||||
net_buf_simple_add_be16(msg, opcode);
|
||||
return;
|
||||
break;
|
||||
case 3:
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
break;
|
||||
default:
|
||||
BT_WARN("Unknown opcode format");
|
||||
break;
|
||||
}
|
||||
|
||||
/* 3-byte OpCode */
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
}
|
||||
|
||||
static int model_send(struct bt_mesh_model *model,
|
||||
|
@ -732,7 +756,7 @@ done:
|
|||
return err;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
|
@ -747,7 +771,7 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem,
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
|
@ -765,3 +789,68 @@ const struct bt_mesh_comp *bt_mesh_comp_get(void)
|
|||
{
|
||||
return dev_comp;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
|
||||
{
|
||||
#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
|
||||
while (mod->next) {
|
||||
mod = mod->next;
|
||||
}
|
||||
#endif
|
||||
return mod;
|
||||
}
|
||||
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *m = root;
|
||||
u32_t depth = 0;
|
||||
|
||||
do {
|
||||
if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
|
||||
return;
|
||||
}
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
if (m->extends) {
|
||||
m = m->extends;
|
||||
depth++;
|
||||
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
|
||||
m = m->next->next;
|
||||
depth--;
|
||||
} else {
|
||||
m = m->next;
|
||||
}
|
||||
#endif
|
||||
} while (m && m != root);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
int bt_mesh_model_extend(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_model *base_mod)
|
||||
{
|
||||
/* Form a cyclical LCRS tree:
|
||||
* The extends-pointer points to the first child, and the next-pointer
|
||||
* points to the next sibling. The last sibling is marked by the
|
||||
* BT_MESH_MOD_NEXT_IS_PARENT flag, and its next-pointer points back to
|
||||
* the parent. This way, the whole tree is accessible from any node.
|
||||
*
|
||||
* We add children (extend them) by inserting them as the first child.
|
||||
*/
|
||||
if (base_mod->next) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (mod->extends) {
|
||||
base_mod->next = mod->extends;
|
||||
} else {
|
||||
base_mod->next = mod;
|
||||
base_mod->flags |= BT_MESH_MOD_NEXT_IS_PARENT;
|
||||
}
|
||||
|
||||
mod->extends = base_mod;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,14 @@ enum {
|
|||
BT_MESH_MOD_BIND_PENDING = BIT(0),
|
||||
BT_MESH_MOD_SUB_PENDING = BIT(1),
|
||||
BT_MESH_MOD_PUB_PENDING = BIT(2),
|
||||
BT_MESH_MOD_DATA_PRESENT = BIT(3),
|
||||
BT_MESH_MOD_NEXT_IS_PARENT = BIT(4),
|
||||
};
|
||||
|
||||
/* Tree walk return codes */
|
||||
enum bt_mesh_walk {
|
||||
BT_MESH_WALK_STOP,
|
||||
BT_MESH_WALK_CONTINUE,
|
||||
};
|
||||
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
|
||||
|
@ -25,12 +33,14 @@ u8_t bt_mesh_elem_count(void);
|
|||
/* Find local element based on unicast or group address */
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id);
|
||||
struct bt_mesh_model * bt_mesh_model_find(struct bt_mesh_elem *elem,
|
||||
u16_t id);
|
||||
struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr);
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr);
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr);
|
||||
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_ADV))
|
||||
#include "host/ble_hs_log.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_ADV_LOG
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "host/ble_hs_adv.h"
|
||||
#include "host/ble_gap.h"
|
||||
#include "nimble/hci_common.h"
|
||||
|
@ -108,9 +106,14 @@ static inline void adv_send(struct os_mbuf *buf)
|
|||
|
||||
adv_int = max(adv_int_min,
|
||||
BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit));
|
||||
#if MYNEWT_VAL(BLE_CONTROLLER)
|
||||
duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) *
|
||||
(adv_int + 10));
|
||||
#else
|
||||
duration = (MESH_SCAN_WINDOW_MS +
|
||||
((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) *
|
||||
(adv_int + 10)));
|
||||
#endif
|
||||
|
||||
BT_DBG("type %u om_len %u: %s", BT_MESH_ADV(buf)->type,
|
||||
buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
@ -188,6 +191,8 @@ mesh_adv_thread(void *args)
|
|||
if (BT_MESH_ADV(buf)->busy) {
|
||||
BT_MESH_ADV(buf)->busy = 0;
|
||||
adv_send(buf);
|
||||
} else {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
/* os_sched(NULL); */
|
||||
|
@ -395,6 +400,8 @@ done:
|
|||
|
||||
int bt_mesh_scan_enable(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
struct ble_gap_ext_disc_params uncoded_params =
|
||||
{ .itvl = MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW,
|
||||
|
@ -402,7 +409,7 @@ int bt_mesh_scan_enable(void)
|
|||
|
||||
BT_DBG("");
|
||||
|
||||
return ble_gap_ext_disc(g_mesh_addr_type, 0, 0, 0, 0, 0,
|
||||
err = ble_gap_ext_disc(g_mesh_addr_type, 0, 0, 0, 0, 0,
|
||||
&uncoded_params, NULL, NULL, NULL);
|
||||
#else
|
||||
struct ble_gap_disc_params scan_param =
|
||||
|
@ -411,13 +418,28 @@ int bt_mesh_scan_enable(void)
|
|||
|
||||
BT_DBG("");
|
||||
|
||||
return ble_gap_disc(g_mesh_addr_type, BLE_HS_FOREVER, &scan_param, NULL, NULL);
|
||||
err = ble_gap_disc(g_mesh_addr_type, BLE_HS_FOREVER, &scan_param,
|
||||
NULL, NULL);
|
||||
#endif
|
||||
if (err && err != BLE_HS_EALREADY) {
|
||||
BT_ERR("starting scan failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_scan_disable(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
return ble_gap_disc_cancel();
|
||||
err = ble_gap_disc_cancel();
|
||||
if (err && err != BLE_HS_EALREADY) {
|
||||
BT_ERR("stopping scan failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,15 +42,12 @@ struct bt_mesh_adv {
|
|||
busy:1;
|
||||
u8_t xmit;
|
||||
|
||||
union {
|
||||
/* Address, used e.g. for Friend Queue messages */
|
||||
u16_t addr;
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
};
|
||||
u8_t flags;
|
||||
|
||||
int ref_cnt;
|
||||
struct ble_npl_event ev;
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_BEACON_LOG
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "os/os_mbuf.h"
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_BEACON))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "adv.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
|
@ -147,7 +146,6 @@ static int secure_beacon_send(void)
|
|||
|
||||
static int unprovisioned_beacon_send(void)
|
||||
{
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
const struct bt_mesh_prov *prov;
|
||||
u8_t uri_hash[16] = { 0 };
|
||||
struct os_mbuf *buf;
|
||||
|
@ -199,10 +197,43 @@ static int unprovisioned_beacon_send(void)
|
|||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unprovisioned_beacon_recv(struct os_mbuf *buf)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_ADV)
|
||||
const struct bt_mesh_prov *prov;
|
||||
u8_t *uuid;
|
||||
u16_t oob_info;
|
||||
u32_t uri_hash_val;
|
||||
u32_t *uri_hash = NULL;
|
||||
|
||||
if (buf->om_len != 18 && buf->om_len != 22) {
|
||||
BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len);
|
||||
return;
|
||||
}
|
||||
|
||||
uuid = net_buf_simple_pull_mem(buf, 16);
|
||||
oob_info = net_buf_simple_pull_be16(buf);
|
||||
|
||||
if (buf->om_len == 4) {
|
||||
uri_hash_val = net_buf_simple_pull_be32(buf);
|
||||
uri_hash = &uri_hash_val;
|
||||
}
|
||||
|
||||
BT_DBG("uuid %s", bt_hex(uuid, 16));
|
||||
|
||||
prov = bt_mesh_prov_get();
|
||||
|
||||
if (prov->unprovisioned_beacon) {
|
||||
prov->unprovisioned_beacon(uuid,
|
||||
(bt_mesh_prov_oob_info_t)oob_info,
|
||||
uri_hash);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void update_beacon_observation(void)
|
||||
{
|
||||
static bool first_half;
|
||||
|
@ -249,11 +280,10 @@ static void beacon_send(struct ble_npl_event *work)
|
|||
k_delayed_work_submit(&beacon_timer,
|
||||
PROVISIONED_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
} else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
|
||||
unprovisioned_beacon_send();
|
||||
k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void secure_beacon_recv(struct os_mbuf *buf)
|
||||
|
@ -351,7 +381,7 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
|
|||
type = net_buf_simple_pull_u8(buf);
|
||||
switch (type) {
|
||||
case BEACON_TYPE_UNPROVISIONED:
|
||||
BT_DBG("Ignoring unprovisioned device beacon");
|
||||
unprovisioned_beacon_recv(buf);
|
||||
break;
|
||||
case BEACON_TYPE_SECURE:
|
||||
secure_beacon_recv(buf);
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include <string.h>
|
||||
|
@ -21,6 +21,9 @@
|
|||
|
||||
#define CID_NVAL 0xffff
|
||||
|
||||
/* 2 byte dummy opcode for getting compile time buffer sizes. */
|
||||
#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff)
|
||||
|
||||
struct comp_data {
|
||||
u8_t *status;
|
||||
struct os_mbuf *comp;
|
||||
|
@ -481,6 +484,38 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
|
|||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int cfg_cli_init(struct bt_mesh_model *model)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
if (!bt_mesh_model_in_primary(model)) {
|
||||
BT_ERR("Configuration Client only allowed in primary element");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!model->user_data) {
|
||||
BT_ERR("No Configuration Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cli = model->user_data;
|
||||
cli->model = model;
|
||||
|
||||
/*
|
||||
* Configuration Model security is device-key based and both the local
|
||||
* and remote keys are allowed to access this model.
|
||||
*/
|
||||
model->keys[0] = BT_MESH_KEY_DEV_ANY;
|
||||
|
||||
k_sem_init(&cli->op_sync, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = {
|
||||
.init = cfg_cli_init,
|
||||
};
|
||||
|
||||
static int cli_prepare(void *param, u32_t op)
|
||||
{
|
||||
if (!cli) {
|
||||
|
@ -519,10 +554,10 @@ static int cli_wait(void)
|
|||
int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
|
||||
u8_t *status, struct os_mbuf *comp)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -556,10 +591,10 @@ done:
|
|||
static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
|
||||
u8_t *val)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -588,10 +623,10 @@ done:
|
|||
static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
|
||||
u8_t new_val, u8_t *val)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -670,10 +705,10 @@ int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
|
|||
int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
|
||||
u8_t *transmit)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -706,10 +741,10 @@ done:
|
|||
int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
|
||||
u8_t new_transmit, u8_t *status, u8_t *transmit)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_SET, 2);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -744,10 +779,10 @@ done:
|
|||
int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
||||
const u8_t net_key[16], u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 18 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_ADD, 18);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -788,10 +823,10 @@ int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
|||
u16_t key_app_idx, const u8_t app_key[16],
|
||||
u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(1 + 19 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_ADD, 19);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -833,10 +868,10 @@ static int mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
|
||||
u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 8 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_BIND, 8);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -904,10 +939,10 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u16_t cid, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 8 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 8);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1014,10 +1049,10 @@ static int mod_sub_va(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
const u8_t label[16], u16_t mod_id, u16_t cid,
|
||||
u16_t *virt_addr, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 22 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 22);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1133,10 +1168,10 @@ static int mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 6 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_GET, 6);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1205,10 +1240,10 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 13 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_SET, 13);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1230,7 +1265,7 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
|
||||
net_buf_simple_add_le16(msg, elem_addr);
|
||||
net_buf_simple_add_le16(msg, pub->addr);
|
||||
net_buf_simple_add_le16(msg, (pub->app_idx & (pub->cred_flag << 12)));
|
||||
net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12)));
|
||||
net_buf_simple_add_u8(msg, pub->ttl);
|
||||
net_buf_simple_add_u8(msg, pub->period);
|
||||
net_buf_simple_add_u8(msg, pub->transmit);
|
||||
|
@ -1281,10 +1316,10 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
|||
int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_SET, 5);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1325,10 +1360,10 @@ done:
|
|||
int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1366,10 +1401,10 @@ done:
|
|||
int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
|
||||
const struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_SET, 9);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
.app_idx = BT_MESH_KEY_DEV_REMOTE,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
|
@ -1412,7 +1447,7 @@ done:
|
|||
int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = BT_MESH_KEY_DEV,
|
||||
|
@ -1460,29 +1495,4 @@ void bt_mesh_cfg_cli_timeout_set(s32_t timeout)
|
|||
msg_timeout = timeout;
|
||||
}
|
||||
|
||||
int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary)
|
||||
{
|
||||
BT_DBG("primary %u", primary);
|
||||
|
||||
if (!primary) {
|
||||
BT_ERR("Configuration Client only allowed in primary element");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!model->user_data) {
|
||||
BT_ERR("No Configuration Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cli = model->user_data;
|
||||
cli->model = model;
|
||||
|
||||
/* Configuration Model security is device-key based */
|
||||
model->keys[0] = BT_MESH_KEY_DEV;
|
||||
|
||||
k_sem_init(&cli->op_sync, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,16 +6,15 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_MODEL)
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
|
@ -34,61 +33,7 @@
|
|||
|
||||
static struct bt_mesh_cfg_srv *conf;
|
||||
|
||||
static struct label {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
} labels[MYNEWT_VAL(BLE_MESH_LABEL_COUNT)];
|
||||
|
||||
static void hb_send(struct bt_mesh_model *model)
|
||||
{
|
||||
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
u16_t feat = 0;
|
||||
struct __packed {
|
||||
u8_t init_ttl;
|
||||
u16_t feat;
|
||||
} hb;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = cfg->hb_pub.net_idx,
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = cfg->hb_pub.dst,
|
||||
.send_ttl = cfg->hb_pub.ttl,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_model_elem(model)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
|
||||
hb.init_ttl = cfg->hb_pub.ttl;
|
||||
|
||||
if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_RELAY;
|
||||
}
|
||||
|
||||
if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_PROXY;
|
||||
}
|
||||
|
||||
if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
|
||||
feat |= BT_MESH_FEAT_FRIEND;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
|
||||
if (bt_mesh.lpn.state != BT_MESH_LPN_DISABLED) {
|
||||
feat |= BT_MESH_FEAT_LOW_POWER;
|
||||
}
|
||||
#endif
|
||||
|
||||
hb.feat = sys_cpu_to_be16(feat);
|
||||
|
||||
BT_DBG("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
|
||||
|
||||
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
static struct label labels[CONFIG_BT_MESH_LABEL_COUNT];
|
||||
|
||||
static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
|
||||
bool primary)
|
||||
|
@ -175,9 +120,9 @@ static void dev_comp_data_get(struct bt_mesh_model *model,
|
|||
bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
page = net_buf_simple_pull_u8(buf);
|
||||
if (page != 0) {
|
||||
BT_WARN("Composition page %u not available", page);
|
||||
page = 0;
|
||||
if (page != 0U) {
|
||||
BT_DBG("Composition page %u not available", page);
|
||||
page = 0U;
|
||||
}
|
||||
|
||||
bt_mesh_model_msg_init(sdu, OP_DEV_COMP_DATA_STATUS);
|
||||
|
@ -481,7 +426,7 @@ static void app_key_add(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
|
||||
u16_t key_net_idx, key_app_idx;
|
||||
u8_t status;
|
||||
|
||||
|
@ -508,7 +453,7 @@ static void app_key_update(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
|
||||
u16_t key_net_idx, key_app_idx;
|
||||
u8_t status;
|
||||
|
||||
|
@ -564,7 +509,7 @@ static void app_key_del(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
|
||||
u16_t key_net_idx, key_app_idx;
|
||||
struct bt_mesh_app_key *key;
|
||||
u8_t status;
|
||||
|
@ -617,8 +562,8 @@ static void app_key_get(struct bt_mesh_model *model,
|
|||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg =
|
||||
NET_BUF_SIMPLE(2 + 3 + 4 +
|
||||
IDX_LEN(MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)));
|
||||
BT_MESH_MODEL_BUF(OP_APP_KEY_LIST,
|
||||
3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
|
||||
u16_t get_idx, i, prev;
|
||||
u8_t status;
|
||||
|
||||
|
@ -679,8 +624,7 @@ static void beacon_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1);
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -699,8 +643,7 @@ static void beacon_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
|
@ -744,8 +687,7 @@ static void default_ttl_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1);
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -766,8 +708,7 @@ static void default_ttl_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
|
@ -803,8 +744,7 @@ done:
|
|||
static void send_gatt_proxy_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_GATT_PROXY_STATUS, 1);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_GATT_PROXY_STATUS);
|
||||
net_buf_simple_add_u8(msg, bt_mesh_gatt_proxy_get());
|
||||
|
@ -833,7 +773,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
|
|||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -866,33 +805,10 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
|
|||
bt_mesh_store_cfg();
|
||||
}
|
||||
|
||||
if (cfg->gatt_proxy == BT_MESH_GATT_PROXY_DISABLED) {
|
||||
int i;
|
||||
|
||||
/* Section 4.2.11.1: "When the GATT Proxy state is set to
|
||||
* 0x00, the Node Identity state for all subnets shall be set
|
||||
* to 0x00 and shall not be changed."
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx != BT_MESH_KEY_UNUSED) {
|
||||
bt_mesh_proxy_identity_stop(sub);
|
||||
}
|
||||
}
|
||||
|
||||
/* Section 4.2.11: "Upon transition from GATT Proxy state 0x01
|
||||
* to GATT Proxy state 0x00 the GATT Bearer Server shall
|
||||
* disconnect all GATT Bearer Clients.
|
||||
*/
|
||||
bt_mesh_proxy_gatt_disconnect();
|
||||
}
|
||||
|
||||
bt_mesh_adv_update();
|
||||
|
||||
sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
|
||||
if ((cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) && sub) {
|
||||
hb_send(model);
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
|
||||
send_status:
|
||||
|
@ -903,8 +819,7 @@ static void net_transmit_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1);
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -925,8 +840,7 @@ static void net_transmit_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
|
@ -961,8 +875,7 @@ static void relay_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2);
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -984,8 +897,7 @@ static void relay_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
|
@ -995,7 +907,6 @@ static void relay_set(struct bt_mesh_model *model,
|
|||
if (!cfg) {
|
||||
BT_WARN("No Configuration Server context available");
|
||||
} else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
|
||||
struct bt_mesh_subnet *sub;
|
||||
bool change;
|
||||
|
||||
if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
|
||||
|
@ -1016,9 +927,8 @@ static void relay_set(struct bt_mesh_model *model,
|
|||
BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
|
||||
BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
|
||||
|
||||
sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
|
||||
if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && sub && change) {
|
||||
hb_send(model);
|
||||
if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
} else {
|
||||
BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]);
|
||||
|
@ -1044,8 +954,7 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
|
|||
bool vnd, struct bt_mesh_model *mod,
|
||||
u8_t status, u8_t *mod_id)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 14 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_MOD_PUB_STATUS);
|
||||
|
||||
|
@ -1188,25 +1097,61 @@ send_status:
|
|||
status, mod_id);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0
|
||||
static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
||||
struct label *get_label(u16_t index)
|
||||
{
|
||||
struct label *free_slot = NULL;
|
||||
if (index >= ARRAY_SIZE(labels)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &labels[index];
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
static inline void va_store(struct label *store)
|
||||
{
|
||||
atomic_set_bit(store->flags, BT_MESH_VA_CHANGED);
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_label();
|
||||
}
|
||||
}
|
||||
|
||||
static struct label *va_find(const u8_t *label_uuid,
|
||||
struct label **free_slot)
|
||||
{
|
||||
struct label *match = NULL;
|
||||
int i;
|
||||
|
||||
if (free_slot != NULL) {
|
||||
*free_slot = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(labels); i++) {
|
||||
if (!labels[i].ref) {
|
||||
free_slot = &labels[i];
|
||||
if (labels[i].ref == 0) {
|
||||
if (free_slot != NULL) {
|
||||
*free_slot = &labels[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
|
||||
*addr = labels[i].addr;
|
||||
labels[i].ref++;
|
||||
return STATUS_SUCCESS;
|
||||
match = &labels[i];
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
||||
{
|
||||
struct label *update, *free_slot = NULL;
|
||||
|
||||
update = va_find(label_uuid, &free_slot);
|
||||
if (update) {
|
||||
update->ref++;
|
||||
va_store(update);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!free_slot) {
|
||||
return STATUS_INSUFF_RESOURCES;
|
||||
}
|
||||
|
@ -1218,23 +1163,24 @@ static u8_t va_add(u8_t *label_uuid, u16_t *addr)
|
|||
free_slot->ref = 1;
|
||||
free_slot->addr = *addr;
|
||||
memcpy(free_slot->uuid, label_uuid, 16);
|
||||
va_store(free_slot);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static u8_t va_del(u8_t *label_uuid, u16_t *addr)
|
||||
{
|
||||
int i;
|
||||
struct label *update;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(labels); i++) {
|
||||
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
|
||||
if (addr) {
|
||||
*addr = labels[i].addr;
|
||||
}
|
||||
update = va_find(label_uuid, NULL);
|
||||
if (update) {
|
||||
update->ref--;
|
||||
|
||||
labels[i].ref--;
|
||||
return STATUS_SUCCESS;
|
||||
if (addr) {
|
||||
*addr = update->addr;
|
||||
}
|
||||
|
||||
va_store(update);
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
|
@ -1244,28 +1190,36 @@ static u8_t va_del(u8_t *label_uuid, u16_t *addr)
|
|||
return STATUS_CANNOT_REMOVE;
|
||||
}
|
||||
|
||||
static void mod_sub_list_clear(struct bt_mesh_model *mod)
|
||||
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
|
||||
{
|
||||
u8_t *label_uuid;
|
||||
size_t clear_count;
|
||||
int i;
|
||||
|
||||
/* Unref stored labels related to this model */
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (!BT_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
label_uuid = bt_mesh_label_uuid_get(mod->groups[i]);
|
||||
if (!label_uuid) {
|
||||
BT_ERR("Label UUID not found");
|
||||
continue;
|
||||
}
|
||||
|
||||
va_del(label_uuid, NULL);
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
|
||||
if (label_uuid) {
|
||||
va_del(label_uuid, NULL);
|
||||
} else {
|
||||
BT_ERR("Label UUID not found");
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all subscriptions (0x0000 is the unassigned address) */
|
||||
memset(mod->groups, 0, sizeof(mod->groups));
|
||||
return clear_count;
|
||||
}
|
||||
|
||||
static void mod_pub_va_set(struct bt_mesh_model *model,
|
||||
|
@ -1300,8 +1254,7 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
|
|||
retransmit = net_buf_simple_pull_u8(buf);
|
||||
mod_id = buf->om_data;
|
||||
|
||||
BT_DBG("elem_addr 0x%04x pub_addr 0x%04x cred_flag %u",
|
||||
elem_addr, pub_addr, cred_flag);
|
||||
BT_DBG("elem_addr 0x%04x cred_flag %u", elem_addr, cred_flag);
|
||||
BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x",
|
||||
pub_app_idx, pub_ttl, pub_period);
|
||||
BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit,
|
||||
|
@ -1335,10 +1288,20 @@ send_status:
|
|||
status, mod_id);
|
||||
}
|
||||
#else
|
||||
static void mod_sub_list_clear(struct bt_mesh_model *mod)
|
||||
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
|
||||
{
|
||||
/* Clear all subscriptions (0x0000 is the unassigned address) */
|
||||
memset(mod->groups, 0, sizeof(mod->groups));
|
||||
size_t clear_count;
|
||||
int i;
|
||||
|
||||
/* Unref stored labels related to this model */
|
||||
for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
|
||||
clear_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return clear_count;
|
||||
}
|
||||
|
||||
static void mod_pub_va_set(struct bt_mesh_model *model,
|
||||
|
@ -1395,8 +1358,7 @@ static void send_mod_sub_status(struct bt_mesh_model *model,
|
|||
u16_t elem_addr, u16_t sub_addr, u8_t *mod_id,
|
||||
bool vnd)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9);
|
||||
|
||||
BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status,
|
||||
elem_addr, sub_addr);
|
||||
|
@ -1429,8 +1391,8 @@ static void mod_sub_add(struct bt_mesh_model *model,
|
|||
struct bt_mesh_elem *elem;
|
||||
u8_t *mod_id;
|
||||
u8_t status;
|
||||
u16_t *entry;
|
||||
bool vnd;
|
||||
int i;
|
||||
|
||||
elem_addr = net_buf_simple_pull_le16(buf);
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
|
||||
|
@ -1463,33 +1425,31 @@ static void mod_sub_add(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
if (bt_mesh_model_find_group(mod, sub_addr)) {
|
||||
if (bt_mesh_model_find_group(&mod, sub_addr)) {
|
||||
/* Tried to add existing subscription */
|
||||
BT_DBG("found existing subscription");
|
||||
status = STATUS_SUCCESS;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = sub_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mod->groups)) {
|
||||
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
|
||||
if (!entry) {
|
||||
status = STATUS_INSUFF_RESOURCES;
|
||||
} else {
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
*entry = sub_addr;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
||||
|
||||
send_status:
|
||||
send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
|
||||
mod_id, vnd);
|
||||
|
@ -1547,7 +1507,7 @@ static void mod_sub_del(struct bt_mesh_model *model,
|
|||
bt_mesh_lpn_group_del(&sub_addr, 1);
|
||||
}
|
||||
|
||||
match = bt_mesh_model_find_group(mod, sub_addr);
|
||||
match = bt_mesh_model_find_group(&mod, sub_addr);
|
||||
if (match) {
|
||||
*match = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
|
@ -1561,6 +1521,18 @@ send_status:
|
|||
mod_id, vnd);
|
||||
}
|
||||
|
||||
static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod,
|
||||
u32_t depth, void *user_data)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
|
||||
}
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
static void mod_sub_overwrite(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
|
@ -1603,13 +1575,10 @@ static void mod_sub_overwrite(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
|
||||
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
|
||||
}
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
|
||||
if (ARRAY_SIZE(mod->groups) > 0) {
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
|
||||
mod_sub_clear_visitor, NULL);
|
||||
|
||||
mod->groups[0] = sub_addr;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
|
@ -1665,11 +1634,8 @@ static void mod_sub_del_all(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
|
||||
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
|
||||
}
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_clear_visitor,
|
||||
NULL);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
|
@ -1682,17 +1648,52 @@ send_status:
|
|||
BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
|
||||
}
|
||||
|
||||
struct mod_sub_list_ctx {
|
||||
u16_t elem_idx;
|
||||
struct os_mbuf *msg;
|
||||
};
|
||||
|
||||
static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod,
|
||||
u32_t depth, void *ctx)
|
||||
{
|
||||
struct mod_sub_list_ctx *visit = ctx;
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
if (mod->elem_idx != visit->elem_idx) {
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (net_buf_simple_tailroom(visit->msg) <
|
||||
2 + BT_MESH_MIC_SHORT) {
|
||||
BT_WARN("No room for all groups");
|
||||
return BT_MESH_WALK_STOP;
|
||||
}
|
||||
|
||||
net_buf_simple_add_le16(visit->msg, mod->groups[i]);
|
||||
count++;
|
||||
}
|
||||
|
||||
BT_DBG("sublist: model %u:%x: %u groups", mod->elem_idx, mod->id,
|
||||
count);
|
||||
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
static void mod_sub_get(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg =
|
||||
NET_BUF_SIMPLE(2 + 5 + 4 +
|
||||
MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT) * 2);
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct mod_sub_list_ctx visit_ctx;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
u16_t addr, id;
|
||||
int i;
|
||||
|
||||
addr = net_buf_simple_pull_le16(buf);
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
|
@ -1727,11 +1728,10 @@ static void mod_sub_get(struct bt_mesh_model *model,
|
|||
net_buf_simple_add_le16(msg, addr);
|
||||
net_buf_simple_add_le16(msg, id);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
net_buf_simple_add_le16(msg, mod->groups[i]);
|
||||
}
|
||||
}
|
||||
visit_ctx.msg = msg;
|
||||
visit_ctx.elem_idx = mod->elem_idx;
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
|
||||
&visit_ctx);
|
||||
|
||||
send_list:
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
|
@ -1747,13 +1747,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg =
|
||||
NET_BUF_SIMPLE(2 + 7 + 4 +
|
||||
MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT) * 2);
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
u16_t company, addr, id;
|
||||
int i;
|
||||
|
||||
addr = net_buf_simple_pull_le16(buf);
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
|
@ -1792,11 +1789,8 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
|
|||
net_buf_simple_add_le16(msg, company);
|
||||
net_buf_simple_add_le16(msg, id);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
net_buf_simple_add_le16(msg, mod->groups[i]);
|
||||
}
|
||||
}
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
|
||||
msg);
|
||||
|
||||
send_list:
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
|
@ -1818,9 +1812,9 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
|
|||
struct bt_mesh_elem *elem;
|
||||
u8_t *label_uuid;
|
||||
u8_t *mod_id;
|
||||
u16_t *entry;
|
||||
u8_t status;
|
||||
bool vnd;
|
||||
int i;
|
||||
|
||||
elem_addr = net_buf_simple_pull_le16(buf);
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
|
||||
|
@ -1854,33 +1848,31 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
if (bt_mesh_model_find_group(mod, sub_addr)) {
|
||||
if (bt_mesh_model_find_group(&mod, sub_addr)) {
|
||||
/* Tried to add existing subscription */
|
||||
status = STATUS_SUCCESS;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
|
||||
mod->groups[i] = sub_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mod->groups)) {
|
||||
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
|
||||
if (!entry) {
|
||||
status = STATUS_INSUFF_RESOURCES;
|
||||
} else {
|
||||
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
*entry = sub_addr;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
send_status:
|
||||
send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
|
||||
mod_id, vnd);
|
||||
|
@ -1936,7 +1928,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
|
|||
bt_mesh_lpn_group_del(&sub_addr, 1);
|
||||
}
|
||||
|
||||
match = bt_mesh_model_find_group(mod, sub_addr);
|
||||
match = bt_mesh_model_find_group(&mod, sub_addr);
|
||||
if (match) {
|
||||
*match = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
|
@ -1992,13 +1984,10 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
|
|||
goto send_status;
|
||||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
|
||||
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
|
||||
}
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
|
||||
if (ARRAY_SIZE(mod->groups) > 0) {
|
||||
bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
|
||||
mod_sub_clear_visitor, NULL);
|
||||
|
||||
status = va_add(label_uuid, &sub_addr);
|
||||
if (status == STATUS_SUCCESS) {
|
||||
mod->groups[0] = sub_addr;
|
||||
|
@ -2145,8 +2134,7 @@ static void send_net_key_status(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
u16_t idx, u8_t status)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_NET_KEY_STATUS);
|
||||
|
||||
|
@ -2361,8 +2349,8 @@ static void net_key_get(struct bt_mesh_model *model,
|
|||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg =
|
||||
NET_BUF_SIMPLE(2 + 4 +
|
||||
IDX_LEN(MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)));
|
||||
BT_MESH_MODEL_BUF(OP_NET_KEY_LIST,
|
||||
IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
|
||||
u16_t prev, i;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST);
|
||||
|
@ -2399,8 +2387,7 @@ static void node_identity_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
|
||||
struct bt_mesh_subnet *sub;
|
||||
u8_t node_id;
|
||||
u16_t idx;
|
||||
|
@ -2441,8 +2428,7 @@ static void node_identity_set(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
|
||||
struct bt_mesh_subnet *sub;
|
||||
u8_t node_id;
|
||||
u16_t idx;
|
||||
|
@ -2474,12 +2460,7 @@ static void node_identity_set(struct bt_mesh_model *model,
|
|||
net_buf_simple_add_u8(msg, STATUS_SUCCESS);
|
||||
net_buf_simple_add_le16(msg, idx);
|
||||
|
||||
/* Section 4.2.11.1: "When the GATT Proxy state is set to
|
||||
* 0x00, the Node Identity state for all subnets shall be set
|
||||
* to 0x00 and shall not be changed."
|
||||
*/
|
||||
if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) &&
|
||||
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
|
||||
if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) {
|
||||
if (node_id) {
|
||||
bt_mesh_proxy_identity_start(sub);
|
||||
} else {
|
||||
|
@ -2522,7 +2503,7 @@ static void mod_app_bind(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
|
||||
u16_t elem_addr, key_app_idx;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
|
@ -2583,7 +2564,7 @@ static void mod_app_unbind(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
|
||||
u16_t elem_addr, key_app_idx;
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
|
@ -2638,7 +2619,11 @@ static void mod_app_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + KEY_LIST_LEN + 4);
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(max(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST,
|
||||
9 + KEY_LIST_LEN),
|
||||
BT_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST,
|
||||
9 + KEY_LIST_LEN)));
|
||||
|
||||
struct bt_mesh_model *mod;
|
||||
struct bt_mesh_elem *elem;
|
||||
u8_t *mod_id, status;
|
||||
|
@ -2709,8 +2694,7 @@ static void node_reset(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0);
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -2733,8 +2717,7 @@ static void node_reset(struct bt_mesh_model *model,
|
|||
static void send_friend_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS);
|
||||
|
@ -2762,7 +2745,6 @@ static void friend_set(struct bt_mesh_model *model,
|
|||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
|
||||
|
@ -2796,9 +2778,8 @@ static void friend_set(struct bt_mesh_model *model,
|
|||
}
|
||||
}
|
||||
|
||||
sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
|
||||
if ((cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) && sub) {
|
||||
hb_send(model);
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
|
||||
send_status:
|
||||
|
@ -2809,8 +2790,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5);
|
||||
struct bt_mesh_friend *frnd;
|
||||
u16_t lpn_addr;
|
||||
s32_t timeout;
|
||||
|
@ -2859,8 +2839,7 @@ static void send_krp_status(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
u16_t idx, u8_t phase, u8_t status)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 4 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_KRP_STATUS);
|
||||
|
||||
|
@ -2999,8 +2978,7 @@ static void hb_pub_send_status(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx, u8_t status,
|
||||
struct hb_pub_param *orig_msg)
|
||||
{
|
||||
/* Needed size: opcode (1 byte) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(1 + 10 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
|
||||
|
@ -3125,8 +3103,7 @@ failed:
|
|||
static void hb_sub_send_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx, u8_t status)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9);
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
u16_t period;
|
||||
s64_t uptime;
|
||||
|
@ -3306,7 +3283,6 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
|
|||
static void hb_publish(struct ble_npl_event *work)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = ble_npl_event_get_arg(work);
|
||||
struct bt_mesh_model *model = cfg->model;
|
||||
struct bt_mesh_subnet *sub;
|
||||
u16_t period_ms;
|
||||
|
||||
|
@ -3329,7 +3305,7 @@ static void hb_publish(struct ble_npl_event *work)
|
|||
k_delayed_work_submit(&cfg->hb_pub.timer, period_ms);
|
||||
}
|
||||
|
||||
hb_send(model);
|
||||
bt_mesh_heartbeat_send();
|
||||
|
||||
if (cfg->hb_pub.count != 0xffff) {
|
||||
cfg->hb_pub.count--;
|
||||
|
@ -3353,10 +3329,17 @@ static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
|
|||
return true;
|
||||
}
|
||||
|
||||
int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary)
|
||||
static int cfg_srv_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!bt_mesh_model_in_primary(model)) {
|
||||
BT_ERR("Configuration Server only allowed in primary element");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cfg) {
|
||||
BT_ERR("No Configuration Server context provided");
|
||||
return -EINVAL;
|
||||
|
@ -3367,8 +3350,11 @@ int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Configuration Model security is device-key based */
|
||||
model->keys[0] = BT_MESH_KEY_DEV;
|
||||
/*
|
||||
* Configuration Model security is device-key based and only the local
|
||||
* device-key is allowed to access this model.
|
||||
*/
|
||||
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
|
||||
|
||||
if (!(MYNEWT_VAL(BLE_MESH_RELAY))) {
|
||||
cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
|
||||
|
@ -3394,19 +3380,33 @@ int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb = {
|
||||
.init = cfg_srv_init,
|
||||
};
|
||||
|
||||
static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
size_t clear_count;
|
||||
|
||||
/* Clear model state that isn't otherwise cleared. E.g. AppKey
|
||||
* binding and model publication is cleared as a consequence
|
||||
* of removing all app keys, however model subscription clearing
|
||||
* must be taken care of here.
|
||||
* of removing all app keys, however model subscription and user data
|
||||
* clearing must be taken care of here.
|
||||
*/
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
clear_count = mod_sub_list_clear(mod);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
if (clear_count) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
bt_mesh_model_data_store(mod, vnd, NULL, 0);
|
||||
}
|
||||
|
||||
if (mod->cb && mod->cb->reset) {
|
||||
mod->cb->reset(mod);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3415,6 +3415,8 @@ void bt_mesh_cfg_reset(void)
|
|||
struct bt_mesh_cfg_srv *cfg = conf;
|
||||
int i;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
@ -26,12 +29,8 @@
|
|||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/cmac_mode.h>
|
||||
#include <tinycrypt/ccm_mode.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_CRYPTO))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
|
||||
|
@ -315,7 +314,7 @@ static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < aad_len; i++, j++) {
|
||||
for (; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
|
@ -479,7 +478,7 @@ static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < aad_len; i++, j++) {
|
||||
for (; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
|
@ -569,7 +568,6 @@ static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
{
|
||||
|
@ -595,7 +593,6 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
|
|||
/* IV Index */
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
#endif /* PROXY */
|
||||
|
||||
static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
|
@ -661,15 +658,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
|||
bt_hex(key, 16), mic_len);
|
||||
BT_DBG("PDU (len %u) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
if (proxy) {
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) {
|
||||
create_proxy_nonce(nonce, buf->om_data, iv_index);
|
||||
} else {
|
||||
create_net_nonce(nonce, buf->om_data, iv_index);
|
||||
}
|
||||
#else
|
||||
create_net_nonce(nonce, buf->om_data, iv_index);
|
||||
#endif
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
|
@ -692,15 +685,11 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
|
|||
BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index,
|
||||
bt_hex(key, 16), mic_len);
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
if (proxy) {
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) {
|
||||
create_proxy_nonce(nonce, buf->om_data, iv_index);
|
||||
} else {
|
||||
create_net_nonce(nonce, buf->om_data, iv_index);
|
||||
}
|
||||
#else
|
||||
create_net_nonce(nonce, buf->om_data, iv_index);
|
||||
#endif
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
|
@ -728,12 +717,11 @@ static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
|
|||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
|
||||
|
@ -745,8 +733,35 @@ int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
|||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, buf->om_data, APP_MIC_LEN(aszmic));
|
||||
return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, buf->om_data,
|
||||
APP_MIC_LEN(aszmic));
|
||||
}
|
||||
|
||||
int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
|
||||
seq_num, iv_index);
|
||||
if (!err) {
|
||||
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
|
||||
seq_num, iv_index);
|
||||
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
|
||||
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
|
||||
|
@ -755,23 +770,43 @@ int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
|||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, struct os_mbuf *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, struct os_mbuf *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst,
|
||||
u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("EncData (len %u) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
|
||||
BT_DBG("EncData (len %u) %s", buf->om_len,
|
||||
bt_hex(buf->om_data, buf->om_len));
|
||||
|
||||
create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, out->om_data, APP_MIC_LEN(aszmic));
|
||||
return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
|
||||
ad ? 16 : 0, out->om_data,
|
||||
APP_MIC_LEN(aszmic));
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
return mesh_app_decrypt(key, dev_key, aszmic, buf, buf,
|
||||
ad, src, dst, seq_num, iv_index);
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, struct os_mbuf *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mesh_app_decrypt(key, dev_key, aszmic, buf, out,
|
||||
ad, src, dst, seq_num, iv_index);
|
||||
if (!err) {
|
||||
net_buf_simple_add(out, buf->om_len);
|
||||
}
|
||||
|
@ -900,6 +935,12 @@ int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
|||
return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25], u8_t out[25 + 8])
|
||||
{
|
||||
return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
}
|
||||
|
||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||
const u8_t net_id[8], u32_t iv_index,
|
||||
u8_t auth[8])
|
||||
|
|
|
@ -131,10 +131,18 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
|
|||
int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
|
||||
u32_t iv_index, bool proxy);
|
||||
|
||||
int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
|
||||
int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf *buf, const u8_t *ad, u16_t src,
|
||||
u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct os_mbuf*buf, struct os_mbuf*out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
|
@ -157,4 +165,6 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
|||
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25 + 8], u8_t out[25]);
|
||||
|
||||
int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25], u8_t out[25 + 8]);
|
||||
#endif
|
||||
|
|
|
@ -115,11 +115,16 @@
|
|||
#define STATUS_UNSPECIFIED 0x10
|
||||
#define STATUS_INVALID_BINDING 0x11
|
||||
|
||||
int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
enum {
|
||||
BT_MESH_VA_CHANGED, /* Label information changed */
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary);
|
||||
int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary);
|
||||
struct label {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
atomic_t flags[1];
|
||||
};
|
||||
|
||||
void bt_mesh_cfg_reset(void);
|
||||
|
||||
|
@ -127,6 +132,8 @@ void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
|
|||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
||||
|
||||
struct label *get_label(u16_t index);
|
||||
|
||||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Bluetooth Mesh */
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
|
@ -6,17 +6,15 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_FRIEND)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_FRIEND))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh/slist.h"
|
||||
#include "mesh_priv.h"
|
||||
|
@ -40,9 +38,9 @@ static os_membuf_t friend_buf_mem[OS_MEMPOOL_SIZE(
|
|||
struct os_mbuf_pool friend_os_mbuf_pool;
|
||||
static struct os_mempool friend_buf_mempool;
|
||||
|
||||
#define NET_BUF_FRAGS BIT(0)
|
||||
|
||||
#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), \
|
||||
struct friend_adv, adv)
|
||||
#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), struct friend_adv, adv)
|
||||
|
||||
/* PDUs from Friend to the LPN should only be transmitted once with the
|
||||
* smallest possible interval (20ms).
|
||||
|
@ -63,54 +61,15 @@ struct friend_pdu_info {
|
|||
|
||||
static struct friend_adv {
|
||||
struct bt_mesh_adv adv;
|
||||
u64_t seq_auth;
|
||||
u16_t app_idx;
|
||||
} adv_pool[FRIEND_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_adv *adv_alloc(int id)
|
||||
{
|
||||
adv_pool[id].app_idx = BT_MESH_KEY_UNUSED;
|
||||
return &adv_pool[id].adv;
|
||||
}
|
||||
|
||||
static void discard_buffer(void)
|
||||
{
|
||||
struct bt_mesh_friend *frnd = &bt_mesh.frnd[0];
|
||||
struct os_mbuf *buf;
|
||||
int i;
|
||||
|
||||
/* Find the Friend context with the most queued buffers */
|
||||
for (i = 1; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
|
||||
if (bt_mesh.frnd[i].queue_size > frnd->queue_size) {
|
||||
frnd = &bt_mesh.frnd[i];
|
||||
}
|
||||
}
|
||||
|
||||
buf = net_buf_slist_get(&frnd->queue);
|
||||
__ASSERT_NO_MSG(buf != NULL);
|
||||
BT_WARN("Discarding buffer %p for LPN 0x%04x", buf, frnd->lpn);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
static struct os_mbuf *friend_buf_alloc(u16_t src)
|
||||
{
|
||||
struct os_mbuf *buf;
|
||||
|
||||
do {
|
||||
buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc,
|
||||
BT_MESH_ADV_DATA,
|
||||
FRIEND_XMIT, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
discard_buffer();
|
||||
}
|
||||
} while (!buf);
|
||||
|
||||
BT_MESH_ADV(buf)->addr = src;
|
||||
FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL;
|
||||
|
||||
BT_DBG("allocated buf %p", buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
|
||||
{
|
||||
if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) {
|
||||
|
@ -150,6 +109,17 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void purge_buffers(struct net_buf_slist_t *list)
|
||||
{
|
||||
struct os_mbuf *buf;
|
||||
|
||||
while (!net_buf_slist_is_empty(list)) {
|
||||
buf = (void *)net_buf_slist_get(list);
|
||||
BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS;
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Intentionally start a little bit late into the ReceiveWindow when
|
||||
* it's large enough. This may improve reliability with some platforms,
|
||||
* like the PTS, where the receiver might not have sufficiently compensated
|
||||
|
@ -184,16 +154,13 @@ static void friend_clear(struct bt_mesh_friend *frnd)
|
|||
frnd->last = NULL;
|
||||
}
|
||||
|
||||
while (!net_buf_slist_is_empty(&frnd->queue)) {
|
||||
net_buf_unref(net_buf_slist_get(&frnd->queue));
|
||||
}
|
||||
purge_buffers(&frnd->queue);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
|
||||
struct bt_mesh_friend_seg *seg = &frnd->seg[i];
|
||||
|
||||
while (!net_buf_slist_is_empty(&seg->queue)) {
|
||||
net_buf_unref(net_buf_slist_get(&seg->queue));
|
||||
}
|
||||
purge_buffers(&seg->queue);
|
||||
seg->seg_count = 0U;
|
||||
}
|
||||
|
||||
frnd->valid = 0;
|
||||
|
@ -327,29 +294,16 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
|
|||
struct friend_pdu_info *info,
|
||||
struct os_mbuf *sdu)
|
||||
{
|
||||
struct bt_mesh_subnet *sub;
|
||||
const u8_t *enc, *priv;
|
||||
struct os_mbuf *buf;
|
||||
u8_t nid;
|
||||
|
||||
sub = bt_mesh_subnet_get(frnd->net_idx);
|
||||
__ASSERT_NO_MSG(sub != NULL);
|
||||
|
||||
buf = friend_buf_alloc(info->src);
|
||||
|
||||
/* Friend Offer needs master security credentials */
|
||||
if (info->ctl && TRANS_CTL_OP(sdu->om_data) == TRANS_CTL_OP_FRIEND_OFFER) {
|
||||
enc = sub->keys[sub->kr_flag].enc;
|
||||
priv = sub->keys[sub->kr_flag].privacy;
|
||||
nid = sub->keys[sub->kr_flag].nid;
|
||||
} else {
|
||||
if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
|
||||
BT_ERR("friend_cred_get failed");
|
||||
goto failed;
|
||||
}
|
||||
buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc,
|
||||
BT_MESH_ADV_DATA,
|
||||
FRIEND_XMIT, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
net_buf_add_u8(buf, (nid | (info->iv_index & 1) << 7));
|
||||
net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */
|
||||
|
||||
if (info->ctl) {
|
||||
net_buf_add_u8(buf, info->ttl | 0x80);
|
||||
|
@ -364,25 +318,187 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
|
|||
|
||||
net_buf_add_mem(buf, sdu->om_data, sdu->om_len);
|
||||
|
||||
/* We re-encrypt and obfuscate using the received IVI rather than
|
||||
* the normal TX IVI (which may be different) since the transport
|
||||
* layer nonce includes the IVI.
|
||||
*/
|
||||
if (bt_mesh_net_encrypt(enc, buf, info->iv_index, false)) {
|
||||
BT_ERR("Re-encrypting failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (bt_mesh_net_obfuscate(buf->om_data, info->iv_index, priv)) {
|
||||
BT_ERR("Re-obfuscating failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
failed:
|
||||
net_buf_unref(buf);
|
||||
return NULL;
|
||||
struct unseg_app_sdu_meta {
|
||||
struct bt_mesh_net_rx net;
|
||||
const u8_t *key;
|
||||
struct bt_mesh_subnet *subnet;
|
||||
bool is_dev_key;
|
||||
u8_t aid;
|
||||
u8_t *ad;
|
||||
};
|
||||
|
||||
static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
|
||||
struct os_mbuf *buf,
|
||||
struct unseg_app_sdu_meta *meta)
|
||||
{
|
||||
u16_t app_idx = FRIEND_ADV(buf)->app_idx;
|
||||
int err;
|
||||
|
||||
meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
|
||||
meta->is_dev_key = (app_idx == BT_MESH_KEY_DEV);
|
||||
meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx);
|
||||
bt_mesh_net_header_parse(buf, &meta->net);
|
||||
err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst,
|
||||
&meta->key, &meta->aid);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
|
||||
meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
|
||||
if (!meta->ad) {
|
||||
return -ENOENT;
|
||||
}
|
||||
} else {
|
||||
meta->ad = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
|
||||
struct os_mbuf *buf,
|
||||
const struct unseg_app_sdu_meta *meta)
|
||||
{
|
||||
struct net_buf_simple_state state;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
net_buf_simple_save(buf, &state);
|
||||
net_buf_simple_pull_mem(buf, 10);
|
||||
buf->om_len -= 4;
|
||||
|
||||
err = bt_mesh_app_decrypt_in_place(meta->key, meta->is_dev_key,
|
||||
0, buf, meta->ad, meta->net.ctx.addr,
|
||||
meta->net.ctx.recv_dst, meta->net.seq,
|
||||
BT_MESH_NET_IVI_TX);
|
||||
|
||||
net_buf_simple_restore(buf, &state);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
|
||||
struct os_mbuf *buf,
|
||||
const struct unseg_app_sdu_meta *meta)
|
||||
{
|
||||
struct net_buf_simple_state state;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
net_buf_simple_save(buf, &state);
|
||||
net_buf_simple_pull_mem(buf, 10);
|
||||
buf->om_len -= 4;
|
||||
|
||||
err = bt_mesh_app_encrypt_in_place(meta->key, meta->is_dev_key, 0, buf,
|
||||
meta->ad, meta->net.ctx.addr,
|
||||
meta->net.ctx.recv_dst, bt_mesh.seq,
|
||||
BT_MESH_NET_IVI_TX);
|
||||
|
||||
net_buf_simple_restore(buf, &state);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct unseg_app_sdu_meta meta;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (FRIEND_ADV(buf)->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = unseg_app_sdu_unpack(frnd, buf, &meta);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* No need to reencrypt the message if the sequence number is
|
||||
* unchanged.
|
||||
*/
|
||||
if (meta.net.seq == bt_mesh.seq) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = unseg_app_sdu_decrypt(frnd, buf, &meta);
|
||||
if (err) {
|
||||
BT_WARN("Decryption failed! %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = unseg_app_sdu_encrypt(frnd, buf, &meta);
|
||||
if (err) {
|
||||
BT_WARN("Re-encryption failed! %d", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
|
||||
bool master_cred)
|
||||
{
|
||||
struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
|
||||
const u8_t *enc, *priv;
|
||||
u32_t iv_index;
|
||||
u16_t src;
|
||||
u8_t nid;
|
||||
int err;
|
||||
|
||||
if (master_cred) {
|
||||
enc = sub->keys[sub->kr_flag].enc;
|
||||
priv = sub->keys[sub->kr_flag].privacy;
|
||||
nid = sub->keys[sub->kr_flag].nid;
|
||||
} else {
|
||||
if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
|
||||
BT_ERR("friend_cred_get failed");
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
src = sys_get_be16(&buf->om_data[5]);
|
||||
|
||||
if (bt_mesh_elem_find(src)) {
|
||||
u32_t seq;
|
||||
|
||||
if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) {
|
||||
err = unseg_app_sdu_prepare(frnd, buf);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
seq = bt_mesh_next_seq();
|
||||
buf->om_data[2] = seq >> 16;
|
||||
buf->om_data[3] = seq >> 8;
|
||||
buf->om_data[4] = seq;
|
||||
|
||||
iv_index = BT_MESH_NET_IVI_TX;
|
||||
FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED;
|
||||
} else {
|
||||
u8_t ivi = (buf->om_data[0] >> 7);
|
||||
iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
|
||||
}
|
||||
|
||||
buf->om_data[0] = (nid | (iv_index & 1) << 7);
|
||||
|
||||
if (bt_mesh_net_encrypt(enc, buf, iv_index, false)) {
|
||||
BT_ERR("Encrypting failed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bt_mesh_net_obfuscate(buf->om_data, iv_index, priv)) {
|
||||
BT_ERR("Obfuscating failed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
|
||||
|
@ -390,7 +506,6 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
|
|||
struct os_mbuf *sdu)
|
||||
{
|
||||
struct friend_pdu_info info;
|
||||
u32_t seq;
|
||||
|
||||
BT_DBG("LPN 0x%04x", frnd->lpn);
|
||||
|
||||
|
@ -402,10 +517,7 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
|
|||
info.ctl = 1;
|
||||
info.ttl = 0;
|
||||
|
||||
seq = bt_mesh_next_seq();
|
||||
info.seq[0] = seq >> 16;
|
||||
info.seq[1] = seq >> 8;
|
||||
info.seq[2] = seq;
|
||||
memset(info.seq, 0, sizeof(info.seq));
|
||||
|
||||
info.iv_index = BT_MESH_NET_IVI_TX;
|
||||
|
||||
|
@ -455,6 +567,10 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (encrypt_friend_pdu(frnd, buf, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (frnd->last) {
|
||||
BT_DBG("Discarding last PDU");
|
||||
net_buf_unref(frnd->last);
|
||||
|
@ -693,8 +809,8 @@ static void clear_procedure_start(struct bt_mesh_friend *frnd)
|
|||
{
|
||||
BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
|
||||
|
||||
frnd->clear.start = k_uptime_get_32() + (2 * frnd->poll_to);
|
||||
frnd->clear.repeat_sec = 1;
|
||||
frnd->clear.start = k_uptime_get_32();
|
||||
frnd->clear.repeat_sec = 1U;
|
||||
|
||||
send_friend_clear(frnd);
|
||||
}
|
||||
|
@ -763,6 +879,10 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (encrypt_friend_pdu(frnd, buf, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
frnd->counter++;
|
||||
|
||||
if (frnd->last) {
|
||||
|
@ -886,7 +1006,7 @@ init_friend:
|
|||
frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
|
||||
|
||||
BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
|
||||
frnd->lpn, rx->rssi, frnd->recv_delay,
|
||||
frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay,
|
||||
(unsigned) frnd->poll_to);
|
||||
|
||||
if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) &&
|
||||
|
@ -895,45 +1015,70 @@ init_friend:
|
|||
}
|
||||
|
||||
k_delayed_work_submit(&frnd->timer,
|
||||
offer_delay(frnd, rx->rssi, msg->criteria));
|
||||
offer_delay(frnd, rx->ctx.recv_rssi,
|
||||
msg->criteria));
|
||||
|
||||
friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
|
||||
frnd->counter);
|
||||
|
||||
enqueue_offer(frnd, rx->rssi);
|
||||
enqueue_offer(frnd, rx->ctx.recv_rssi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
|
||||
{
|
||||
struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
|
||||
struct net_buf_simple_state state;
|
||||
u16_t buf_seq_zero;
|
||||
u16_t buf_src;
|
||||
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
net_buf_simple_save(buf, &state);
|
||||
net_buf_skip(buf, 5); /* skip IVI, NID, CTL, TTL, SEQ */
|
||||
buf_src = net_buf_pull_be16(buf);
|
||||
net_buf_skip(buf, 3); /* skip DST, OP/AID */
|
||||
buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK);
|
||||
net_buf_simple_restore(buf, &state);
|
||||
|
||||
return ((src == buf_src) && (seq_zero == buf_seq_zero));
|
||||
}
|
||||
|
||||
static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
|
||||
u16_t src, u64_t *seq_auth)
|
||||
u16_t src, u16_t seq_zero,
|
||||
u8_t seg_count)
|
||||
{
|
||||
struct bt_mesh_friend_seg *unassigned = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
|
||||
struct bt_mesh_friend_seg *seg = &frnd->seg[i];
|
||||
struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
|
||||
|
||||
if (buf && BT_MESH_ADV(buf)->addr == src &&
|
||||
FRIEND_ADV(buf)->seq_auth == *seq_auth) {
|
||||
if (is_seg(seg, src, seq_zero)) {
|
||||
return seg;
|
||||
}
|
||||
|
||||
if (!unassigned && !buf) {
|
||||
if (!unassigned && !net_buf_slist_peek_head(&seg->queue)) {
|
||||
unassigned = seg;
|
||||
}
|
||||
}
|
||||
|
||||
if (unassigned) {
|
||||
unassigned->seg_count = seg_count;
|
||||
}
|
||||
|
||||
return unassigned;
|
||||
}
|
||||
|
||||
static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u16_t src, u8_t seg_count,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_friend_seg *seg;
|
||||
struct friend_adv *adv;
|
||||
|
||||
BT_DBG("type %u", type);
|
||||
|
||||
|
@ -946,11 +1091,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
|
|||
return;
|
||||
}
|
||||
|
||||
adv = FRIEND_ADV(buf);
|
||||
seg = get_seg(frnd, BT_MESH_ADV(buf)->addr, &adv->seq_auth);
|
||||
u16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
|
||||
|
||||
seg = get_seg(frnd, src, seq_zero, seg_count);
|
||||
if (!seg) {
|
||||
BT_ERR("No free friend segment RX contexts for 0x%04x",
|
||||
BT_MESH_ADV(buf)->addr);
|
||||
BT_ERR("No free friend segment RX contexts for 0x%04x", src);
|
||||
net_buf_unref(buf);
|
||||
return;
|
||||
}
|
||||
|
@ -962,19 +1107,13 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
|
|||
enqueue_update(frnd, 1);
|
||||
}
|
||||
|
||||
/* Only acks should have a valid SeqAuth in the Friend queue
|
||||
* (otherwise we can't easily detect them there), so clear
|
||||
* the SeqAuth information from the segments before merging.
|
||||
*/
|
||||
struct os_mbuf *m;
|
||||
struct os_mbuf_pkthdr *pkthdr;
|
||||
NET_BUF_SLIST_FOR_EACH_NODE(&seg->queue, pkthdr) {
|
||||
m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
|
||||
FRIEND_ADV(m)->seq_auth = TRANS_SEQ_AUTH_NVAL;
|
||||
frnd->queue_size++;
|
||||
}
|
||||
|
||||
net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
|
||||
|
||||
frnd->queue_size += seg->seg_count;
|
||||
seg->seg_count = 0U;
|
||||
} else {
|
||||
/* Mark the buffer as having more to come after it */
|
||||
BT_MESH_ADV(buf)->flags |= NET_BUF_FRAGS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1040,13 +1179,21 @@ static void friend_timeout(struct ble_npl_event *work)
|
|||
return;
|
||||
}
|
||||
|
||||
frnd->last = net_buf_slist_get(&frnd->queue);
|
||||
frnd->last = (void *)net_buf_slist_get(&frnd->queue);
|
||||
if (!frnd->last) {
|
||||
BT_WARN("Friendship not established with 0x%04x", frnd->lpn);
|
||||
BT_WARN("Friendship not established with 0x%04x",
|
||||
frnd->lpn);
|
||||
friend_clear(frnd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (encrypt_friend_pdu(frnd, frnd->last, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear the flag we use for segment tracking */
|
||||
BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS;
|
||||
|
||||
BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
|
||||
frnd->last, frnd->lpn);
|
||||
frnd->queue_size--;
|
||||
|
@ -1093,6 +1240,42 @@ int bt_mesh_friend_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
|
||||
{
|
||||
struct net_buf_simple_state state;
|
||||
bool found = false;
|
||||
|
||||
if (buf->om_len != 16) {
|
||||
return false;
|
||||
}
|
||||
|
||||
net_buf_simple_save(buf, &state);
|
||||
|
||||
net_buf_skip(buf, 1); /* skip IVI, NID */
|
||||
|
||||
if (!(net_buf_pull_u8(buf) >> 7)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
net_buf_pull(buf, 3); /* skip SEQNUM */
|
||||
|
||||
if (src != net_buf_pull_be16(buf)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
net_buf_skip(buf, 2); /* skip dst */
|
||||
|
||||
if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) ==
|
||||
(*seqauth & TRANS_SEQ_ZERO_MASK);
|
||||
end:
|
||||
net_buf_simple_restore(buf, &state);
|
||||
return found;
|
||||
}
|
||||
|
||||
static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
|
||||
u16_t src)
|
||||
{
|
||||
|
@ -1104,8 +1287,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
|
|||
cur != NULL; prev = cur, cur = net_buf_slist_peek_next(cur)) {
|
||||
struct os_mbuf *buf = (void *)cur;
|
||||
|
||||
if (BT_MESH_ADV(buf)->addr == src &&
|
||||
FRIEND_ADV(buf)->seq_auth == *seq_auth) {
|
||||
if (is_segack(buf, seq_auth, src)) {
|
||||
BT_DBG("Removing old ack from Friend Queue");
|
||||
|
||||
net_buf_slist_remove(&frnd->queue, prev, cur);
|
||||
|
@ -1120,11 +1302,20 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
|
|||
static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf)
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf)
|
||||
{
|
||||
struct friend_pdu_info info;
|
||||
struct os_mbuf *buf;
|
||||
|
||||
/* Because of network loopback, tx packets will also be passed into
|
||||
* this rx function. These packets have already been added to the
|
||||
* queue, and should be ignored.
|
||||
*/
|
||||
if (bt_mesh_elem_find(rx->ctx.addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn,
|
||||
(unsigned) frnd->queue_size);
|
||||
|
||||
|
@ -1155,11 +1346,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (seq_auth) {
|
||||
FRIEND_ADV(buf)->seq_auth = *seq_auth;
|
||||
}
|
||||
|
||||
enqueue_friend_pdu(frnd, type, buf);
|
||||
enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
|
||||
|
||||
BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
|
||||
frnd->lpn, (unsigned) frnd->queue_size);
|
||||
|
@ -1168,11 +1355,11 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
|
|||
static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
|
||||
struct bt_mesh_net_tx *tx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf)
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf)
|
||||
{
|
||||
struct friend_pdu_info info;
|
||||
struct os_mbuf *buf;
|
||||
u32_t seq;
|
||||
|
||||
BT_DBG("LPN 0x%04x", frnd->lpn);
|
||||
|
||||
|
@ -1186,10 +1373,9 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
|
|||
info.ttl = tx->ctx->send_ttl;
|
||||
info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
|
||||
|
||||
seq = bt_mesh_next_seq();
|
||||
info.seq[0] = seq >> 16;
|
||||
info.seq[1] = seq >> 8;
|
||||
info.seq[2] = seq;
|
||||
info.seq[0] = (bt_mesh.seq >> 16);
|
||||
info.seq[1] = (bt_mesh.seq >> 8);
|
||||
info.seq[2] = bt_mesh.seq;
|
||||
|
||||
info.iv_index = BT_MESH_NET_IVI_TX;
|
||||
|
||||
|
@ -1199,11 +1385,15 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (seq_auth) {
|
||||
FRIEND_ADV(buf)->seq_auth = *seq_auth;
|
||||
if (type == BT_MESH_FRIEND_PDU_SINGLE && !info.ctl) {
|
||||
/* Unsegmented application packets may be reencrypted later,
|
||||
* as they depend on the the sequence number being the same
|
||||
* when encrypting in transport and network.
|
||||
*/
|
||||
FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx;
|
||||
}
|
||||
|
||||
enqueue_friend_pdu(frnd, type, buf);
|
||||
enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
|
||||
|
||||
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
|
||||
}
|
||||
|
@ -1253,9 +1443,112 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
|
||||
u64_t *seq_auth, u8_t seg_count)
|
||||
{
|
||||
u32_t total = 0;
|
||||
int i;
|
||||
|
||||
if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
|
||||
struct bt_mesh_friend_seg *seg = &frnd->seg[i];
|
||||
|
||||
if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
|
||||
/* If there's a segment queue for this message then the
|
||||
* space verification has already happened.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
total += seg->seg_count;
|
||||
}
|
||||
|
||||
/* If currently pending segments combined with this segmented message
|
||||
* are more than the Friend Queue Size, then there's no space. This
|
||||
* is because we don't have a mechanism of aborting already pending
|
||||
* segmented messages to free up buffers.
|
||||
*/
|
||||
return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
|
||||
}
|
||||
|
||||
bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
|
||||
u64_t *seq_auth, u8_t seg_count)
|
||||
{
|
||||
bool someone_has_space = false, friend_match = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
|
||||
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
|
||||
|
||||
if (!friend_lpn_matches(frnd, net_idx, dst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
friend_match = true;
|
||||
|
||||
if (friend_queue_has_space(frnd, src, seq_auth, seg_count)) {
|
||||
someone_has_space = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there were no matched LPNs treat this as success, so the
|
||||
* transport layer can continue its work.
|
||||
*/
|
||||
if (!friend_match) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* From the transport layers perspective it's good enough that at
|
||||
* least one Friend Queue has space. If there were multiple Friend
|
||||
* matches then the destination must be a group address, in which
|
||||
* case e.g. segment acks are not sent.
|
||||
*/
|
||||
return someone_has_space;
|
||||
}
|
||||
|
||||
static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
|
||||
u64_t *seq_auth, u8_t seg_count)
|
||||
{
|
||||
bool pending_segments;
|
||||
u8_t avail_space;
|
||||
|
||||
if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
avail_space = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - frnd->queue_size;
|
||||
pending_segments = false;
|
||||
|
||||
while (pending_segments || avail_space < seg_count) {
|
||||
struct os_mbuf *buf = (void *)net_buf_slist_get(&frnd->queue);
|
||||
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to free up enough buffers");
|
||||
return false;
|
||||
}
|
||||
|
||||
frnd->queue_size--;
|
||||
avail_space++;
|
||||
|
||||
pending_segments = (BT_MESH_ADV(buf)->flags & NET_BUF_FRAGS);
|
||||
BT_DBG("PENDING SEGMENTS %d", pending_segments);
|
||||
|
||||
/* Make sure old slist entry state doesn't remain */
|
||||
BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS;
|
||||
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf)
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1272,16 +1565,25 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
|
|||
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
|
||||
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
|
||||
|
||||
if (friend_lpn_matches(frnd, rx->sub->net_idx,
|
||||
rx->ctx.recv_dst)) {
|
||||
friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, sbuf);
|
||||
if (!friend_lpn_matches(frnd, rx->sub->net_idx,
|
||||
rx->ctx.recv_dst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth,
|
||||
seg_count)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count,
|
||||
sbuf);
|
||||
}
|
||||
}
|
||||
|
||||
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf)
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf)
|
||||
{
|
||||
bool matched = false;
|
||||
int i;
|
||||
|
@ -1297,10 +1599,19 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
|
|||
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
|
||||
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
|
||||
|
||||
if (friend_lpn_matches(frnd, tx->sub->net_idx, tx->ctx->addr)) {
|
||||
friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, sbuf);
|
||||
matched = true;
|
||||
if (!friend_lpn_matches(frnd, tx->sub->net_idx,
|
||||
tx->ctx->addr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!friend_queue_prepare_space(frnd, tx->src, seq_auth,
|
||||
seg_count)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, seg_count,
|
||||
sbuf);
|
||||
matched = true;
|
||||
}
|
||||
|
||||
return matched;
|
||||
|
@ -1323,26 +1634,16 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
|
|||
|
||||
for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
|
||||
struct bt_mesh_friend_seg *seg = &frnd->seg[j];
|
||||
struct os_mbuf *buf;
|
||||
|
||||
buf = (void *)net_buf_slist_peek_head(&seg->queue);
|
||||
if (!buf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BT_MESH_ADV(buf)->addr != src) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FRIEND_ADV(buf)->seq_auth != *seq_auth) {
|
||||
if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BT_WARN("Clearing incomplete segments for 0x%04x", src);
|
||||
|
||||
while (!net_buf_slist_is_empty(&seg->queue)) {
|
||||
net_buf_unref(net_buf_slist_get(&seg->queue));
|
||||
}
|
||||
purge_buffers(&seg->queue);
|
||||
seg->seg_count = 0U;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,12 +22,17 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
|
|||
struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
|
||||
bool valid, bool established);
|
||||
|
||||
bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
|
||||
u64_t *seq_auth, u8_t seg_count);
|
||||
|
||||
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf);
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf);
|
||||
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct os_mbuf *sbuf);
|
||||
u64_t *seq_auth, u8_t seg_count,
|
||||
struct os_mbuf *sbuf);
|
||||
|
||||
void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
|
||||
u16_t dst, u64_t *seq_auth);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
|
||||
#include "mesh/glue.h"
|
||||
#include "adv.h"
|
||||
#ifndef MYNEWT
|
||||
|
@ -27,22 +30,6 @@
|
|||
#include "base64/base64.h"
|
||||
#endif
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
#define BT_MESH_ADV_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES))
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROXY)
|
||||
/* Note that BLE_MULTI_ADV_INSTANCES contains number of additional instances.
|
||||
* Instance 0 is always there
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) < 1
|
||||
#error "Mesh needs at least BLE_MULTI_ADV_INSTANCES set to 1"
|
||||
#endif
|
||||
#define BT_MESH_ADV_GATT_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) - 1)
|
||||
#endif /* BLE_MESH_PROXY */
|
||||
#endif /* BLE_EXT_ADV */
|
||||
|
||||
extern u8_t g_mesh_addr_type;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
@ -133,13 +120,16 @@ bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data)
|
|||
mbedtls_aes_init(&s);
|
||||
|
||||
if (mbedtls_aes_setkey_enc(&s, key, 128) != 0) {
|
||||
mbedtls_aes_free(&s);
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
if (mbedtls_aes_crypt_ecb(&s, MBEDTLS_AES_ENCRYPT, plaintext, enc_data) != 0) {
|
||||
mbedtls_aes_free(&s);
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
mbedtls_aes_free(&s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -872,13 +862,11 @@ void net_buf_slist_remove(struct net_buf_slist_t *list, struct os_mbuf *prev,
|
|||
void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
|
||||
struct net_buf_slist_t *list_to_append)
|
||||
{
|
||||
struct os_mbuf_pkthdr *pkthdr;
|
||||
|
||||
STAILQ_FOREACH(pkthdr, list_to_append, omp_next) {
|
||||
STAILQ_INSERT_TAIL(list, pkthdr, omp_next);
|
||||
if (!STAILQ_EMPTY(list_to_append)) {
|
||||
*(list)->stqh_last = list_to_append->stqh_first;
|
||||
(list)->stqh_last = list_to_append->stqh_last;
|
||||
STAILQ_INIT(list_to_append);
|
||||
}
|
||||
|
||||
STAILQ_INIT(list);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
|
||||
|
@ -889,7 +877,8 @@ int settings_bytes_from_str(char *val_str, void *vp, int *len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *settings_str_from_bytes(void *vp, int vp_len, char *buf, int buf_len)
|
||||
char *settings_str_from_bytes(const void *vp, int vp_len,
|
||||
char *buf, int buf_len)
|
||||
{
|
||||
if (BASE64_ENCODE_SIZE(vp_len) > buf_len) {
|
||||
return NULL;
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
|
@ -206,7 +205,7 @@ static int cli_wait(void)
|
|||
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *attention)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -241,7 +240,7 @@ done:
|
|||
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t attention, u8_t *updated_attention)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -287,7 +286,7 @@ done:
|
|||
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *divisor)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -322,7 +321,7 @@ done:
|
|||
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t divisor, u8_t *updated_divisor)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -369,7 +368,7 @@ int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
u16_t cid, u8_t test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -420,7 +419,7 @@ int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -470,7 +469,7 @@ int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
|
@ -528,11 +527,11 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary)
|
||||
static int health_cli_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_health_cli *cli = model->user_data;
|
||||
|
||||
BT_DBG("primary %u", primary);
|
||||
BT_DBG("primary %u", bt_mesh_model_in_primary(model));
|
||||
|
||||
if (!cli) {
|
||||
BT_ERR("No Health Client context provided");
|
||||
|
@ -551,3 +550,7 @@ int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_health_cli_cb = {
|
||||
.init = health_cli_init,
|
||||
};
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "adv.h"
|
||||
|
@ -218,8 +217,7 @@ done:
|
|||
static void send_attention_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u8_t time;
|
||||
|
||||
|
@ -273,8 +271,7 @@ static void attention_set(struct bt_mesh_model *model,
|
|||
static void send_health_period_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_STATUS, 1);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_STATUS);
|
||||
|
||||
|
@ -347,8 +344,10 @@ static int health_pub_update(struct bt_mesh_model *mod)
|
|||
BT_DBG("");
|
||||
|
||||
count = health_get_current(mod, pub->msg);
|
||||
if (!count) {
|
||||
pub->period_div = 0;
|
||||
if (count) {
|
||||
pub->fast_period = 1U;
|
||||
} else {
|
||||
pub->fast_period = 0U;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -363,6 +362,15 @@ int bt_mesh_fault_update(struct bt_mesh_elem *elem)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Let periodic publishing, if enabled, take care of sending the
|
||||
* Health Current Status.
|
||||
*/
|
||||
if (bt_mesh_model_pub_period_get(mod)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
health_pub_update(mod);
|
||||
|
||||
return bt_mesh_model_publish(mod);
|
||||
}
|
||||
|
||||
|
@ -376,12 +384,12 @@ static void attention_off(struct ble_npl_event *work)
|
|||
}
|
||||
}
|
||||
|
||||
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
||||
static int health_srv_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
|
||||
if (!srv) {
|
||||
if (!primary) {
|
||||
if (!bt_mesh_model_in_primary(model)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -401,13 +409,17 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
|||
|
||||
srv->model = model;
|
||||
|
||||
if (primary) {
|
||||
if (bt_mesh_model_in_primary(model)) {
|
||||
health_srv = srv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
|
||||
.init = health_srv_init,
|
||||
};
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv;
|
||||
|
|
|
@ -7,14 +7,12 @@
|
|||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOW_POWER_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_LOW_POWER))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "crypto.h"
|
||||
|
@ -66,7 +64,7 @@
|
|||
|
||||
static void (*lpn_cb)(u16_t friend_addr, bool established);
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_DEBUG_LOW_POWER)
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
|
||||
static const char *state2str(int state)
|
||||
{
|
||||
switch (state) {
|
||||
|
@ -92,11 +90,11 @@ static const char *state2str(int state)
|
|||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLUETOOTH_MESH_DEBUG_LPN */
|
||||
#endif
|
||||
|
||||
static inline void lpn_set_state(int state)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_MESH_DEBUG_LOW_POWER)
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
|
||||
BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state));
|
||||
#endif
|
||||
bt_mesh.lpn.state = state;
|
||||
|
@ -196,6 +194,7 @@ static int send_friend_clear(void)
|
|||
|
||||
static void clear_friendship(bool force, bool disable)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
BT_DBG("force %u disable %u", force, disable);
|
||||
|
@ -243,6 +242,10 @@ static void clear_friendship(bool force, bool disable)
|
|||
*/
|
||||
lpn->groups_changed = 1;
|
||||
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
|
||||
if (disable) {
|
||||
lpn_set_state(BT_MESH_LPN_DISABLED);
|
||||
return;
|
||||
|
@ -311,7 +314,7 @@ static void req_sent(u16_t duration, int err, void *user_data)
|
|||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
#if BT_DBG_ENABLED
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
|
||||
BT_DBG("req 0x%02x duration %u err %d state %s",
|
||||
lpn->sent_req, duration, err, state2str(lpn->state));
|
||||
#endif
|
||||
|
@ -725,7 +728,7 @@ static void lpn_timeout(struct ble_npl_event *work)
|
|||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_DEBUG_LOW_POWER)
|
||||
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
|
||||
BT_DBG("state: %s", state2str(lpn->state));
|
||||
#endif
|
||||
|
||||
|
@ -758,6 +761,7 @@ static void lpn_timeout(struct ble_npl_event *work)
|
|||
}
|
||||
lpn->counter++;
|
||||
lpn_set_state(BT_MESH_LPN_ENABLED);
|
||||
lpn->sent_req = 0U;
|
||||
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
|
||||
break;
|
||||
case BT_MESH_LPN_ESTABLISHED:
|
||||
|
@ -940,6 +944,8 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
}
|
||||
|
||||
if (!lpn->established) {
|
||||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
|
||||
/* This is normally checked on the transport layer, however
|
||||
* in this state we're also still accepting master
|
||||
* credentials so we need to ensure the right ones (Friend
|
||||
|
@ -954,6 +960,10 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
|
||||
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
|
||||
|
||||
if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
|
||||
bt_mesh_heartbeat_send();
|
||||
}
|
||||
|
||||
if (lpn_cb) {
|
||||
lpn_cb(lpn->frnd, true);
|
||||
}
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
|
||||
#include "host/ble_hs_log.h"
|
||||
#include "host/ble_uuid.h"
|
||||
|
||||
#include "adv.h"
|
||||
|
@ -50,7 +49,7 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
|||
}
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
|
||||
if (bt_mesh_proxy_prov_disable() == 0) {
|
||||
if (bt_mesh_proxy_prov_disable(false) == 0) {
|
||||
pb_gatt_enabled = true;
|
||||
} else {
|
||||
pb_gatt_enabled = false;
|
||||
|
@ -88,6 +87,26 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration)
|
||||
{
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bt_mesh_subnet_get(net_idx) == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
|
||||
return bt_mesh_pb_adv_open(uuid, net_idx, addr,
|
||||
attention_duration);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
void bt_mesh_reset(void)
|
||||
{
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
|
||||
|
@ -149,14 +168,12 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
|
|||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (MYNEWT_VAL(BLE_MESH_DEBUG)) {
|
||||
char uuid_buf[BLE_UUID_STR_LEN];
|
||||
const struct bt_mesh_prov *prov = bt_mesh_prov_get();
|
||||
ble_uuid_t *uuid = BLE_UUID128_DECLARE();
|
||||
char uuid_buf[BLE_UUID_STR_LEN];
|
||||
const struct bt_mesh_prov *prov = bt_mesh_prov_get();
|
||||
ble_uuid_t *uuid = BLE_UUID128_DECLARE();
|
||||
|
||||
memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
|
||||
BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
|
||||
}
|
||||
memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
|
||||
BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
|
@ -189,8 +206,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
|
|||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_disable();
|
||||
bt_mesh_adv_update();
|
||||
bt_mesh_proxy_prov_disable(true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -32,6 +32,7 @@ struct bt_mesh_net;
|
|||
#define OP_LIGHT_LIGHTNESS_GET BT_MESH_MODEL_OP_2(0x82, 0x4b)
|
||||
#define OP_LIGHT_LIGHTNESS_SET BT_MESH_MODEL_OP_2(0x82, 0x4c)
|
||||
#define OP_LIGHT_LIGHTNESS_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x4d)
|
||||
#define OP_LIGHT_LIGHTNESS_STATUS BT_MESH_MODEL_OP_2(0x82, 0x4e)
|
||||
|
||||
bool bt_mesh_is_provisioned(void);
|
||||
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <mesh/mesh.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh/model_cli.h"
|
||||
#include "mesh_priv.h"
|
||||
|
||||
static s32_t msg_timeout = K_SECONDS(5);
|
||||
|
||||
struct bt_mesh_gen_model_cli gen_onoff_cli;
|
||||
struct bt_mesh_gen_model_cli gen_level_cli;
|
||||
static struct bt_mesh_gen_model_cli *gen_onoff_cli;
|
||||
static struct bt_mesh_gen_model_cli *gen_level_cli;
|
||||
|
||||
static u8_t transaction_id = 0;
|
||||
|
||||
|
@ -90,11 +91,53 @@ const struct bt_mesh_model_op gen_onoff_cli_op[] = {
|
|||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int onoff_cli_init(struct bt_mesh_model *model)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
if (!model->user_data) {
|
||||
BT_ERR("No Generic OnOff Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gen_onoff_cli = model->user_data;
|
||||
gen_onoff_cli->model = model;
|
||||
|
||||
k_sem_init(&gen_onoff_cli->op_sync, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_gen_onoff_cli_cb = {
|
||||
.init = onoff_cli_init,
|
||||
};
|
||||
|
||||
const struct bt_mesh_model_op gen_level_cli_op[] = {
|
||||
{ OP_GEN_LEVEL_STATUS, 2, gen_level_status },
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int level_cli_init(struct bt_mesh_model *model)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
if (!model->user_data) {
|
||||
BT_ERR("No Generic Level Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gen_level_cli = model->user_data;
|
||||
gen_level_cli->model = model;
|
||||
|
||||
k_sem_init(&gen_level_cli->op_sync, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
|
||||
.init = level_cli_init,
|
||||
};
|
||||
|
||||
static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
|
||||
{
|
||||
int err;
|
||||
|
@ -129,13 +172,13 @@ int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
|
||||
bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_GET);
|
||||
|
||||
err = bt_mesh_model_send(gen_onoff_cli.model, &ctx, msg, NULL, NULL);
|
||||
err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = cli_wait(&gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS);
|
||||
err = cli_wait(gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS);
|
||||
done:
|
||||
os_mbuf_free_chain(msg);
|
||||
return err;
|
||||
|
@ -165,7 +208,7 @@ int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
net_buf_simple_add_u8(msg, val);
|
||||
net_buf_simple_add_u8(msg, transaction_id);
|
||||
|
||||
err = bt_mesh_model_send(gen_onoff_cli.model, &ctx, msg, NULL, NULL);
|
||||
err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
goto done;
|
||||
|
@ -175,7 +218,7 @@ int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
goto done;
|
||||
}
|
||||
|
||||
err = cli_wait(&gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS);
|
||||
err = cli_wait(gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS);
|
||||
done:
|
||||
if (err == 0) {
|
||||
transaction_id++;
|
||||
|
@ -201,13 +244,13 @@ int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
|
||||
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_GET);
|
||||
|
||||
err = bt_mesh_model_send(gen_level_cli.model, &ctx, msg, NULL, NULL);
|
||||
err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = cli_wait(&gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS);
|
||||
err = cli_wait(gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS);
|
||||
done:
|
||||
os_mbuf_free_chain(msg);
|
||||
return err;
|
||||
|
@ -237,7 +280,7 @@ int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
net_buf_simple_add_le16(msg, val);
|
||||
net_buf_simple_add_u8(msg, transaction_id);
|
||||
|
||||
err = bt_mesh_model_send(gen_level_cli.model, &ctx, msg, NULL, NULL);
|
||||
err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
goto done;
|
||||
|
@ -247,7 +290,7 @@ int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
|||
goto done;
|
||||
}
|
||||
|
||||
err = cli_wait(&gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS);
|
||||
err = cli_wait(gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS);
|
||||
done:
|
||||
if (err == 0) {
|
||||
transaction_id++;
|
||||
|
@ -256,21 +299,3 @@ done:
|
|||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_gen_model_cli_init(struct bt_mesh_model *model, bool primary)
|
||||
{
|
||||
struct bt_mesh_gen_model_cli *cli = model->user_data;
|
||||
|
||||
BT_DBG("primary %u", primary);
|
||||
|
||||
if (!cli) {
|
||||
BT_ERR("No Generic Model Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cli->model = model;
|
||||
|
||||
k_sem_init(&cli->op_sync, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,17 +4,21 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
|
||||
|
||||
#include "mesh/model_srv.h"
|
||||
#include "mesh_priv.h"
|
||||
|
||||
static struct bt_mesh_gen_onoff_srv *gen_onoff_srv;
|
||||
static struct bt_mesh_gen_level_srv *gen_level_srv;
|
||||
static struct bt_mesh_light_lightness_srv *light_lightness_srv;
|
||||
|
||||
static void gen_onoff_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
struct bt_mesh_gen_onoff_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(3);
|
||||
u8_t *state;
|
||||
|
||||
|
@ -46,7 +50,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_gen_onoff_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
|
||||
u8_t state;
|
||||
|
||||
state = buf->om_data[0];
|
||||
|
@ -71,7 +75,7 @@ static void gen_onoff_set(struct bt_mesh_model *model,
|
|||
static void gen_level_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
struct bt_mesh_gen_level_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_gen_level_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
|
||||
s16_t *level;
|
||||
|
||||
|
@ -102,7 +106,7 @@ static void gen_level_get(struct bt_mesh_model *model,
|
|||
static void gen_level_set_unack(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf) {
|
||||
struct bt_mesh_gen_level_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_gen_level_srv *cb = model->user_data;
|
||||
s16_t level;
|
||||
|
||||
level = (s16_t) net_buf_simple_pull_le16(buf);
|
||||
|
@ -124,11 +128,11 @@ static void gen_level_set(struct bt_mesh_model *model,
|
|||
static void light_lightness_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
struct bt_mesh_light_lightness_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_light_lightness_srv *cb = model->user_data;
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
|
||||
s16_t *lightness;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
|
||||
bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS);
|
||||
lightness = net_buf_simple_add(msg, 2);
|
||||
if (cb && cb->get) {
|
||||
cb->get(model, lightness);
|
||||
|
@ -155,7 +159,7 @@ static void light_lightness_get(struct bt_mesh_model *model,
|
|||
static void light_lightness_set_unack(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf) {
|
||||
struct bt_mesh_light_lightness_srv_cb *cb = model->user_data;
|
||||
struct bt_mesh_light_lightness_srv *cb = model->user_data;
|
||||
s16_t lightness;
|
||||
|
||||
lightness = (s16_t) net_buf_simple_pull_le16(buf);
|
||||
|
@ -194,3 +198,69 @@ const struct bt_mesh_model_op light_lightness_srv_op[] = {
|
|||
{ OP_LIGHT_LIGHTNESS_SET_UNACK, 3, light_lightness_set_unack },
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int onoff_srv_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_gen_onoff_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!cfg) {
|
||||
BT_ERR("No Generic OnOff Server context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg->model = model;
|
||||
|
||||
gen_onoff_srv = cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb gen_onoff_srv_cb = {
|
||||
.init = onoff_srv_init,
|
||||
};
|
||||
|
||||
static int level_srv_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_gen_level_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!cfg) {
|
||||
BT_ERR("No Generic Level Server context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg->model = model;
|
||||
|
||||
gen_level_srv = cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb gen_level_srv_cb = {
|
||||
.init = level_srv_init,
|
||||
};
|
||||
|
||||
static int lightness_srv_init(struct bt_mesh_model *model)
|
||||
{
|
||||
struct bt_mesh_light_lightness_srv *cfg = model->user_data;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!cfg) {
|
||||
BT_ERR("No Light Lightness Server context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg->model = model;
|
||||
|
||||
light_lightness_srv = cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_cb light_lightness_srv_cb = {
|
||||
.init = lightness_srv_init,
|
||||
};
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_NET_LOG
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -13,10 +16,6 @@
|
|||
#include "os/os_mbuf.h"
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_NET)
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "crypto.h"
|
||||
#include "adv.h"
|
||||
#include "mesh_priv.h"
|
||||
|
@ -60,9 +59,7 @@
|
|||
#define FRIEND_CRED_COUNT 0
|
||||
#endif
|
||||
|
||||
#if FRIEND_CRED_COUNT > 0
|
||||
static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
|
||||
#endif
|
||||
|
||||
static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
|
||||
static u16_t msg_cache_next;
|
||||
|
@ -80,6 +77,13 @@ struct bt_mesh_net bt_mesh = {
|
|||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
},
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
.nodes = {
|
||||
[0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static u32_t dup_cache[4];
|
||||
|
@ -131,7 +135,8 @@ static bool msg_cache_match(struct bt_mesh_net_rx *rx,
|
|||
}
|
||||
|
||||
/* Add to the cache */
|
||||
msg_cache[msg_cache_next++] = hash;
|
||||
rx->msg_cache_idx = msg_cache_next++;
|
||||
msg_cache[rx->msg_cache_idx] = hash;
|
||||
msg_cache_next %= ARRAY_SIZE(msg_cache);
|
||||
|
||||
return false;
|
||||
|
@ -203,8 +208,6 @@ int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) || \
|
||||
(MYNEWT_VAL(BLE_MESH_FRIEND)))
|
||||
int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
|
||||
{
|
||||
u16_t lpn_addr, frnd_addr;
|
||||
|
@ -251,7 +254,8 @@ int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
|
|||
void friend_cred_refresh(u16_t net_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
struct friend_cred *cred = &friend_cred[i];
|
||||
|
||||
|
@ -261,6 +265,7 @@ void friend_cred_refresh(u16_t net_idx)
|
|||
sizeof(cred->cred[0]));
|
||||
}
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
int friend_cred_update(struct bt_mesh_subnet *sub)
|
||||
|
@ -268,7 +273,8 @@ int friend_cred_update(struct bt_mesh_subnet *sub)
|
|||
int err, i;
|
||||
|
||||
BT_DBG("net_idx 0x%04x", sub->net_idx);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
struct friend_cred *cred = &friend_cred[i];
|
||||
|
||||
|
@ -282,7 +288,7 @@ int friend_cred_update(struct bt_mesh_subnet *sub)
|
|||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,7 +299,8 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
|
|||
int i, err;
|
||||
|
||||
BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
|
||||
(friend_cred[i].addr == addr &&
|
||||
|
@ -302,7 +309,7 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
if (!cred) {
|
||||
BT_WARN("No free friend credential slots");
|
||||
return NULL;
|
||||
|
@ -342,7 +349,8 @@ void friend_cred_clear(struct friend_cred *cred)
|
|||
int friend_cred_del(u16_t net_idx, u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
struct friend_cred *cred = &friend_cred[i];
|
||||
|
||||
|
@ -351,7 +359,7 @@ int friend_cred_del(u16_t net_idx, u16_t addr)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -361,7 +369,8 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
|
|||
int i;
|
||||
|
||||
BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
struct friend_cred *cred = &friend_cred[i];
|
||||
|
||||
|
@ -387,16 +396,9 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
return -ENOENT;
|
||||
}
|
||||
#else
|
||||
int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
|
||||
const u8_t **enc, const u8_t **priv)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif /* FRIEND || LOW_POWER */
|
||||
|
||||
u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
|
@ -719,6 +721,14 @@ u32_t bt_mesh_next_seq(void)
|
|||
bt_mesh_store_seq();
|
||||
}
|
||||
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) &&
|
||||
bt_mesh.seq > IV_UPDATE_SEQ_LIMIT &&
|
||||
bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) {
|
||||
bt_mesh_beacon_ivu_initiator(true);
|
||||
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
|
||||
bt_mesh_net_sec_update(NULL);
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
@ -728,6 +738,7 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
|
|||
{
|
||||
const u8_t *enc, *priv;
|
||||
u32_t seq;
|
||||
u16_t dst;
|
||||
int err;
|
||||
|
||||
BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
|
||||
|
@ -753,6 +764,9 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
|
|||
buf->om_data[3] = seq >> 8;
|
||||
buf->om_data[4] = seq;
|
||||
|
||||
/* Get destination, in case it's a proxy client */
|
||||
dst = DST(buf->om_data);
|
||||
|
||||
err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
|
||||
if (err) {
|
||||
BT_ERR("encrypt failed (err %d)", err);
|
||||
|
@ -765,13 +779,11 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
|
|||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_adv_send(buf, cb, cb_data);
|
||||
|
||||
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) &&
|
||||
bt_mesh.seq > IV_UPDATE_SEQ_LIMIT) {
|
||||
bt_mesh_beacon_ivu_initiator(true);
|
||||
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
|
||||
bt_mesh_net_sec_update(NULL);
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
|
||||
bt_mesh_proxy_relay(buf, dst)) {
|
||||
send_cb_finalize(cb, cb_data);
|
||||
} else {
|
||||
bt_mesh_adv_send(buf, cb, cb_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -886,15 +898,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
|
|||
/* Notify completion if this only went
|
||||
* through the Mesh Proxy.
|
||||
*/
|
||||
if (cb) {
|
||||
if (cb->start) {
|
||||
cb->start(0, 0, cb_data);
|
||||
}
|
||||
|
||||
if (cb->end) {
|
||||
cb->end(0, cb_data);
|
||||
}
|
||||
}
|
||||
send_cb_finalize(cb, cb_data);
|
||||
|
||||
err = 0;
|
||||
goto done;
|
||||
|
@ -1019,8 +1023,6 @@ static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
|
|||
return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER) || \
|
||||
MYNEWT_VAL(BLE_MESH_FRIEND))
|
||||
static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
|
||||
size_t data_len, struct bt_mesh_net_rx *rx,
|
||||
struct os_mbuf *buf)
|
||||
|
@ -1028,7 +1030,8 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
|
|||
int i;
|
||||
|
||||
BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
|
||||
struct friend_cred *cred = &friend_cred[i];
|
||||
|
||||
|
@ -1053,10 +1056,9 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
|
@ -1073,15 +1075,14 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
|
|||
continue;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER) || \
|
||||
MYNEWT_VAL(BLE_MESH_FRIEND))
|
||||
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
|
||||
rx->friend_cred = 1;
|
||||
if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
|
||||
IS_ENABLED(CONFIG_BT_MESH_FRIEND)) &&
|
||||
!friend_decrypt(sub, data, data_len, rx, buf)) {
|
||||
rx->friend_cred = 1U;
|
||||
rx->ctx.net_idx = sub->net_idx;
|
||||
rx->sub = sub;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NID(data) == sub->keys[0].nid &&
|
||||
!net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
|
||||
|
@ -1233,6 +1234,17 @@ done:
|
|||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
void bt_mesh_net_header_parse(struct os_mbuf *buf,
|
||||
struct bt_mesh_net_rx *rx)
|
||||
{
|
||||
rx->old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01));
|
||||
rx->ctl = CTL(buf->om_data);
|
||||
rx->ctx.recv_ttl = TTL(buf->om_data);
|
||||
rx->seq = SEQ(buf->om_data);
|
||||
rx->ctx.addr = SRC(buf->om_data);
|
||||
rx->ctx.recv_dst = DST(buf->om_data);
|
||||
}
|
||||
|
||||
int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
|
||||
struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
|
@ -1303,7 +1315,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
|
|||
enum bt_mesh_net_if net_if)
|
||||
{
|
||||
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
|
||||
struct bt_mesh_net_rx rx = { .rssi = rssi };
|
||||
struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi };
|
||||
struct net_buf_simple_state state;
|
||||
|
||||
BT_DBG("rssi %d net_if %u", rssi, net_if);
|
||||
|
@ -1320,15 +1332,33 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
|
|||
/* Save the state so the buffer can later be relayed */
|
||||
net_buf_simple_save(buf, &state);
|
||||
|
||||
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY)) &&
|
||||
net_if == BT_MESH_NET_IF_PROXY) {
|
||||
bt_mesh_proxy_addr_add(data, rx.ctx.addr);
|
||||
}
|
||||
|
||||
rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) ||
|
||||
bt_mesh_elem_find(rx.ctx.recv_dst));
|
||||
|
||||
bt_mesh_trans_recv(buf, &rx);
|
||||
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY)) &&
|
||||
net_if == BT_MESH_NET_IF_PROXY) {
|
||||
bt_mesh_proxy_addr_add(data, rx.ctx.addr);
|
||||
|
||||
if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_DISABLED &&
|
||||
!rx.local_match) {
|
||||
BT_INFO("Proxy is disabled; ignoring message");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* The transport layer has indicated that it has rejected the message,
|
||||
* but would like to see it again if it is received in the future.
|
||||
* This can happen if a message is received when the device is in
|
||||
* Low Power mode, but the message was not encrypted with the friend
|
||||
* credentials. Remove it from the message cache so that we accept
|
||||
* it again in the future.
|
||||
*/
|
||||
if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) {
|
||||
BT_WARN("Removing rejected message from Network Message Cache");
|
||||
msg_cache[rx.msg_cache_idx] = 0ULL;
|
||||
/* Rewind the next index now that we're not using this entry */
|
||||
msg_cache_next = rx.msg_cache_idx;
|
||||
}
|
||||
|
||||
/* Relay if this was a group/virtual address, or if the destination
|
||||
* was neither a local element nor an LPN we're Friends for.
|
||||
|
|
|
@ -41,6 +41,13 @@ struct bt_mesh_app_key {
|
|||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_node {
|
||||
u16_t addr;
|
||||
u16_t net_idx;
|
||||
u8_t dev_key[16];
|
||||
u8_t num_elem;
|
||||
};
|
||||
|
||||
struct bt_mesh_subnet {
|
||||
u32_t beacon_sent; /* Timestamp of last sent beacon */
|
||||
u8_t beacons_last; /* Number of beacons during last
|
||||
|
@ -78,7 +85,7 @@ struct bt_mesh_subnet {
|
|||
struct bt_mesh_rpl {
|
||||
u16_t src;
|
||||
bool old_iv;
|
||||
#if defined(CONFIG_BT_SETTINGS)
|
||||
#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
|
||||
bool store;
|
||||
#endif
|
||||
u32_t seq;
|
||||
|
@ -115,6 +122,12 @@ struct bt_mesh_friend {
|
|||
|
||||
struct bt_mesh_friend_seg {
|
||||
struct net_buf_slist_t queue;
|
||||
|
||||
/* The target number of segments, i.e. not necessarily
|
||||
* the current number of segments, in the queue. This is
|
||||
* used for Friend Queue free space calculations.
|
||||
*/
|
||||
u8_t seg_count;
|
||||
} seg[FRIEND_SEG_RX];
|
||||
|
||||
struct os_mbuf *last;
|
||||
|
@ -208,7 +221,7 @@ enum {
|
|||
BT_MESH_IVU_TEST, /* IV Update test mode */
|
||||
BT_MESH_IVU_PENDING, /* Update blocked by SDU in progress */
|
||||
|
||||
/* pending storage actions */
|
||||
/* pending storage actions, must reside within first 32 flags */
|
||||
BT_MESH_RPL_PENDING,
|
||||
BT_MESH_KEYS_PENDING,
|
||||
BT_MESH_NET_PENDING,
|
||||
|
@ -217,6 +230,8 @@ enum {
|
|||
BT_MESH_HB_PUB_PENDING,
|
||||
BT_MESH_CFG_PENDING,
|
||||
BT_MESH_MOD_PENDING,
|
||||
BT_MESH_VA_PENDING,
|
||||
BT_MESH_NODES_PENDING,
|
||||
|
||||
/* Don't touch - intentionally last */
|
||||
BT_MESH_FLAG_COUNT,
|
||||
|
@ -249,6 +264,10 @@ struct bt_mesh_net {
|
|||
|
||||
u8_t dev_key[16];
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)];
|
||||
#endif
|
||||
|
||||
struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)];
|
||||
|
||||
struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)];
|
||||
|
@ -276,7 +295,7 @@ struct bt_mesh_net_rx {
|
|||
net_if:2, /* Network interface */
|
||||
local_match:1, /* Matched a local element */
|
||||
friend_match:1; /* Matched an LPN we're friends for */
|
||||
s8_t rssi;
|
||||
u16_t msg_cache_idx; /* Index of entry in message cache */
|
||||
};
|
||||
|
||||
/* Encoding context for Network/Transport data */
|
||||
|
@ -346,6 +365,8 @@ u32_t bt_mesh_next_seq(void);
|
|||
void bt_mesh_net_start(void);
|
||||
|
||||
void bt_mesh_net_init(void);
|
||||
void bt_mesh_net_header_parse(struct os_mbuf *buf,
|
||||
struct bt_mesh_net_rx *rx);
|
||||
|
||||
/* Friendship Credential Management */
|
||||
struct friend_cred {
|
||||
|
@ -372,4 +393,20 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
|
|||
void friend_cred_clear(struct friend_cred *cred);
|
||||
int friend_cred_del(u16_t net_idx, u16_t addr);
|
||||
|
||||
static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb->start) {
|
||||
cb->start(0, 0, cb_data);
|
||||
}
|
||||
|
||||
if (cb->end) {
|
||||
cb->end(0, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
#include "access.h"
|
||||
#include "settings.h"
|
||||
|
||||
/*
|
||||
* Check if an address range from addr_start for addr_start + num_elem - 1 is
|
||||
* free for use. When a conflict is found, next will be set to the next address
|
||||
* available after the conflicting range and -EAGAIN will be returned.
|
||||
*/
|
||||
static int addr_is_free(u16_t addr_start, u8_t num_elem, u16_t *next)
|
||||
{
|
||||
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
|
||||
u16_t addr_end = addr_start + num_elem - 1;
|
||||
u16_t other_start, other_end;
|
||||
int i;
|
||||
|
||||
if (comp == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
|
||||
!BT_MESH_ADDR_IS_UNICAST(addr_end) ||
|
||||
num_elem == 0 || next == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
other_start = bt_mesh_primary_addr();
|
||||
other_end = other_start + comp->elem_count - 1;
|
||||
|
||||
/* Compare with local element addresses */
|
||||
if (!(addr_end < other_start || addr_start > other_end)) {
|
||||
*next = other_end + 1;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
|
||||
struct bt_mesh_node *node = &bt_mesh.nodes[i];
|
||||
|
||||
if (node->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
other_start = node->addr;
|
||||
other_end = other_start + node->num_elem - 1;
|
||||
|
||||
if (!(addr_end < other_start || addr_start > other_end)) {
|
||||
*next = other_end + 1;
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the lowest possible starting address that can fit num_elem elements. If
|
||||
* a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
|
||||
* returned. Otherwise the first address in the range is returned.
|
||||
*
|
||||
* NOTE: This is quite an ineffective algorithm as it might need to look
|
||||
* through the array of nodes N+2 times. A more effective algorithm
|
||||
* could be used if the nodes were stored in a sorted list.
|
||||
*/
|
||||
static u16_t find_lowest_free_addr(u8_t num_elem)
|
||||
{
|
||||
u16_t addr = 1, next;
|
||||
int err, i;
|
||||
|
||||
/*
|
||||
* It takes a maximum of node count + 2 to find a free address if there
|
||||
* is any. +1 for our own address and +1 for making sure that the
|
||||
* address range is valid.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes) + 2; ++i) {
|
||||
err = addr_is_free(addr, num_elem, &next);
|
||||
if (err == 0) {
|
||||
break;
|
||||
} else if (err != -EAGAIN) {
|
||||
addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
break;
|
||||
}
|
||||
|
||||
addr = next;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct bt_mesh_node *bt_mesh_node_find(u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
|
||||
struct bt_mesh_node *node = &bt_mesh.nodes[i];
|
||||
|
||||
if (addr >= node->addr &&
|
||||
addr <= node->addr + node->num_elem - 1) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem,
|
||||
u16_t net_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
addr = find_lowest_free_addr(num_elem);
|
||||
if (addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (!addr_is_free(addr, num_elem, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) {
|
||||
struct bt_mesh_node *node = &bt_mesh.nodes[i];
|
||||
|
||||
if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
node->addr = addr;
|
||||
node->num_elem = num_elem;
|
||||
node->net_idx = net_idx;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_mesh_node_del(struct bt_mesh_node *node, bool store)
|
||||
{
|
||||
BT_DBG("Node addr 0x%04x store %u", node->addr, store);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
|
||||
bt_mesh_clear_node(node);
|
||||
}
|
||||
|
||||
node->addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
(void)memset(node->dev_key, 0, sizeof(node->dev_key));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
struct bt_mesh_node *bt_mesh_node_find(u16_t addr);
|
||||
struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem,
|
||||
u16_t net_idx);
|
||||
void bt_mesh_node_del(struct bt_mesh_node *node, bool store);
|
|
@ -5,14 +5,14 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROV)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_PROV))
|
||||
#include "host/ble_hs_log.h"
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
|||
#include "proxy.h"
|
||||
#include "prov.h"
|
||||
#include "testing.h"
|
||||
#include "settings.h"
|
||||
#include "nodes.h"
|
||||
|
||||
/* 3 transmissions, 20ms interval */
|
||||
#define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
|
||||
|
@ -69,6 +71,8 @@
|
|||
#define PROV_COMPLETE 0x08
|
||||
#define PROV_FAILED 0x09
|
||||
|
||||
#define PROV_NO_PDU 0xff
|
||||
|
||||
#define PROV_ALG_P256 0x00
|
||||
|
||||
#define GPCF(gpc) (gpc & 0x03)
|
||||
|
@ -98,22 +102,40 @@
|
|||
#define XACT_NVAL 0xff
|
||||
|
||||
enum {
|
||||
REMOTE_PUB_KEY, /* Remote key has been received */
|
||||
WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
|
||||
LINK_ACTIVE, /* Link has been opened */
|
||||
HAVE_DHKEY, /* DHKey has been calculated */
|
||||
SEND_CONFIRM, /* Waiting to send Confirm value */
|
||||
LINK_ACK_RECVD, /* Ack for link has been received */
|
||||
LINK_CLOSING, /* Link is closing down */
|
||||
SEND_PUB_KEY, /* Waiting to send PubKey */
|
||||
WAIT_NUMBER, /* Waiting for number input from user */
|
||||
WAIT_STRING, /* Waiting for string input from user */
|
||||
NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
|
||||
LINK_INVALID, /* Error occurred during provisioning */
|
||||
PROVISIONER, /* The link was opened as provisioner */
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
#define PROVISIONER_LINK 1
|
||||
#else
|
||||
#define PROVISIONER_LINK 0
|
||||
#endif
|
||||
|
||||
struct provisioner_link {
|
||||
struct bt_mesh_node *node;
|
||||
u16_t addr;
|
||||
u16_t net_idx;
|
||||
u8_t attention_duration;
|
||||
};
|
||||
|
||||
struct prov_link {
|
||||
ATOMIC_DEFINE(flags, NUM_FLAGS);
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
|
||||
uint16_t conn_handle; /* GATT connection */
|
||||
#endif
|
||||
struct provisioner_link provisioner[PROVISIONER_LINK];
|
||||
|
||||
u8_t dhkey[32]; /* Calculated DHKey */
|
||||
u8_t expect; /* Next expected PDU */
|
||||
|
||||
|
@ -168,6 +190,7 @@ struct prov_rx {
|
|||
|
||||
#define RETRANSMIT_TIMEOUT K_MSEC(500)
|
||||
#define BUF_TIMEOUT K_MSEC(400)
|
||||
#define CLOSING_TIMEOUT K_SECONDS(3)
|
||||
#define TRANSACTION_TIMEOUT K_SECONDS(30)
|
||||
#define PROTOCOL_TIMEOUT K_SECONDS(60)
|
||||
|
||||
|
@ -200,6 +223,11 @@ static int reset_state(void)
|
|||
bt_mesh_attention(NULL, 0);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
link.provisioner->node != NULL) {
|
||||
bt_mesh_node_del(link.provisioner->node, false);
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
/* Clear everything except the retransmit and protocol timer
|
||||
* delayed work objects.
|
||||
|
@ -210,6 +238,9 @@ static int reset_state(void)
|
|||
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
|
||||
link.rx.buf = bt_mesh_proxy_get_buf();
|
||||
#else
|
||||
if (!rx_buf) {
|
||||
rx_buf = NET_BUF_SIMPLE(65);
|
||||
}
|
||||
net_buf_simple_init(rx_buf, 0);
|
||||
link.rx.buf = rx_buf;
|
||||
#endif /* PB_GATT */
|
||||
|
@ -364,7 +395,7 @@ static void send_reliable(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int bearer_ctl_send(u8_t op, void *data, u8_t data_len)
|
||||
static int bearer_ctl_send(u8_t op, const void *data, u8_t data_len)
|
||||
{
|
||||
struct os_mbuf *buf;
|
||||
|
||||
|
@ -402,11 +433,20 @@ static u8_t last_seg(u8_t len)
|
|||
|
||||
static inline u8_t next_transaction_id(void)
|
||||
{
|
||||
if (link.tx.id != 0 && link.tx.id != 0xFF) {
|
||||
return ++link.tx.id;
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
if (link.tx.id != 0x7F) {
|
||||
link.tx.id++;
|
||||
} else {
|
||||
link.tx.id = 0;
|
||||
}
|
||||
} else {
|
||||
if (link.tx.id != 0U && link.tx.id != 0xFF) {
|
||||
link.tx.id++;
|
||||
} else {
|
||||
link.tx.id = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
link.tx.id = 0x80;
|
||||
return link.tx.id;
|
||||
}
|
||||
|
||||
|
@ -576,10 +616,63 @@ done:
|
|||
os_mbuf_free_chain(buf);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_ADV)
|
||||
static void send_invite(void)
|
||||
{
|
||||
struct os_mbuf *inv = PROV_BUF(2);
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
prov_buf_init(inv, PROV_INVITE);
|
||||
net_buf_simple_add_u8(inv, link.provisioner->attention_duration);
|
||||
|
||||
link.conf_inputs[0] = link.provisioner->attention_duration;
|
||||
|
||||
if (prov_send(inv)) {
|
||||
BT_ERR("Failed to send invite");
|
||||
goto done;
|
||||
}
|
||||
|
||||
link.expect = PROV_CAPABILITIES;
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(inv);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void send_start(void)
|
||||
{
|
||||
struct os_mbuf *start = PROV_BUF(6);
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
prov_buf_init(start, PROV_START);
|
||||
|
||||
net_buf_simple_add_u8(start, PROV_ALG_P256);
|
||||
net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
|
||||
net_buf_simple_add_u8(start, AUTH_METHOD_NO_OOB);
|
||||
memset(link.auth, 0, sizeof(link.auth));
|
||||
|
||||
net_buf_simple_add_u8(start, 0); /* Auth Action */
|
||||
net_buf_simple_add_u8(start, 0); /* Auth Size */
|
||||
|
||||
memcpy(&link.conf_inputs[12], &start->om_data[1], 5);
|
||||
|
||||
if (prov_send(start)) {
|
||||
BT_ERR("Failed to send start");
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(start);
|
||||
}
|
||||
|
||||
static void prov_capabilities(const u8_t *data)
|
||||
{
|
||||
u16_t algorithms, output_action, input_action;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Elements: %u", data[0]);
|
||||
|
||||
algorithms = sys_get_be16(&data[1]);
|
||||
|
@ -596,6 +689,26 @@ static void prov_capabilities(const u8_t *data)
|
|||
|
||||
input_action = sys_get_be16(&data[9]);
|
||||
BT_DBG("Input OOB Action: 0x%04x", input_action);
|
||||
|
||||
if (data[0] == 0) {
|
||||
BT_ERR("Invalid number of elements");
|
||||
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
|
||||
return;
|
||||
}
|
||||
|
||||
link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr,
|
||||
data[0],
|
||||
link.provisioner->net_idx);
|
||||
if (link.provisioner->node == NULL) {
|
||||
prov_send_fail_msg(PROV_ERR_RESOURCES);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&link.conf_inputs[1], data, 11);
|
||||
|
||||
atomic_set_bit(link.flags, SEND_PUB_KEY);
|
||||
|
||||
send_start();
|
||||
}
|
||||
|
||||
static bt_mesh_output_action_t output_action(u8_t action)
|
||||
|
@ -669,6 +782,8 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE);
|
||||
|
||||
if (output == BT_MESH_DISPLAY_STRING) {
|
||||
unsigned char str[9];
|
||||
u8_t i;
|
||||
|
@ -810,7 +925,11 @@ static void send_confirm(void)
|
|||
goto done;
|
||||
}
|
||||
|
||||
link.expect = PROV_RANDOM;
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
link.expect = PROV_CONFIRM;
|
||||
} else {
|
||||
link.expect = PROV_RANDOM;
|
||||
}
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(cfm);
|
||||
|
@ -824,6 +943,7 @@ static void send_input_complete(void)
|
|||
if (prov_send(buf)) {
|
||||
BT_ERR("Failed to send Provisioning Input Complete");
|
||||
}
|
||||
link.expect = PROV_CONFIRM;
|
||||
|
||||
os_mbuf_free_chain(buf);
|
||||
}
|
||||
|
@ -840,14 +960,6 @@ int bt_mesh_input_number(u32_t num)
|
|||
|
||||
send_input_complete();
|
||||
|
||||
if (!atomic_test_bit(link.flags, HAVE_DHKEY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) {
|
||||
send_confirm();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -863,43 +975,9 @@ int bt_mesh_input_string(const char *str)
|
|||
|
||||
send_input_complete();
|
||||
|
||||
if (!atomic_test_bit(link.flags, HAVE_DHKEY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) {
|
||||
send_confirm();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prov_dh_key_cb(const u8_t key[32])
|
||||
{
|
||||
BT_DBG("%p", key);
|
||||
|
||||
if (!key) {
|
||||
BT_ERR("DHKey generation failed");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(link.dhkey, key, 32);
|
||||
|
||||
BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
|
||||
|
||||
atomic_set_bit(link.flags, HAVE_DHKEY);
|
||||
|
||||
if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
|
||||
atomic_test_bit(link.flags, WAIT_STRING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) {
|
||||
send_confirm();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_pub_key(void)
|
||||
{
|
||||
struct os_mbuf *buf = PROV_BUF(65);
|
||||
|
@ -914,56 +992,112 @@ static void send_pub_key(void)
|
|||
|
||||
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
|
||||
|
||||
/* Copy remote key in little-endian for bt_dh_key_gen().
|
||||
* X and Y halves are swapped independently. Use response
|
||||
* buffer as a temporary storage location. The bt_dh_key_gen()
|
||||
* will also take care of validating the remote public key.
|
||||
*/
|
||||
sys_memcpy_swap(buf->om_data, &link.conf_inputs[17], 32);
|
||||
sys_memcpy_swap(&buf->om_data[32], &link.conf_inputs[49], 32);
|
||||
|
||||
if (bt_dh_key_gen(buf->om_data, prov_dh_key_cb)) {
|
||||
BT_ERR("Failed to generate DHKey");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
prov_buf_init(buf, PROV_PUB_KEY);
|
||||
|
||||
/* Swap X and Y halves independently to big-endian */
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
|
||||
sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
|
||||
|
||||
memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
/* PublicKeyProvisioner */
|
||||
memcpy(&link.conf_inputs[17], &buf->om_data[1], 64);
|
||||
} else {
|
||||
/* PublicKeyRemote */
|
||||
memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
|
||||
}
|
||||
|
||||
if (prov_send(buf)) {
|
||||
BT_ERR("Failed to send Public Key");
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
link.expect = PROV_CONFIRM;
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
link.expect = PROV_PUB_KEY;
|
||||
} else {
|
||||
if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
|
||||
atomic_test_bit(link.flags, WAIT_STRING)) {
|
||||
link.expect = PROV_NO_PDU; /* Wait for input */
|
||||
} else {
|
||||
link.expect = PROV_CONFIRM;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(buf);
|
||||
}
|
||||
|
||||
static void prov_dh_key_cb(const u8_t dhkey[32])
|
||||
{
|
||||
BT_DBG("%p", dhkey);
|
||||
|
||||
if (!dhkey) {
|
||||
BT_ERR("DHKey generation failed");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(link.dhkey, dhkey, 32);
|
||||
|
||||
BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
|
||||
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
send_confirm();
|
||||
} else {
|
||||
send_pub_key();
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_dh_key_gen(void)
|
||||
{
|
||||
u8_t remote_pk_le[64], *remote_pk;
|
||||
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
remote_pk = &link.conf_inputs[81];
|
||||
} else {
|
||||
remote_pk = &link.conf_inputs[17];
|
||||
}
|
||||
|
||||
/* Copy remote key in little-endian for bt_dh_key_gen().
|
||||
* X and Y halves are swapped independently. The bt_dh_key_gen()
|
||||
* will also take care of validating the remote public key.
|
||||
*/
|
||||
sys_memcpy_swap(remote_pk_le, remote_pk, 32);
|
||||
sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
|
||||
|
||||
if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
|
||||
BT_ERR("Failed to generate DHKey");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_pub_key(const u8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
|
||||
|
||||
memcpy(&link.conf_inputs[17], data, 64);
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
/* PublicKeyDevice */
|
||||
memcpy(&link.conf_inputs[81], data, 64);
|
||||
|
||||
if (!bt_pub_key_get()) {
|
||||
/* Clear retransmit timer */
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
prov_clear_tx();
|
||||
#endif
|
||||
atomic_set_bit(link.flags, REMOTE_PUB_KEY);
|
||||
BT_WARN("Waiting for local public key");
|
||||
return;
|
||||
} else {
|
||||
/* PublicKeyProvisioner */
|
||||
memcpy(&link.conf_inputs[17], data, 64);
|
||||
|
||||
if (!bt_pub_key_get()) {
|
||||
/* Clear retransmit timer */
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
prov_clear_tx();
|
||||
#endif
|
||||
|
||||
atomic_set_bit(link.flags, WAIT_PUB_KEY);
|
||||
BT_WARN("Waiting for local public key");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
send_pub_key();
|
||||
prov_dh_key_gen();
|
||||
}
|
||||
|
||||
static void pub_key_ready(const u8_t *pkey)
|
||||
|
@ -975,53 +1109,145 @@ static void pub_key_ready(const u8_t *pkey)
|
|||
|
||||
BT_DBG("Local public key ready");
|
||||
|
||||
if (atomic_test_and_clear_bit(link.flags, REMOTE_PUB_KEY)) {
|
||||
send_pub_key();
|
||||
if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) {
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
send_pub_key();
|
||||
} else {
|
||||
prov_dh_key_gen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_input_complete(void)
|
||||
{
|
||||
if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) &&
|
||||
prov->input_complete) {
|
||||
prov->input_complete();
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_input_complete(const u8_t *data)
|
||||
{
|
||||
BT_DBG("");
|
||||
notify_input_complete();
|
||||
}
|
||||
|
||||
static void prov_confirm(const u8_t *data)
|
||||
static void send_prov_data(void)
|
||||
{
|
||||
BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
|
||||
struct os_mbuf *pdu = PROV_BUF(34);
|
||||
struct bt_mesh_subnet *sub;
|
||||
u8_t session_key[16];
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
memcpy(link.conf, data, 16);
|
||||
|
||||
if (!atomic_test_bit(link.flags, HAVE_DHKEY)) {
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
prov_clear_tx();
|
||||
#endif
|
||||
atomic_set_bit(link.flags, SEND_CONFIRM);
|
||||
} else {
|
||||
send_confirm();
|
||||
}
|
||||
}
|
||||
|
||||
static void prov_random(const u8_t *data)
|
||||
{
|
||||
struct os_mbuf *rnd = PROV_BUF(16);
|
||||
u8_t conf_verify[16];
|
||||
|
||||
BT_DBG("Remote Random: %s", bt_hex(data, 16));
|
||||
|
||||
if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
|
||||
BT_ERR("Unable to calculate confirmation verification");
|
||||
err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session key");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (memcmp(conf_verify, link.conf, 16)) {
|
||||
BT_ERR("Invalid confirmation value");
|
||||
BT_DBG("Received: %s", bt_hex(link.conf, 16));
|
||||
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
|
||||
prov_send_fail_msg(PROV_ERR_CFM_FAILED);
|
||||
BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
|
||||
|
||||
err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate session nonce");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
goto done;
|
||||
}
|
||||
|
||||
BT_DBG("Nonce: %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_dev_key(link.dhkey, link.prov_salt,
|
||||
link.provisioner->node->dev_key);
|
||||
if (err) {
|
||||
BT_ERR("Unable to generate device key");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
goto done;
|
||||
}
|
||||
|
||||
BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16));
|
||||
|
||||
sub = bt_mesh_subnet_get(link.provisioner->node->net_idx);
|
||||
if (sub == NULL) {
|
||||
BT_ERR("No subnet with net_idx %u",
|
||||
link.provisioner->node->net_idx);
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
goto done;
|
||||
}
|
||||
|
||||
prov_buf_init(pdu, PROV_DATA);
|
||||
net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net, 16);
|
||||
net_buf_simple_add_be16(pdu, link.provisioner->node->net_idx);
|
||||
net_buf_simple_add_u8(pdu, bt_mesh_net_flags(sub));
|
||||
net_buf_simple_add_be32(pdu, bt_mesh.iv_index);
|
||||
net_buf_simple_add_be16(pdu, link.provisioner->node->addr);
|
||||
net_buf_simple_add(pdu, 8); /* For MIC */
|
||||
|
||||
BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
|
||||
link.provisioner->node->net_idx, bt_mesh.iv_index,
|
||||
link.provisioner->node->addr);
|
||||
|
||||
err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
|
||||
&pdu->om_data[1]);
|
||||
if (err) {
|
||||
BT_ERR("Unable to encrypt provisioning data");
|
||||
prov_send_fail_msg(PROV_ERR_DECRYPT);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (prov_send(pdu)) {
|
||||
BT_ERR("Failed to send Provisioning Data");
|
||||
goto done;
|
||||
}
|
||||
|
||||
link.expect = PROV_COMPLETE;
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(pdu);
|
||||
}
|
||||
|
||||
static void prov_complete(const u8_t *data)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct bt_mesh_node *node = link.provisioner->node;
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_ADV)
|
||||
u8_t reason = CLOSE_REASON_SUCCESS;
|
||||
#endif
|
||||
|
||||
BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
|
||||
bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
|
||||
node->addr);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_node(node);
|
||||
}
|
||||
|
||||
link.provisioner->node = NULL;
|
||||
link.expect = PROV_NO_PDU;
|
||||
atomic_set_bit(link.flags, LINK_CLOSING);
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_ADV)
|
||||
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
|
||||
#endif
|
||||
|
||||
bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem);
|
||||
|
||||
/*
|
||||
* According to mesh profile spec (5.3.1.4.3), the close message should
|
||||
* be restransmitted at least three times. Retransmit the LINK_CLOSE
|
||||
* message until CLOSING_TIMEOUT has elapsed instead of resetting the
|
||||
* link here.
|
||||
*/
|
||||
}
|
||||
|
||||
static void send_random(void)
|
||||
{
|
||||
struct os_mbuf *rnd = PROV_BUF(17);
|
||||
|
||||
prov_buf_init(rnd, PROV_RANDOM);
|
||||
net_buf_simple_add_mem(rnd, link.rand, 16);
|
||||
|
||||
|
@ -1030,19 +1256,75 @@ static void prov_random(const u8_t *data)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_salt(link.conf_salt, data, link.rand,
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
link.expect = PROV_RANDOM;
|
||||
} else {
|
||||
link.expect = PROV_DATA;
|
||||
}
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(rnd);
|
||||
}
|
||||
|
||||
static void prov_random(const u8_t *data)
|
||||
{
|
||||
u8_t conf_verify[16];
|
||||
const u8_t *prov_rand, *dev_rand;
|
||||
|
||||
BT_DBG("Remote Random: %s", bt_hex(data, 16));
|
||||
|
||||
if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
|
||||
BT_ERR("Unable to calculate confirmation verification");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(conf_verify, link.conf, 16)) {
|
||||
BT_ERR("Invalid confirmation value");
|
||||
BT_DBG("Received: %s", bt_hex(link.conf, 16));
|
||||
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
|
||||
prov_send_fail_msg(PROV_ERR_CFM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
prov_rand = link.rand;
|
||||
dev_rand = data;
|
||||
} else {
|
||||
prov_rand = data;
|
||||
dev_rand = link.rand;
|
||||
}
|
||||
|
||||
if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand,
|
||||
link.prov_salt)) {
|
||||
BT_ERR("Failed to generate provisioning salt");
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
goto done;
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
|
||||
|
||||
link.expect = PROV_DATA;
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
send_prov_data();
|
||||
} else {
|
||||
send_random();
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(rnd);
|
||||
static void prov_confirm(const u8_t *data)
|
||||
{
|
||||
BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
|
||||
|
||||
memcpy(link.conf, data, 16);
|
||||
|
||||
notify_input_complete();
|
||||
|
||||
if (atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
send_random();
|
||||
} else {
|
||||
send_confirm();
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_pb_gatt(void)
|
||||
|
@ -1119,7 +1401,7 @@ static void prov_data(const u8_t *data)
|
|||
}
|
||||
|
||||
/* Ignore any further PDUs on this link */
|
||||
link.expect = 0;
|
||||
link.expect = PROV_NO_PDU;
|
||||
|
||||
/* Store info, since bt_mesh_provision() will end up clearing it */
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
|
||||
|
@ -1145,11 +1427,6 @@ done:
|
|||
os_mbuf_free_chain(msg);
|
||||
}
|
||||
|
||||
static void prov_complete(const u8_t *data)
|
||||
{
|
||||
BT_DBG("");
|
||||
}
|
||||
|
||||
static void prov_failed(const u8_t *data)
|
||||
{
|
||||
BT_WARN("Error: 0x%02x", data[0]);
|
||||
|
@ -1174,7 +1451,7 @@ static const struct {
|
|||
#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
|
||||
static void prov_retransmit(struct ble_npl_event *work)
|
||||
{
|
||||
int i;
|
||||
int i, timeout;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
|
@ -1183,7 +1460,13 @@ static void prov_retransmit(struct ble_npl_event *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) {
|
||||
if (atomic_test_bit(link.flags, LINK_CLOSING)) {
|
||||
timeout = CLOSING_TIMEOUT;
|
||||
} else {
|
||||
timeout = TRANSACTION_TIMEOUT;
|
||||
}
|
||||
|
||||
if (k_uptime_get() - link.tx.start > timeout) {
|
||||
BT_WARN("Giving up transaction");
|
||||
reset_adv_link();
|
||||
return;
|
||||
|
@ -1248,12 +1531,26 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
|
|||
bearer_ctl_send(LINK_ACK, NULL, 0);
|
||||
|
||||
link.expect = PROV_INVITE;
|
||||
|
||||
}
|
||||
|
||||
static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
BT_DBG("Link ack: len %u", buf->om_len);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
atomic_test_bit(link.flags, PROVISIONER)) {
|
||||
if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
prov_clear_tx();
|
||||
|
||||
if (prov->link_open) {
|
||||
prov->link_open(BT_MESH_PROV_ADV);
|
||||
}
|
||||
|
||||
send_invite();
|
||||
}
|
||||
}
|
||||
|
||||
static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
|
||||
|
@ -1398,7 +1695,21 @@ static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
|
|||
}
|
||||
|
||||
if (rx->xact_id == link.tx.id) {
|
||||
prov_clear_tx();
|
||||
/* Don't clear resending of LINK_CLOSE messages */
|
||||
if (!atomic_test_bit(link.flags, LINK_CLOSING)) {
|
||||
prov_clear_tx();
|
||||
}
|
||||
|
||||
/* Send the PubKey when the the Start message is ACK'ed */
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
atomic_test_and_clear_bit(link.flags, SEND_PUB_KEY)) {
|
||||
if (!bt_pub_key_get()) {
|
||||
atomic_set_bit(link.flags, WAIT_PUB_KEY);
|
||||
BT_WARN("Waiting for local public key");
|
||||
} else {
|
||||
send_pub_key();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1456,9 +1767,9 @@ static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
|
|||
}
|
||||
|
||||
static const struct {
|
||||
void (*const func)(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
const u8_t require_link;
|
||||
const u8_t min_len;
|
||||
void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
|
||||
bool require_link;
|
||||
u8_t min_len;
|
||||
} gen_prov[] = {
|
||||
{ gen_prov_start, true, 3 },
|
||||
{ gen_prov_ack, true, 0 },
|
||||
|
@ -1510,6 +1821,31 @@ void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
|
|||
|
||||
gen_prov_recv(&rx, buf);
|
||||
}
|
||||
|
||||
int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration)
|
||||
{
|
||||
BT_DBG("uuid %s", bt_hex(uuid, 16));
|
||||
|
||||
if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
atomic_set_bit(link.flags, PROVISIONER);
|
||||
|
||||
bt_rand(&link.id, sizeof(link.id));
|
||||
link.tx.id = 0x7F;
|
||||
link.provisioner->addr = addr;
|
||||
link.provisioner->net_idx = net_idx;
|
||||
link.provisioner->attention_duration = attention_duration;
|
||||
|
||||
net_buf_simple_init(link.rx.buf, 0);
|
||||
|
||||
bearer_ctl_send(LINK_OPEN, uuid, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
|
||||
|
||||
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
|
||||
|
@ -1655,6 +1991,13 @@ void bt_mesh_prov_complete(u16_t net_idx, u16_t addr)
|
|||
}
|
||||
}
|
||||
|
||||
void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
|
||||
{
|
||||
if (prov->node_added) {
|
||||
prov->node_added(net_idx, addr, num_elem);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_prov_reset(void)
|
||||
{
|
||||
if (prov->reset) {
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "mesh/mesh.h"
|
||||
#include "../src/ble_hs_conn_priv.h"
|
||||
|
||||
int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration);
|
||||
|
||||
void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
|
||||
|
||||
bool bt_prov_active(void);
|
||||
|
@ -28,6 +31,7 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
|
|||
void bt_mesh_prov_reset_link(void);
|
||||
|
||||
void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
|
||||
void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem);
|
||||
void bt_mesh_prov_reset(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,13 +7,11 @@
|
|||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROXY)
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_PROXY))
|
||||
#include "host/ble_hs_log.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
#include "../../host/src/ble_hs_priv.h"
|
||||
|
@ -654,10 +652,7 @@ static void proxy_connected(uint16_t conn_handle)
|
|||
static void proxy_disconnected(uint16_t conn_handle, int reason)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_INFO("conn_handle %d reason %d", conn_handle, reason);
|
||||
|
||||
conn_count--;
|
||||
bool disconnected = false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||
struct bt_mesh_proxy_client *client = &clients[i];
|
||||
|
@ -670,11 +665,16 @@ static void proxy_disconnected(uint16_t conn_handle, int reason)
|
|||
|
||||
k_delayed_work_cancel(&client->sar_timer);
|
||||
client->conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
conn_count--;
|
||||
disconnected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_adv_update();
|
||||
if (disconnected) {
|
||||
BT_INFO("conn_handle %d reason %d", conn_handle, reason);
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
}
|
||||
|
||||
struct os_mbuf *bt_mesh_proxy_get_buf(void)
|
||||
|
@ -740,7 +740,7 @@ int bt_mesh_proxy_prov_enable(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_proxy_prov_disable(void)
|
||||
int bt_mesh_proxy_prov_disable(bool disconnect)
|
||||
{
|
||||
uint16_t handle;
|
||||
int rc;
|
||||
|
@ -767,13 +767,23 @@ int bt_mesh_proxy_prov_disable(void)
|
|||
for (i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||
struct bt_mesh_proxy_client *client = &clients[i];
|
||||
|
||||
if ((client->conn_handle != BLE_HS_CONN_HANDLE_NONE)
|
||||
&& (client->filter_type == PROV)) {
|
||||
if ((client->conn_handle == BLE_HS_CONN_HANDLE_NONE)
|
||||
|| (client->filter_type != PROV)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (disconnect) {
|
||||
rc = ble_gap_terminate(client->conn_handle,
|
||||
BLE_ERR_REM_USER_CONN_TERM);
|
||||
assert(rc == 0);
|
||||
} else {
|
||||
bt_mesh_pb_gatt_close(client->conn_handle);
|
||||
client->filter_type = NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_adv_update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
|
||||
|
@ -907,16 +917,6 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
|
|||
|
||||
BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
|
||||
|
||||
if (client->filter_type == WHITELIST) {
|
||||
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
|
||||
if (client->filter[i] == addr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (client->filter_type == BLACKLIST) {
|
||||
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
|
||||
if (client->filter[i] == addr) {
|
||||
|
@ -927,6 +927,18 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (addr == BT_MESH_ADDR_ALL_NODES) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (client->filter_type == WHITELIST) {
|
||||
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
|
||||
if (client->filter[i] == addr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1146,7 +1158,7 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub)
|
|||
}
|
||||
|
||||
return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
|
||||
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
|
||||
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static struct bt_mesh_subnet *next_sub(void)
|
||||
|
@ -1189,7 +1201,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
|||
BT_DBG("");
|
||||
|
||||
if (conn_count == CONFIG_BT_MAX_CONN) {
|
||||
BT_WARN("Connectable advertising deferred (max connections)");
|
||||
BT_DBG("Connectable advertising deferred (max connections)");
|
||||
return remaining;
|
||||
}
|
||||
|
||||
|
@ -1213,11 +1225,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
|
|||
}
|
||||
|
||||
if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) {
|
||||
if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
|
||||
net_id_adv(sub);
|
||||
} else {
|
||||
return gatt_proxy_advertise(next_sub());
|
||||
}
|
||||
net_id_adv(sub);
|
||||
}
|
||||
|
||||
subnet_count = sub_count();
|
||||
|
@ -1353,12 +1361,39 @@ void bt_mesh_proxy_adv_stop(void)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg)
|
||||
static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/* When EXT ADV is enabled then mesh proxy is connected
|
||||
* when proxy advertising instance is completed.
|
||||
* Therefore no need to handle BLE_GAP_EVENT_CONNECT
|
||||
*/
|
||||
if (event->type == BLE_GAP_EVENT_ADV_COMPLETE) {
|
||||
/* Reason 0 means advertising has been completed because
|
||||
* connection has been established
|
||||
*/
|
||||
if (event->adv_complete.reason != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->adv_complete.instance != BT_MESH_ADV_GATT_INST) {
|
||||
return;
|
||||
}
|
||||
|
||||
proxy_connected(event->adv_complete.conn_handle);
|
||||
}
|
||||
#else
|
||||
if (event->type == BLE_GAP_EVENT_CONNECT) {
|
||||
proxy_connected(event->connect.conn_handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
if ((event->type == BLE_GAP_EVENT_CONNECT) ||
|
||||
(event->type == BLE_GAP_EVENT_ADV_COMPLETE)) {
|
||||
ble_mesh_handle_connect(event, arg);
|
||||
} else if (event->type == BLE_GAP_EVENT_DISCONNECT) {
|
||||
proxy_disconnected(event->disconnect.conn.conn_handle,
|
||||
event->disconnect.reason);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg);
|
||||
|
||||
int bt_mesh_proxy_prov_enable(void);
|
||||
int bt_mesh_proxy_prov_disable(void);
|
||||
int bt_mesh_proxy_prov_disable(bool disconnect);
|
||||
|
||||
int bt_mesh_proxy_gatt_enable(void);
|
||||
int bt_mesh_proxy_gatt_disable(void);
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_SETTINGS_LOG
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
|
||||
|
||||
#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_SETTINGS)
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
#include "mesh/glue.h"
|
||||
#include "net.h"
|
||||
|
@ -19,6 +18,7 @@
|
|||
#include "foundation.h"
|
||||
#include "proxy.h"
|
||||
#include "settings.h"
|
||||
#include "nodes.h"
|
||||
|
||||
#include "config/config.h"
|
||||
|
||||
|
@ -105,6 +105,31 @@ struct mod_pub_val {
|
|||
cred:1;
|
||||
};
|
||||
|
||||
/* Virtual Address information */
|
||||
struct va_val {
|
||||
u16_t ref;
|
||||
u16_t addr;
|
||||
u8_t uuid[16];
|
||||
} __packed;
|
||||
|
||||
/* Node storage information */
|
||||
struct node_val {
|
||||
u16_t net_idx;
|
||||
u8_t dev_key[16];
|
||||
u8_t num_elem;
|
||||
} __packed;
|
||||
|
||||
struct node_update {
|
||||
u16_t addr;
|
||||
bool clear;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT];
|
||||
#else
|
||||
static struct node_update node_updates[0];
|
||||
#endif
|
||||
|
||||
/* We need this so we don't overwrite app-hardcoded values in case FCB
|
||||
* contains a history of changes but then has a NULL at the end.
|
||||
*/
|
||||
|
@ -658,6 +683,14 @@ static int mod_set(bool vnd, int argc, char **argv, char *val)
|
|||
return mod_set_pub(mod, val);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "data")) {
|
||||
mod->flags |= BT_MESH_MOD_DATA_PRESENT;
|
||||
|
||||
if (mod->cb && mod->cb->settings_set) {
|
||||
return mod->cb->settings_set(mod, val);
|
||||
}
|
||||
}
|
||||
|
||||
BT_WARN("Unknown module key %s", argv[1]);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -672,6 +705,115 @@ static int vnd_mod_set(int argc, char **argv, char *val)
|
|||
return mod_set(true, argc, argv, val);
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
static int va_set(int argc, char **argv, char *val)
|
||||
{
|
||||
struct va_val va;
|
||||
struct label *lab;
|
||||
u16_t index;
|
||||
int len, err;
|
||||
|
||||
if (argc < 1) {
|
||||
BT_ERR("Insufficient number of arguments");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
index = strtol(argv[0], NULL, 16);
|
||||
|
||||
if (val == NULL) {
|
||||
BT_WARN("Mesh Virtual Address length = 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = settings_bytes_from_str(val, &va, &len);
|
||||
if (err) {
|
||||
BT_ERR("Failed to decode value %s (err %d)", val, err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len != sizeof(struct va_val)) {
|
||||
BT_ERR("Invalid length for virtual address");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (va.ref == 0) {
|
||||
BT_WARN("Ignore Mesh Virtual Address ref = 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lab = get_label(index);
|
||||
if (lab == NULL) {
|
||||
BT_WARN("Out of labels buffers");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(lab->uuid, va.uuid, 16);
|
||||
lab->addr = va.addr;
|
||||
lab->ref = va.ref;
|
||||
|
||||
BT_DBG("Restored Virtual Address, addr 0x%04x ref 0x%04x",
|
||||
lab->addr, lab->ref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
static int node_set(int argc, char **argv, char *str)
|
||||
{
|
||||
struct bt_mesh_node *node;
|
||||
struct node_val val;
|
||||
u16_t addr;
|
||||
int len, err;
|
||||
|
||||
if (argc < 1) {
|
||||
BT_ERR("Insufficient number of arguments");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
addr = strtol(argv[0], NULL, 16);
|
||||
|
||||
if (str == NULL) {
|
||||
BT_DBG("val (null)");
|
||||
BT_DBG("Deleting node 0x%04x", addr);
|
||||
|
||||
node = bt_mesh_node_find(addr);
|
||||
if (node) {
|
||||
bt_mesh_node_del(node, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = settings_bytes_from_str(str, &val, &len);
|
||||
if (err) {
|
||||
BT_ERR("Failed to decode value %s (err %d)", val, err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len != sizeof(struct node_val)) {
|
||||
BT_ERR("Invalid length for node_val");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
node = bt_mesh_node_find(addr);
|
||||
if (!node) {
|
||||
node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
BT_ERR("No space for a new node");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(node->dev_key, &val.dev_key, 16);
|
||||
|
||||
BT_DBG("Node 0x%04x recovered from storage", addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct mesh_setting {
|
||||
const char *name;
|
||||
int (*func)(int argc, char **argv, char *val);
|
||||
|
@ -686,6 +828,12 @@ const struct mesh_setting {
|
|||
{ "Cfg", cfg_set },
|
||||
{ "s", sig_mod_set },
|
||||
{ "v", vnd_mod_set },
|
||||
#if CONFIG_BT_MESH_LABEL_COUNT > 0
|
||||
{ "Va", va_set },
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
{ "Node", node_set },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int mesh_set(int argc, char **argv, char *val)
|
||||
|
@ -756,6 +904,10 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
|||
k_delayed_work_submit(&mod->pub->timer, ms);
|
||||
}
|
||||
}
|
||||
|
||||
if (mod->cb && mod->cb->settings_commit) {
|
||||
mod->cb->settings_commit(mod);
|
||||
}
|
||||
}
|
||||
|
||||
static int mesh_commit(void)
|
||||
|
@ -772,7 +924,7 @@ static int mesh_commit(void)
|
|||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
|
||||
bt_mesh_proxy_prov_disable();
|
||||
bt_mesh_proxy_prov_disable(true);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
|
@ -820,24 +972,41 @@ static int mesh_commit(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Pending flags that use K_NO_WAIT as the storage timeout */
|
||||
#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_NET_PENDING) | \
|
||||
BIT(BT_MESH_IV_PENDING) | \
|
||||
BIT(BT_MESH_SEQ_PENDING))
|
||||
|
||||
/* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */
|
||||
#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \
|
||||
BIT(BT_MESH_HB_PUB_PENDING) | \
|
||||
BIT(BT_MESH_CFG_PENDING) | \
|
||||
BIT(BT_MESH_MOD_PENDING) | \
|
||||
BIT(BT_MESH_NODES_PENDING))
|
||||
|
||||
static void schedule_store(int flag)
|
||||
{
|
||||
s32_t timeout;
|
||||
s32_t timeout, remaining;
|
||||
|
||||
atomic_set_bit(bt_mesh.flags, flag);
|
||||
|
||||
if (atomic_test_bit(bt_mesh.flags, BT_MESH_NET_PENDING) ||
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_IV_PENDING) ||
|
||||
atomic_test_bit(bt_mesh.flags, BT_MESH_SEQ_PENDING)) {
|
||||
if (atomic_get(bt_mesh.flags) & NO_WAIT_PENDING_BITS) {
|
||||
timeout = K_NO_WAIT;
|
||||
} else if (atomic_test_bit(bt_mesh.flags, BT_MESH_RPL_PENDING) &&
|
||||
(CONFIG_BT_MESH_RPL_STORE_TIMEOUT <
|
||||
CONFIG_BT_MESH_STORE_TIMEOUT)) {
|
||||
(!(atomic_get(bt_mesh.flags) & GENERIC_PENDING_BITS) ||
|
||||
(CONFIG_BT_MESH_RPL_STORE_TIMEOUT <
|
||||
CONFIG_BT_MESH_STORE_TIMEOUT))) {
|
||||
timeout = K_SECONDS(CONFIG_BT_MESH_RPL_STORE_TIMEOUT);
|
||||
} else {
|
||||
timeout = K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT);
|
||||
}
|
||||
|
||||
remaining = k_delayed_work_remaining_get(&pending_store);
|
||||
if (remaining && remaining < timeout) {
|
||||
BT_DBG("Not rescheduling due to existing earlier deadline");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Waiting %d seconds", (int) (timeout / MSEC_PER_SEC));
|
||||
|
||||
k_delayed_work_submit(&pending_store, timeout);
|
||||
|
@ -845,14 +1014,26 @@ static void schedule_store(int flag)
|
|||
|
||||
static void clear_iv(void)
|
||||
{
|
||||
BT_DBG("Clearing IV");
|
||||
settings_save_one("bt_mesh/IV", NULL);
|
||||
int err;
|
||||
|
||||
err = settings_save_one("bt_mesh/IV", NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear IV");
|
||||
} else {
|
||||
BT_DBG("Cleared IV");
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_net(void)
|
||||
{
|
||||
BT_DBG("Clearing Network");
|
||||
settings_save_one("bt_mesh/Net", NULL);
|
||||
int err;
|
||||
|
||||
err = settings_save_one("bt_mesh/Net", NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear Network");
|
||||
} else {
|
||||
BT_DBG("Cleared Network");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_net(void)
|
||||
|
@ -860,6 +1041,7 @@ static void store_pending_net(void)
|
|||
char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))];
|
||||
struct net_val net;
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(),
|
||||
bt_hex(bt_mesh.dev_key, 16));
|
||||
|
@ -874,7 +1056,12 @@ static void store_pending_net(void)
|
|||
}
|
||||
|
||||
BT_DBG("Saving Network as value %s", str);
|
||||
settings_save_one("bt_mesh/Net", str);
|
||||
err = settings_save_one("bt_mesh/Net", str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store Network");
|
||||
} else {
|
||||
BT_DBG("Stored Network");
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_store_net(void)
|
||||
|
@ -887,6 +1074,7 @@ static void store_pending_iv(void)
|
|||
char buf[BT_SETTINGS_SIZE(sizeof(struct iv_val))];
|
||||
struct iv_val iv;
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
iv.iv_index = bt_mesh.iv_index;
|
||||
iv.iv_update = atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
|
||||
|
@ -899,7 +1087,12 @@ static void store_pending_iv(void)
|
|||
}
|
||||
|
||||
BT_DBG("Saving IV as value %s", str);
|
||||
settings_save_one("bt_mesh/IV", str);
|
||||
err = settings_save_one("bt_mesh/IV", str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store IV");
|
||||
} else {
|
||||
BT_DBG("Stored IV");
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_store_iv(bool only_duration)
|
||||
|
@ -917,6 +1110,7 @@ static void store_pending_seq(void)
|
|||
char buf[BT_SETTINGS_SIZE(sizeof(struct seq_val))];
|
||||
struct seq_val seq;
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
seq.val[0] = bt_mesh.seq;
|
||||
seq.val[1] = bt_mesh.seq >> 8;
|
||||
|
@ -929,7 +1123,12 @@ static void store_pending_seq(void)
|
|||
}
|
||||
|
||||
BT_DBG("Saving Seq as value %s", str);
|
||||
settings_save_one("bt_mesh/Seq", str);
|
||||
err = settings_save_one("bt_mesh/Seq", str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store Seq");
|
||||
} else {
|
||||
BT_DBG("Stored Seq");
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_store_seq(void)
|
||||
|
@ -948,6 +1147,7 @@ static void store_rpl(struct bt_mesh_rpl *entry)
|
|||
struct rpl_val rpl;
|
||||
char path[18];
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src,
|
||||
(unsigned) entry->seq, entry->old_iv);
|
||||
|
@ -964,12 +1164,17 @@ static void store_rpl(struct bt_mesh_rpl *entry)
|
|||
snprintk(path, sizeof(path), "bt_mesh/RPL/%x", entry->src);
|
||||
|
||||
BT_DBG("Saving RPL %s as value %s", path, str);
|
||||
settings_save_one(path, str);
|
||||
err = settings_save_one(path, str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store RPL");
|
||||
} else {
|
||||
BT_DBG("Stored RPL");
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_rpl(void)
|
||||
{
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
|
@ -982,7 +1187,12 @@ static void clear_rpl(void)
|
|||
}
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src);
|
||||
settings_save_one(path, NULL);
|
||||
err = settings_save_one(path, NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear RPL");
|
||||
} else {
|
||||
BT_DBG("Cleared RPL");
|
||||
}
|
||||
|
||||
memset(rpl, 0, sizeof(*rpl));
|
||||
}
|
||||
|
@ -1010,6 +1220,7 @@ static void store_pending_hb_pub(void)
|
|||
struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
|
||||
struct hb_pub_val val;
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
if (!pub) {
|
||||
return;
|
||||
|
@ -1035,7 +1246,12 @@ static void store_pending_hb_pub(void)
|
|||
|
||||
BT_DBG("Saving Heartbeat Publication as value %s",
|
||||
str ? str : "(null)");
|
||||
settings_save_one("bt_mesh/HBPub", str);
|
||||
err = settings_save_one("bt_mesh/HBPub", str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store Heartbeat Publication");
|
||||
} else {
|
||||
BT_DBG("Stored Heartbeat Publication");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_cfg(void)
|
||||
|
@ -1044,6 +1260,7 @@ static void store_pending_cfg(void)
|
|||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
struct cfg_val val;
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
if (!cfg) {
|
||||
return;
|
||||
|
@ -1064,33 +1281,56 @@ static void store_pending_cfg(void)
|
|||
}
|
||||
|
||||
BT_DBG("Saving configuration as value %s", str);
|
||||
settings_save_one("bt_mesh/Cfg", str);
|
||||
err = settings_save_one("bt_mesh/Cfg", str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store configuration");
|
||||
} else {
|
||||
BT_DBG("Stored configuration");
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_cfg(void)
|
||||
{
|
||||
BT_DBG("Clearing configuration");
|
||||
settings_save_one("bt_mesh/Cfg", NULL);
|
||||
int err;
|
||||
|
||||
err = settings_save_one("bt_mesh/Cfg", NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear configuration");
|
||||
} else {
|
||||
BT_DBG("Cleared configuration");
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_app_key(u16_t app_idx)
|
||||
{
|
||||
char path[20];
|
||||
int err;
|
||||
|
||||
BT_DBG("AppKeyIndex 0x%03x", app_idx);
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx);
|
||||
settings_save_one(path, NULL);
|
||||
err = settings_save_one(path, NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
|
||||
} else {
|
||||
BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_net_key(u16_t net_idx)
|
||||
{
|
||||
char path[20];
|
||||
int err;
|
||||
|
||||
BT_DBG("NetKeyIndex 0x%03x", net_idx);
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx);
|
||||
settings_save_one(path, NULL);
|
||||
err = settings_save_one(path, NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
|
||||
} else {
|
||||
BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void store_net_key(struct bt_mesh_subnet *sub)
|
||||
|
@ -1099,6 +1339,7 @@ static void store_net_key(struct bt_mesh_subnet *sub)
|
|||
struct net_key_val key;
|
||||
char path[20];
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
|
||||
bt_hex(sub->keys[0].net, 16));
|
||||
|
@ -1117,7 +1358,12 @@ static void store_net_key(struct bt_mesh_subnet *sub)
|
|||
snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx);
|
||||
|
||||
BT_DBG("Saving NetKey %s as value %s", path, str);
|
||||
settings_save_one(path, str);
|
||||
err = settings_save_one(path, str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store NetKey");
|
||||
} else {
|
||||
BT_DBG("Stored NetKey");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_app_key(struct bt_mesh_app_key *app)
|
||||
|
@ -1126,6 +1372,7 @@ static void store_app_key(struct bt_mesh_app_key *app)
|
|||
struct app_key_val key;
|
||||
char path[20];
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
key.net_idx = app->net_idx;
|
||||
key.updated = app->updated;
|
||||
|
@ -1141,7 +1388,12 @@ static void store_app_key(struct bt_mesh_app_key *app)
|
|||
snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app->app_idx);
|
||||
|
||||
BT_DBG("Saving AppKey %s as value %s", path, str);
|
||||
settings_save_one(path, str);
|
||||
err = settings_save_one(path, str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store AppKey");
|
||||
} else {
|
||||
BT_DBG("Stored AppKey");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_keys(void)
|
||||
|
@ -1190,6 +1442,104 @@ static void store_pending_keys(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void store_node(struct bt_mesh_node *node)
|
||||
{
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))];
|
||||
struct node_val val;
|
||||
char path[20];
|
||||
char *str;
|
||||
int err;
|
||||
|
||||
val.net_idx = node->net_idx;
|
||||
val.num_elem = node->num_elem;
|
||||
memcpy(val.dev_key, node->dev_key, 16);
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/Node/%x", node->addr);
|
||||
|
||||
str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
|
||||
if (!str) {
|
||||
BT_ERR("Unable to encode Node as value");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
err = settings_save_one(path, str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store Node %s value", path);
|
||||
} else {
|
||||
BT_DBG("Stored Node %s value", path);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_node(u16_t addr)
|
||||
{
|
||||
char path[20];
|
||||
int err;
|
||||
|
||||
BT_DBG("Node 0x%04x", addr);
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/Node/%x", addr);
|
||||
err = settings_save_one(path, NULL);
|
||||
if (err) {
|
||||
BT_ERR("Failed to clear Node 0x%04x", addr);
|
||||
} else {
|
||||
BT_DBG("Cleared Node 0x%04x", addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_nodes(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(node_updates); ++i) {
|
||||
struct node_update *update = &node_updates[i];
|
||||
|
||||
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update->clear) {
|
||||
clear_node(update->addr);
|
||||
} else {
|
||||
struct bt_mesh_node *node;
|
||||
|
||||
node = bt_mesh_node_find(update->addr);
|
||||
if (node) {
|
||||
store_node(node);
|
||||
} else {
|
||||
BT_WARN("Node 0x%04x not found", update->addr);
|
||||
}
|
||||
}
|
||||
|
||||
update->addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
static struct node_update *node_update_find(u16_t addr,
|
||||
struct node_update **free_slot)
|
||||
{
|
||||
struct node_update *match;
|
||||
int i;
|
||||
|
||||
match = NULL;
|
||||
*free_slot = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(node_updates); i++) {
|
||||
struct node_update *update = &node_updates[i];
|
||||
|
||||
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
*free_slot = update;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update->addr == addr) {
|
||||
match = update;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
|
||||
const char *key, char *path, size_t path_len)
|
||||
{
|
||||
|
@ -1207,7 +1557,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
|
|||
u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(keys))];
|
||||
char path[20];
|
||||
int i, count;
|
||||
int i, count, err;
|
||||
char *val;
|
||||
|
||||
for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) {
|
||||
|
@ -1230,7 +1580,12 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
|
|||
encode_mod_path(mod, vnd, "bind", path, sizeof(path));
|
||||
|
||||
BT_DBG("Saving %s as %s", path, val ? val : "(null)");
|
||||
settings_save_one(path, val);
|
||||
err = settings_save_one(path, val);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store bind");
|
||||
} else {
|
||||
BT_DBG("Stored bind");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
|
||||
|
@ -1238,10 +1593,10 @@ static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
|
|||
u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(groups))];
|
||||
char path[20];
|
||||
int i, count;
|
||||
int i, count, err;
|
||||
char *val;
|
||||
|
||||
for (i = 0, count = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
groups[count++] = mod->groups[i];
|
||||
}
|
||||
|
@ -1261,7 +1616,12 @@ static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
|
|||
encode_mod_path(mod, vnd, "sub", path, sizeof(path));
|
||||
|
||||
BT_DBG("Saving %s as %s", path, val ? val : "(null)");
|
||||
settings_save_one(path, val);
|
||||
err = settings_save_one(path, val);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store sub");
|
||||
} else {
|
||||
BT_DBG("Stored sub");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
|
||||
|
@ -1270,6 +1630,7 @@ static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
|
|||
struct mod_pub_val pub;
|
||||
char path[20];
|
||||
char *val;
|
||||
int err;
|
||||
|
||||
if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
val = NULL;
|
||||
|
@ -1293,7 +1654,12 @@ static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
|
|||
encode_mod_path(mod, vnd, "pub", path, sizeof(path));
|
||||
|
||||
BT_DBG("Saving %s as %s", path, val ? val : "(null)");
|
||||
settings_save_one(path, val);
|
||||
err = settings_save_one(path, val);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store pub");
|
||||
} else {
|
||||
BT_DBG("Stored pub");
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending_mod(struct bt_mesh_model *mod,
|
||||
|
@ -1320,6 +1686,52 @@ static void store_pending_mod(struct bt_mesh_model *mod,
|
|||
}
|
||||
}
|
||||
|
||||
#define IS_VA_DEL(_label) ((_label)->ref == 0)
|
||||
static void store_pending_va(void)
|
||||
{
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))];
|
||||
struct label *lab;
|
||||
struct va_val va;
|
||||
char path[18];
|
||||
char *val;
|
||||
u16_t i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; (lab = get_label(i)) != NULL; i++) {
|
||||
if (!atomic_test_and_clear_bit(lab->flags,
|
||||
BT_MESH_VA_CHANGED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintk(path, sizeof(path), "bt_mesh/Va/%x", i);
|
||||
|
||||
if (IS_VA_DEL(lab)) {
|
||||
val = NULL;
|
||||
} else {
|
||||
va.ref = lab->ref;
|
||||
va.addr = lab->addr;
|
||||
memcpy(va.uuid, lab->uuid, 16);
|
||||
|
||||
val = settings_str_from_bytes(&va, sizeof(va),
|
||||
buf, sizeof(buf));
|
||||
if (!val) {
|
||||
BT_ERR("Unable to encode model publication as value");
|
||||
return;
|
||||
}
|
||||
|
||||
err = settings_save_one(path, val);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("Failed to %s %s value (err %d)",
|
||||
IS_VA_DEL(lab) ? "delete" : "store", path, err);
|
||||
} else {
|
||||
BT_DBG("%s %s value",
|
||||
IS_VA_DEL(lab) ? "Deleted" : "Stored", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending(struct ble_npl_event *work)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
@ -1371,6 +1783,15 @@ static void store_pending(struct ble_npl_event *work)
|
|||
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_MOD_PENDING)) {
|
||||
bt_mesh_model_foreach(store_pending_mod, NULL);
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_VA_PENDING)) {
|
||||
store_pending_va();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
|
||||
atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) {
|
||||
store_pending_nodes();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
|
||||
|
@ -1552,6 +1973,93 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *mod)
|
|||
schedule_store(BT_MESH_MOD_PENDING);
|
||||
}
|
||||
|
||||
|
||||
void bt_mesh_store_label(void)
|
||||
{
|
||||
schedule_store(BT_MESH_VA_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_store_node(struct bt_mesh_node *node)
|
||||
{
|
||||
struct node_update *update, *free_slot;
|
||||
|
||||
BT_DBG("Node 0x%04x", node->addr);
|
||||
|
||||
update = node_update_find(node->addr, &free_slot);
|
||||
if (update) {
|
||||
update->clear = false;
|
||||
schedule_store(BT_MESH_NODES_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!free_slot) {
|
||||
store_node(node);
|
||||
return;
|
||||
}
|
||||
|
||||
free_slot->addr = node->addr;
|
||||
|
||||
schedule_store(BT_MESH_NODES_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_clear_node(struct bt_mesh_node *node)
|
||||
{
|
||||
struct node_update *update, *free_slot;
|
||||
|
||||
BT_DBG("Node 0x%04x", node->addr);
|
||||
|
||||
update = node_update_find(node->addr, &free_slot);
|
||||
if (update) {
|
||||
update->clear = true;
|
||||
schedule_store(BT_MESH_NODES_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!free_slot) {
|
||||
clear_node(node->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
free_slot->addr = node->addr;
|
||||
|
||||
schedule_store(BT_MESH_NODES_PENDING);
|
||||
}
|
||||
|
||||
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
|
||||
const void *data, size_t data_len)
|
||||
{
|
||||
char path[20];
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))];
|
||||
char *val;
|
||||
int err;
|
||||
|
||||
encode_mod_path(mod, vnd, "data", path, sizeof(path));
|
||||
|
||||
if (data_len) {
|
||||
mod->flags |= BT_MESH_MOD_DATA_PRESENT;
|
||||
val = settings_str_from_bytes(data, data_len,
|
||||
buf, sizeof(buf));
|
||||
if (!val) {
|
||||
BT_ERR("Unable to encode model publication as value");
|
||||
return -EINVAL;
|
||||
}
|
||||
err = settings_save_one(path, val);
|
||||
} else if (mod->flags & BT_MESH_MOD_DATA_PRESENT) {
|
||||
mod->flags &= ~BT_MESH_MOD_DATA_PRESENT;
|
||||
err = settings_save_one(path, NULL);
|
||||
} else {
|
||||
/* Nothing to delete */
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("Failed to store %s value", path);
|
||||
} else {
|
||||
BT_DBG("Stored %s value", path);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct conf_handler bt_mesh_settings_conf_handler = {
|
||||
.ch_name = "bt_mesh",
|
||||
.ch_get = NULL,
|
||||
|
|
|
@ -15,10 +15,13 @@ void bt_mesh_store_cfg(void);
|
|||
void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
|
||||
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
|
||||
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
|
||||
void bt_mesh_store_label(void);
|
||||
void bt_mesh_store_node(struct bt_mesh_node *node);
|
||||
|
||||
void bt_mesh_clear_net(void);
|
||||
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
|
||||
void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
|
||||
void bt_mesh_clear_rpl(void);
|
||||
void bt_mesh_clear_node(struct bt_mesh_node *node);
|
||||
|
||||
void bt_mesh_settings_init(void);
|
||||
|
|
|
@ -222,37 +222,46 @@ static struct bt_mesh_health_cli health_cli = {
|
|||
#endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
|
||||
static struct bt_mesh_model_pub gen_onoff_pub;
|
||||
static struct bt_mesh_model_pub gen_level_pub;
|
||||
static struct bt_mesh_gen_model_cli gen_onoff_cli;
|
||||
static struct bt_mesh_model_pub gen_onoff_cli_pub;
|
||||
static struct bt_mesh_model_pub gen_onoff_srv_pub;
|
||||
static struct bt_mesh_gen_model_cli gen_level_cli;
|
||||
static struct bt_mesh_model_pub gen_level_cli_pub;
|
||||
static struct bt_mesh_model_pub gen_level_srv_pub;
|
||||
static struct bt_mesh_model_pub light_lightness_pub;
|
||||
static struct bt_mesh_gen_onoff_srv_cb gen_onoff_srv_cb = {
|
||||
static struct bt_mesh_gen_onoff_srv gen_onoff_srv = {
|
||||
.get = light_model_gen_onoff_get,
|
||||
.set = light_model_gen_onoff_set,
|
||||
};
|
||||
static struct bt_mesh_gen_level_srv_cb gen_level_srv_cb = {
|
||||
static struct bt_mesh_gen_level_srv gen_level_srv = {
|
||||
.get = light_model_gen_level_get,
|
||||
.set = light_model_gen_level_set,
|
||||
};
|
||||
static struct bt_mesh_light_lightness_srv_cb light_lightness_srv_cb = {
|
||||
static struct bt_mesh_light_lightness_srv light_lightness_srv = {
|
||||
.get = light_model_light_lightness_get,
|
||||
.set = light_model_light_lightness_set,
|
||||
};
|
||||
|
||||
void bt_mesh_set_gen_onoff_srv_cb(struct bt_mesh_gen_onoff_srv_cb *gen_onoff_cb)
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state))
|
||||
{
|
||||
gen_onoff_srv_cb = *gen_onoff_cb;
|
||||
gen_onoff_srv.get = get;
|
||||
gen_onoff_srv.set = set;
|
||||
}
|
||||
|
||||
void bt_mesh_set_gen_level_srv_cb(struct bt_mesh_gen_level_srv_cb *gen_level_cb)
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level))
|
||||
{
|
||||
gen_level_srv_cb = *gen_level_cb;
|
||||
gen_level_srv.get = get;
|
||||
gen_level_srv.set = set;
|
||||
}
|
||||
|
||||
void bt_mesh_set_light_lightness_srv_cb(struct bt_mesh_light_lightness_srv_cb *light_lightness_cb)
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level))
|
||||
{
|
||||
light_lightness_srv_cb = *light_lightness_cb;
|
||||
light_lightness_srv.get = get;
|
||||
light_lightness_srv.set = set;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static struct bt_mesh_model root_models[] = {
|
||||
|
@ -265,11 +274,11 @@ static struct bt_mesh_model root_models[] = {
|
|||
BT_MESH_MODEL_HEALTH_CLI(&health_cli),
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
|
||||
BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv_cb, &gen_onoff_pub),
|
||||
BT_MESH_MODEL_GEN_ONOFF_CLI(),
|
||||
BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv_cb, &gen_level_pub),
|
||||
BT_MESH_MODEL_GEN_LEVEL_CLI(),
|
||||
BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&light_lightness_srv_cb, &light_lightness_pub),
|
||||
BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv, &gen_onoff_srv_pub),
|
||||
BT_MESH_MODEL_GEN_ONOFF_CLI(&gen_onoff_cli, &gen_onoff_cli_pub),
|
||||
BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv, &gen_level_srv_pub),
|
||||
BT_MESH_MODEL_GEN_LEVEL_CLI(&gen_level_cli, &gen_level_cli_pub),
|
||||
BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&light_lightness_srv, &light_lightness_pub),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -323,11 +332,25 @@ static void prov_complete(u16_t net_idx, u16_t addr)
|
|||
{
|
||||
printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
|
||||
net_idx, addr);
|
||||
net.net_idx = net_idx,
|
||||
net.local = addr;
|
||||
net.net_idx = net_idx,
|
||||
net.dst = addr;
|
||||
}
|
||||
|
||||
static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
|
||||
{
|
||||
printk("Node provisioned, net_idx 0x%04x address "
|
||||
"0x%04x elements %d", net_idx, addr, num_elem);
|
||||
|
||||
net.net_idx = net_idx,
|
||||
net.dst = addr;
|
||||
}
|
||||
|
||||
static void prov_input_complete(void)
|
||||
{
|
||||
printk("Input complete");
|
||||
}
|
||||
|
||||
static void prov_reset(void)
|
||||
{
|
||||
printk("The local node has been reset and needs reprovisioning\n");
|
||||
|
@ -467,6 +490,7 @@ static struct bt_mesh_prov prov = {
|
|||
.link_open = link_open,
|
||||
.link_close = link_close,
|
||||
.complete = prov_complete,
|
||||
.node_added = prov_node_added,
|
||||
.reset = prov_reset,
|
||||
.static_val = NULL,
|
||||
.static_val_len = 0,
|
||||
|
@ -477,6 +501,7 @@ static struct bt_mesh_prov prov = {
|
|||
.input_size = MYNEWT_VAL(BLE_MESH_OOB_INPUT_SIZE),
|
||||
.input_actions = MYNEWT_VAL(BLE_MESH_OOB_INPUT_ACTIONS),
|
||||
.input = input,
|
||||
.input_complete = prov_input_complete,
|
||||
};
|
||||
|
||||
static int cmd_static_oob(int argc, char *argv[])
|
||||
|
@ -794,19 +819,6 @@ struct shell_cmd_help cmd_net_send_help = {
|
|||
NULL, "<hex string>", NULL
|
||||
};
|
||||
|
||||
static int cmd_iv_update(int argc, char *argv[])
|
||||
{
|
||||
if (bt_mesh_iv_update()) {
|
||||
printk("Transitioned to IV Update In Progress state\n");
|
||||
} else {
|
||||
printk("Transitioned to IV Update Normal state\n");
|
||||
}
|
||||
|
||||
printk("IV Index is 0x%08lx\n", bt_mesh.iv_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_rpl_clear(int argc, char *argv[])
|
||||
{
|
||||
bt_mesh_rpl_clear();
|
||||
|
@ -857,6 +869,20 @@ struct shell_cmd_help cmd_lpn_unsubscribe_help = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
|
||||
static int cmd_iv_update(int argc, char *argv[])
|
||||
{
|
||||
if (bt_mesh_iv_update()) {
|
||||
printk("Transitioned to IV Update In Progress state\n");
|
||||
} else {
|
||||
printk("Transitioned to IV Update Normal state\n");
|
||||
}
|
||||
|
||||
printk("IV Index is 0x%08lx\n", bt_mesh.iv_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_iv_update_test(int argc, char *argv[])
|
||||
{
|
||||
bool enable;
|
||||
|
@ -880,6 +906,7 @@ static int cmd_iv_update_test(int argc, char *argv[])
|
|||
struct shell_cmd_help cmd_iv_update_test_help = {
|
||||
NULL, "<value: off, on>", NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
|
||||
|
||||
|
@ -1802,6 +1829,37 @@ static int cmd_pb_adv(int argc, char *argv[])
|
|||
{
|
||||
return cmd_pb(BT_MESH_PROV_ADV, argc, argv);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
static int cmd_provision_adv(int argc, char *argv[])
|
||||
{
|
||||
u8_t uuid[16];
|
||||
u8_t attention_duration;
|
||||
u16_t net_idx;
|
||||
u16_t addr;
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
len = hex2bin(argv[1], uuid, sizeof(uuid));
|
||||
(void)memset(uuid + len, 0, sizeof(uuid) - len);
|
||||
|
||||
net_idx = strtoul(argv[2], NULL, 0);
|
||||
addr = strtoul(argv[3], NULL, 0);
|
||||
attention_duration = strtoul(argv[4], NULL, 0);
|
||||
|
||||
err = bt_mesh_provision_adv(uuid, net_idx, addr, attention_duration);
|
||||
if (err) {
|
||||
printk("Provisioning failed (err %d)", err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct shell_cmd_help cmd_provision_adv_help = {
|
||||
NULL, "<UUID> <NetKeyIndex> <addr> <AttentionDuration>" , NULL
|
||||
};
|
||||
#endif /* CONFIG_BT_MESH_PROVISIONER */
|
||||
|
||||
#endif /* CONFIG_BT_MESH_PB_ADV */
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_GATT)
|
||||
|
@ -2403,6 +2461,13 @@ static const struct shell_cmd mesh_commands[] = {
|
|||
.sc_cmd_func = cmd_pb_adv,
|
||||
.help = &cmd_pb_help,
|
||||
},
|
||||
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
|
||||
{
|
||||
.sc_cmd = "provision-adv",
|
||||
.sc_cmd_func = cmd_provision_adv,
|
||||
.help = &cmd_provision_adv_help,
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_MESH_PB_GATT)
|
||||
{
|
||||
|
@ -2482,6 +2547,7 @@ static const struct shell_cmd mesh_commands[] = {
|
|||
.sc_cmd_func = cmd_net_send,
|
||||
.help = &cmd_net_send_help,
|
||||
},
|
||||
#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
|
||||
{
|
||||
.sc_cmd = "iv-update",
|
||||
.sc_cmd_func = cmd_iv_update,
|
||||
|
@ -2492,6 +2558,7 @@ static const struct shell_cmd mesh_commands[] = {
|
|||
.sc_cmd_func = cmd_iv_update_test,
|
||||
.help = &cmd_iv_update_test_help,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.sc_cmd = "rpl-clear",
|
||||
.sc_cmd_func = cmd_rpl_clear,
|
||||
|
|
|
@ -357,7 +357,6 @@ void ble_att_error_rsp_parse(const void *payload, int len,
|
|||
struct ble_att_error_rsp *rsp);
|
||||
void ble_att_error_rsp_write(void *payload, int len,
|
||||
const struct ble_att_error_rsp *rsp);
|
||||
void ble_att_error_rsp_log(const struct ble_att_error_rsp *cmd);
|
||||
void ble_att_mtu_req_parse(const void *payload, int len,
|
||||
struct ble_att_mtu_cmd *cmd);
|
||||
void ble_att_mtu_req_write(void *payload, int len,
|
||||
|
@ -366,43 +365,34 @@ void ble_att_mtu_rsp_parse(const void *payload, int len,
|
|||
struct ble_att_mtu_cmd *cmd);
|
||||
void ble_att_mtu_rsp_write(void *payload, int len,
|
||||
const struct ble_att_mtu_cmd *cmd);
|
||||
void ble_att_mtu_cmd_log(const struct ble_att_mtu_cmd *cmd);
|
||||
void ble_att_find_info_req_parse(const void *payload, int len,
|
||||
struct ble_att_find_info_req *req);
|
||||
void ble_att_find_info_req_write(void *payload, int len,
|
||||
const struct ble_att_find_info_req *req);
|
||||
void ble_att_find_info_req_log(const struct ble_att_find_info_req *cmd);
|
||||
void ble_att_find_info_rsp_parse(const void *payload, int len,
|
||||
struct ble_att_find_info_rsp *rsp);
|
||||
void ble_att_find_info_rsp_write(void *payload, int len,
|
||||
const struct ble_att_find_info_rsp *rsp);
|
||||
void ble_att_find_info_rsp_log(const struct ble_att_find_info_rsp *cmd);
|
||||
void ble_att_find_type_value_req_parse(
|
||||
const void *payload, int len, struct ble_att_find_type_value_req *req);
|
||||
void ble_att_find_type_value_req_write(
|
||||
void *payload, int len, const struct ble_att_find_type_value_req *req);
|
||||
void ble_att_find_type_value_req_log(
|
||||
const struct ble_att_find_type_value_req *cmd);
|
||||
void ble_att_read_type_req_parse(const void *payload, int len,
|
||||
struct ble_att_read_type_req *req);
|
||||
void ble_att_read_type_req_write(void *payload, int len,
|
||||
const struct ble_att_read_type_req *req);
|
||||
void ble_att_read_type_req_log(const struct ble_att_read_type_req *cmd);
|
||||
void ble_att_read_type_rsp_parse(const void *payload, int len,
|
||||
struct ble_att_read_type_rsp *rsp);
|
||||
void ble_att_read_type_rsp_write(void *payload, int len,
|
||||
const struct ble_att_read_type_rsp *rsp);
|
||||
void ble_att_read_type_rsp_log(const struct ble_att_read_type_rsp *cmd);
|
||||
void ble_att_read_req_parse(const void *payload, int len,
|
||||
struct ble_att_read_req *req);
|
||||
void ble_att_read_req_write(void *payload, int len,
|
||||
const struct ble_att_read_req *req);
|
||||
void ble_att_read_req_log(const struct ble_att_read_req *cmd);
|
||||
void ble_att_read_blob_req_parse(const void *payload, int len,
|
||||
struct ble_att_read_blob_req *req);
|
||||
void ble_att_read_blob_req_write(void *payload, int len,
|
||||
const struct ble_att_read_blob_req *req);
|
||||
void ble_att_read_blob_req_log(const struct ble_att_read_blob_req *cmd);
|
||||
void ble_att_read_mult_req_parse(const void *payload, int len);
|
||||
void ble_att_read_mult_req_write(void *payload, int len);
|
||||
void ble_att_read_mult_rsp_parse(const void *payload, int len);
|
||||
|
@ -411,14 +401,10 @@ void ble_att_read_group_type_req_parse(
|
|||
const void *payload, int len, struct ble_att_read_group_type_req *req);
|
||||
void ble_att_read_group_type_req_write(
|
||||
void *payload, int len, const struct ble_att_read_group_type_req *req);
|
||||
void ble_att_read_group_type_req_log(
|
||||
const struct ble_att_read_group_type_req *cmd);
|
||||
void ble_att_read_group_type_rsp_parse(
|
||||
const void *payload, int len, struct ble_att_read_group_type_rsp *rsp);
|
||||
void ble_att_read_group_type_rsp_write(
|
||||
void *payload, int len, const struct ble_att_read_group_type_rsp *rsp);
|
||||
void ble_att_read_group_type_rsp_log(
|
||||
const struct ble_att_read_group_type_rsp *cmd);
|
||||
void ble_att_write_req_parse(const void *payload, int len,
|
||||
struct ble_att_write_req *req);
|
||||
void ble_att_write_req_write(void *payload, int len,
|
||||
|
@ -427,20 +413,16 @@ void ble_att_write_cmd_parse(const void *payload, int len,
|
|||
struct ble_att_write_req *req);
|
||||
void ble_att_write_cmd_write(void *payload, int len,
|
||||
const struct ble_att_write_req *req);
|
||||
void ble_att_write_cmd_log(const struct ble_att_write_cmd *cmd);
|
||||
void ble_att_write_req_log(const struct ble_att_write_req *req);
|
||||
void ble_att_prep_write_req_parse(const void *payload, int len,
|
||||
struct ble_att_prep_write_cmd *cmd);
|
||||
void ble_att_prep_write_req_write(void *payload, int len,
|
||||
const struct ble_att_prep_write_cmd *cmd);
|
||||
void ble_att_prep_write_cmd_log(const struct ble_att_prep_write_cmd *cmd);
|
||||
void ble_att_prep_write_rsp_parse(const void *payload, int len,
|
||||
struct ble_att_prep_write_cmd *cmd);
|
||||
void ble_att_prep_write_rsp_write(void *payload, int len,
|
||||
const struct ble_att_prep_write_cmd *cmd);
|
||||
void ble_att_exec_write_req_parse(const void *payload, int len,
|
||||
struct ble_att_exec_write_req *req);
|
||||
void ble_att_exec_write_req_log(const struct ble_att_exec_write_req *cmd);
|
||||
void ble_att_exec_write_req_write(void *payload, int len,
|
||||
const struct ble_att_exec_write_req *req);
|
||||
void ble_att_exec_write_rsp_parse(const void *payload, int len);
|
||||
|
@ -449,14 +431,12 @@ void ble_att_notify_req_parse(const void *payload, int len,
|
|||
struct ble_att_notify_req *req);
|
||||
void ble_att_notify_req_write(void *payload, int len,
|
||||
const struct ble_att_notify_req *req);
|
||||
void ble_att_notify_req_log(const struct ble_att_notify_req *cmd);
|
||||
void ble_att_indicate_req_parse(const void *payload, int len,
|
||||
struct ble_att_indicate_req *req);
|
||||
void ble_att_indicate_req_write(void *payload, int len,
|
||||
const struct ble_att_indicate_req *req);
|
||||
void ble_att_indicate_rsp_parse(const void *payload, int len);
|
||||
void ble_att_indicate_rsp_write(void *payload, int len);
|
||||
void ble_att_indicate_req_log(const struct ble_att_indicate_req *cmd);
|
||||
|
||||
void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom);
|
||||
void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom);
|
||||
|
|
|
@ -170,12 +170,6 @@ void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu);
|
|||
uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan);
|
||||
int ble_att_init(void);
|
||||
|
||||
#define BLE_ATT_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \
|
||||
BLE_HS_LOG_CMD((is_tx), "att", (cmd_name), (conn_handle), (log_cb), (cmd))
|
||||
|
||||
#define BLE_ATT_LOG_EMPTY_CMD(is_tx, cmd_name, conn_handle) \
|
||||
BLE_HS_LOG_EMPTY_CMD((is_tx), "att", (cmd_name), (conn_handle))
|
||||
|
||||
/*** @svr */
|
||||
|
||||
int ble_att_svr_start(void);
|
||||
|
|
|
@ -81,23 +81,40 @@ void ble_gap_rx_le_scan_timeout(void);
|
|||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc);
|
||||
void ble_gap_rx_adv_set_terminated(struct hci_le_adv_set_terminated *evt);
|
||||
void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev);
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
|
||||
void ble_gap_rx_peroidic_adv_sync_estab(struct hci_le_subev_periodic_adv_sync_estab *evt);
|
||||
void ble_gap_rx_periodic_adv_rpt(struct hci_le_subev_periodic_adv_rpt *evt);
|
||||
void ble_gap_rx_periodic_adv_sync_lost(struct hci_le_subev_periodic_adv_sync_lost *evt);
|
||||
void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev);
|
||||
void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev);
|
||||
void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev);
|
||||
void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev);
|
||||
#endif
|
||||
void ble_gap_rx_scan_req_rcvd(struct hci_le_scan_req_rcvd *evt);
|
||||
void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev);
|
||||
#endif
|
||||
void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
|
||||
void ble_gap_rx_rd_rem_sup_feat_complete(struct hci_le_rd_rem_supp_feat_complete *evt);
|
||||
int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance);
|
||||
void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
|
||||
void ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt);
|
||||
void ble_gap_rx_param_req(struct hci_le_conn_param_req *evt);
|
||||
void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev);
|
||||
|
||||
struct ble_gap_conn_complete
|
||||
{
|
||||
uint8_t status;
|
||||
uint16_t connection_handle;
|
||||
uint8_t role;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
uint16_t conn_itvl;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint8_t master_clk_acc;
|
||||
uint8_t local_rpa[BLE_DEV_ADDR_LEN];
|
||||
uint8_t peer_rpa[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance);
|
||||
void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev);
|
||||
void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev);
|
||||
void ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev);
|
||||
int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
|
||||
struct ble_gap_upd_params *params);
|
||||
void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt);
|
||||
void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev);
|
||||
void ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||
int security_restored, int bonded);
|
||||
void ble_gap_passkey_event(uint16_t conn_handle,
|
||||
|
@ -118,6 +135,7 @@ int ble_gap_master_in_progress(void);
|
|||
void ble_gap_preempt(void);
|
||||
void ble_gap_preempt_done(void);
|
||||
|
||||
int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason);
|
||||
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
|
||||
void ble_gap_reset_state(int reason);
|
||||
int32_t ble_gap_timer(void);
|
||||
|
|
|
@ -38,6 +38,15 @@ typedef uint8_t ble_hs_conn_flags_t;
|
|||
#define BLE_HS_CONN_F_TERMINATING 0x02
|
||||
#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */
|
||||
|
||||
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
|
||||
#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM \
|
||||
((MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) % (8 * sizeof(uint32_t))) ? 1 : 0)
|
||||
|
||||
#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN \
|
||||
(MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) / (8 * sizeof(uint32_t)) + \
|
||||
BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM)
|
||||
#endif
|
||||
|
||||
struct ble_hs_conn {
|
||||
SLIST_ENTRY(ble_hs_conn) bhc_next;
|
||||
uint16_t bhc_handle;
|
||||
|
@ -61,6 +70,9 @@ struct ble_hs_conn {
|
|||
struct ble_l2cap_chan_list bhc_channels;
|
||||
struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */
|
||||
ble_npl_time_t bhc_rx_timeout;
|
||||
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
|
||||
uint32_t l2cap_coc_cid_mask[BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Count of packets sent over this connection that the controller has not
|
||||
|
@ -86,6 +98,10 @@ struct ble_hs_conn {
|
|||
|
||||
ble_gap_event_fn *bhc_cb;
|
||||
void *bhc_cb_arg;
|
||||
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
|
||||
struct ble_hs_periodic_sync *psync;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ble_hs_conn_addrs {
|
||||
|
@ -110,15 +126,19 @@ struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn,
|
|||
uint16_t cid);
|
||||
struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn,
|
||||
uint16_t cid);
|
||||
bool ble_hs_conn_chan_exist(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
|
||||
int ble_hs_conn_chan_insert(struct ble_hs_conn *conn,
|
||||
struct ble_l2cap_chan *chan);
|
||||
void
|
||||
ble_hs_conn_delete_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
|
||||
void ble_hs_conn_delete_chan(struct ble_hs_conn *conn,
|
||||
struct ble_l2cap_chan *chan);
|
||||
|
||||
void ble_hs_conn_addrs(const struct ble_hs_conn *conn,
|
||||
struct ble_hs_conn_addrs *addrs);
|
||||
int32_t ble_hs_conn_timer(void);
|
||||
|
||||
typedef int ble_hs_conn_foreach_fn(struct ble_hs_conn *conn, void *arg);
|
||||
void ble_hs_conn_foreach(ble_hs_conn_foreach_fn *cb, void *arg);
|
||||
|
||||
int ble_hs_conn_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
void ble_hs_flow_connection_broken(uint16_t conn_handle);
|
||||
void ble_hs_flow_fill_acl_usrhdr(struct os_mbuf *om);
|
||||
void ble_hs_flow_track_data_mbuf(struct os_mbuf *om);
|
||||
int ble_hs_flow_startup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -48,7 +48,7 @@ struct os_mbuf;
|
|||
|
||||
struct ble_hs_hci_ack {
|
||||
int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */
|
||||
uint8_t *bha_params;
|
||||
const uint8_t *bha_params;
|
||||
int bha_params_len;
|
||||
uint16_t bha_opcode;
|
||||
uint8_t bha_hci_handle;
|
||||
|
@ -81,11 +81,8 @@ struct hci_periodic_adv_params
|
|||
|
||||
extern uint16_t ble_hs_hci_avail_pkts;
|
||||
|
||||
int ble_hs_hci_cmd_tx(uint16_t opcode, void *cmd, uint8_t cmd_len,
|
||||
void *evt_buf, uint8_t evt_buf_len,
|
||||
uint8_t *out_evt_buf_len);
|
||||
int ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode, void *cmd, uint8_t cmd_len);
|
||||
void ble_hs_hci_rx_ack(uint8_t *ack_ev);
|
||||
int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len,
|
||||
void *rsp, uint8_t rsp_len);
|
||||
void ble_hs_hci_init(void);
|
||||
void ble_hs_hci_deinit(void);
|
||||
|
||||
|
@ -103,78 +100,11 @@ int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr);
|
|||
int ble_hs_hci_util_rand(void *dst, int len);
|
||||
int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi);
|
||||
int ble_hs_hci_util_set_random_addr(const uint8_t *addr);
|
||||
int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
|
||||
uint16_t tx_time);
|
||||
int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
|
||||
struct hci_data_hdr *out_hdr);
|
||||
int ble_hs_hci_evt_process(uint8_t *data);
|
||||
int ble_hs_hci_evt_process(const struct ble_hci_ev *ev);
|
||||
|
||||
void ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint16_t ocf, uint8_t len,
|
||||
void *buf);
|
||||
int ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len);
|
||||
void ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask, uint8_t *dst,
|
||||
int dst_len);
|
||||
void ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst,
|
||||
int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_set_host_chan_class(const uint8_t *chan_map,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_read_chan_map(uint16_t conn_handle,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_le_read_buffer_size(void);
|
||||
void ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
|
||||
int dst_len);
|
||||
int ble_hs_hci_cmd_le_set_adv_enable(uint8_t enable);
|
||||
int ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,
|
||||
uint16_t scan_itvl,
|
||||
uint16_t scan_window,
|
||||
uint8_t own_addr_type,
|
||||
uint8_t filter_policy,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable,
|
||||
uint8_t filter_dups,
|
||||
uint8_t *dst, uint8_t dst_len);
|
||||
int ble_hs_hci_cmd_le_set_scan_enable(uint8_t enable, uint8_t filter_dups);
|
||||
int ble_hs_hci_cmd_build_le_create_connection(
|
||||
const struct hci_create_conn *hcc, uint8_t *cmd, int cmd_len);
|
||||
int ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr,
|
||||
uint8_t addr_type,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_reset(void);
|
||||
int ble_hs_hci_cmd_tx_set_ctlr_to_host_fc(uint8_t fc_enable);
|
||||
int ble_hs_hci_cmd_tx_host_buf_size(const struct hci_host_buf_size *cmd);
|
||||
int ble_hs_hci_cmd_build_host_num_comp_pkts_entry(
|
||||
const struct hci_host_num_comp_pkts_entry *entry,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_read_adv_pwr(void);
|
||||
int ble_hs_hci_cmd_le_create_conn_cancel(void);
|
||||
int ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu);
|
||||
void ble_hs_hci_cmd_build_le_lt_key_req_reply(
|
||||
const struct hci_lt_key_req_reply *hkr, uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
|
||||
uint8_t *dst, int dst_len);
|
||||
void ble_hs_hci_cmd_build_le_conn_param_reply(
|
||||
const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr);
|
||||
void ble_hs_hci_cmd_build_le_conn_param_neg_reply(
|
||||
const struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_le_conn_param_neg_reply(
|
||||
const struct hci_conn_param_neg_reply *hcn);
|
||||
void ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len);
|
||||
int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts);
|
||||
void ble_hs_hci_add_avail_pkts(uint16_t delta);
|
||||
|
||||
|
@ -184,145 +114,9 @@ uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb,
|
|||
int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om);
|
||||
int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om);
|
||||
|
||||
int ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,
|
||||
uint16_t tx_octets, uint16_t tx_time,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_add_to_resolv_list(
|
||||
const struct hci_add_dev_to_resolving_list *padd,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_remove_from_resolv_list(
|
||||
uint8_t addr_type, const uint8_t *addr, uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_read_peer_resolv_addr(
|
||||
uint8_t peer_identity_addr_type, const uint8_t *peer_identity_addr,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_read_lcl_resolv_addr(
|
||||
uint8_t local_identity_addr_type, const uint8_t *local_identity_addr,
|
||||
uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_set_addr_res_en(
|
||||
uint8_t enable, uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
|
||||
uint16_t timeout, uint8_t *dst, int dst_len);
|
||||
int ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
|
||||
uint8_t *dst, int dst_len);
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
int ble_hs_hci_cmd_build_le_set_ext_scan_params(uint8_t own_addr_type,
|
||||
uint8_t filter_policy,
|
||||
uint8_t phy_mask,
|
||||
uint8_t phy_count,
|
||||
struct ble_hs_hci_ext_scan_param *params[],
|
||||
uint8_t *dst, uint16_t dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_set_ext_scan_enable(uint8_t enable,
|
||||
uint8_t filter_dups,
|
||||
uint16_t duration,
|
||||
uint16_t period,
|
||||
uint8_t *dst, uint16_t dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_ext_create_conn(const struct hci_ext_create_conn *hcc,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,
|
||||
const uint8_t *addr,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
|
||||
uint8_t frag_pref, struct os_mbuf *data,
|
||||
uint8_t data_len,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable, uint8_t sets_num,
|
||||
const struct hci_ext_adv_set *sets,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
|
||||
const struct hci_ext_adv_params *params,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_periodic_adv_params(uint8_t handle,
|
||||
const struct hci_periodic_adv_params *params,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_periodic_adv_enable(uint8_t enable,
|
||||
uint8_t handle,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_periodic_adv_data(uint8_t handle, uint8_t operation,
|
||||
struct os_mbuf *data,
|
||||
uint8_t data_len,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_periodic_adv_create_sync(uint8_t filter_policy,
|
||||
uint8_t adv_sid,
|
||||
uint8_t adv_add_type,
|
||||
const uint8_t *adv_addr,
|
||||
uint16_t skip,
|
||||
uint16_t sync_timeout,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_periodic_adv_terminate_sync(uint16_t sync_handle,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_add_dev_to_periodic_adv_list(uint8_t adv_add_type,
|
||||
const uint8_t *adv_addr,
|
||||
uint8_t adv_sid,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
int
|
||||
ble_hs_hci_cmd_build_le_rem_dev_from_periodic_adv_list(uint8_t adv_add_type,
|
||||
const uint8_t *adv_addr,
|
||||
uint8_t adv_sid,
|
||||
uint8_t *cmd, int cmd_len);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
int ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan, uint8_t phy,
|
||||
uint8_t mod_idx,
|
||||
uint8_t *dst, uint16_t dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_enh_trans_test(uint8_t tx_chan,
|
||||
uint8_t test_data_len,
|
||||
uint8_t packet_payload_idx,
|
||||
uint8_t phy,
|
||||
uint8_t *dst, uint16_t dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_set_priv_mode(const uint8_t *addr, uint8_t addr_type,
|
||||
uint8_t priv_mode, uint8_t *dst,
|
||||
uint16_t dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_read_phy(uint16_t conn_handle, uint8_t *dst,
|
||||
int dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_set_default_phy(uint8_t tx_phys_mask,
|
||||
uint8_t rx_phys_mask,
|
||||
uint8_t *dst, int dst_len);
|
||||
|
||||
int ble_hs_hci_cmd_build_le_set_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
|
||||
uint8_t rx_phys_mask, uint16_t phy_opts,
|
||||
uint8_t *dst, int dst_len);
|
||||
|
||||
int ble_hs_hci_frag_num_mbufs(void);
|
||||
int ble_hs_hci_frag_num_mbufs_free(void);
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
#endif
|
||||
|
||||
int ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst,
|
||||
int dst_len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "ble_att_priv.h"
|
||||
#include "ble_gap_priv.h"
|
||||
#include "ble_gatt_priv.h"
|
||||
#include "ble_hs_dbg_priv.h"
|
||||
#include "ble_hs_hci_priv.h"
|
||||
#include "ble_hs_atomic_priv.h"
|
||||
#include "ble_hs_conn_priv.h"
|
||||
|
@ -118,7 +117,8 @@ int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
|||
int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||
struct ble_hs_conn **out_conn,
|
||||
struct ble_l2cap_chan **out_chan);
|
||||
uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type);
|
||||
uint8_t ble_hs_misc_own_addr_type_to_id(uint8_t addr_type);
|
||||
uint8_t ble_hs_misc_peer_addr_type_to_id(uint8_t addr_type);
|
||||
int ble_hs_misc_restore_irks(void);
|
||||
|
||||
int ble_hs_locked_by_cur_task(void);
|
||||
|
@ -142,31 +142,6 @@ int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg
|
|||
struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq);
|
||||
int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om);
|
||||
|
||||
#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG && !BLE_MONITOR
|
||||
|
||||
#define BLE_HS_LOG_CMD(is_tx, cmd_type, cmd_name, conn_handle, \
|
||||
log_cb, cmd) do \
|
||||
{ \
|
||||
BLE_HS_LOG(DEBUG, "%sed %s command: %s; conn=%d ", \
|
||||
(is_tx) ? "tx" : "rx", (cmd_type), (cmd_name), (conn_handle)); \
|
||||
(log_cb)(cmd); \
|
||||
BLE_HS_LOG(DEBUG, "\n"); \
|
||||
} while (0)
|
||||
|
||||
#define BLE_HS_LOG_EMPTY_CMD(is_tx, cmd_type, cmd_name, conn_handle) do \
|
||||
{ \
|
||||
BLE_HS_LOG(DEBUG, "%sed %s command: %s; conn=%d ", \
|
||||
(is_tx) ? "tx" : "rx", (cmd_type), (cmd_name), (conn_handle)); \
|
||||
BLE_HS_LOG(DEBUG, "\n"); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define BLE_HS_LOG_CMD(is_tx, cmd_type, cmd_name, conn_handle, log_cb, cmd)
|
||||
#define BLE_HS_LOG_EMPTY_CMD(is_tx, cmd_type, cmd_name, conn_handle)
|
||||
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
||||
#define BLE_HS_DBG_ASSERT(x) assert(x)
|
||||
#define BLE_HS_DBG_ASSERT_EVAL(x) assert(x)
|
||||
|
|
|
@ -57,25 +57,46 @@ struct ble_l2cap_coc_srv {
|
|||
int ble_l2cap_coc_init(void);
|
||||
int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu,
|
||||
ble_l2cap_event_fn *cb, void *cb_arg);
|
||||
int ble_l2cap_coc_create_srv_chan(uint16_t conn_handle, uint16_t psm,
|
||||
int ble_l2cap_coc_create_srv_chan(struct ble_hs_conn *conn, uint16_t psm,
|
||||
struct ble_l2cap_chan **chan);
|
||||
struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(uint16_t conn_handle,
|
||||
struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn,
|
||||
uint16_t psm, uint16_t mtu,
|
||||
struct os_mbuf *sdu_rx,
|
||||
ble_l2cap_event_fn *cb,
|
||||
void *cb_arg);
|
||||
void ble_l2cap_coc_cleanup_chan(struct ble_l2cap_chan *chan);
|
||||
void ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
|
||||
void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
|
||||
uint16_t credits);
|
||||
int ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan,
|
||||
struct os_mbuf *sdu_rx);
|
||||
int ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx);
|
||||
void ble_l2cap_coc_set_new_mtu_mps(struct ble_l2cap_chan *chan, uint16_t mtu, uint16_t mps);
|
||||
#else
|
||||
#define ble_l2cap_coc_init() 0
|
||||
#define ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg) BLE_HS_ENOTSUP
|
||||
#define ble_l2cap_coc_recv_ready(chan, sdu_rx) BLE_HS_ENOTSUP
|
||||
#define ble_l2cap_coc_cleanup_chan(chan)
|
||||
#define ble_l2cap_coc_send(chan, sdu_tx) BLE_HS_ENOTSUP
|
||||
static inline int
|
||||
ble_l2cap_coc_init(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu,
|
||||
ble_l2cap_event_fn *cb, void *cb_arg) {
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan,
|
||||
struct os_mbuf *sdu_rx) {
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan) {
|
||||
}
|
||||
|
||||
static inline int
|
||||
ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx) {
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -65,8 +65,20 @@ struct ble_l2cap_chan {
|
|||
uint16_t conn_handle;
|
||||
uint16_t dcid;
|
||||
uint16_t scid;
|
||||
uint16_t my_mtu;
|
||||
uint16_t peer_mtu; /* 0 if not exchanged. */
|
||||
|
||||
/* Unions just to avoid confusion on MPS/MTU.
|
||||
* In CoC context, L2CAP MTU is MPS
|
||||
*/
|
||||
union {
|
||||
uint16_t my_mtu;
|
||||
uint16_t my_coc_mps;
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t peer_mtu;
|
||||
uint16_t peer_coc_mps;
|
||||
};
|
||||
|
||||
ble_l2cap_chan_flags flags;
|
||||
|
||||
struct os_mbuf *rx_buf;
|
||||
|
@ -102,7 +114,7 @@ struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
|
|||
uint16_t len);
|
||||
|
||||
struct ble_l2cap_chan *ble_l2cap_chan_alloc(uint16_t conn_handle);
|
||||
void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
|
||||
void ble_l2cap_chan_free(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
|
||||
|
||||
bool ble_l2cap_is_mtu_req_sent(const struct ble_l2cap_chan *chan);
|
||||
|
||||
|
@ -118,6 +130,13 @@ void ble_l2cap_remove_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
|
|||
|
||||
int ble_l2cap_init(void);
|
||||
|
||||
/* Below experimental API is available when BLE_VERSION >= 52 */
|
||||
int ble_l2cap_enhanced_connect(uint16_t conn_handle,
|
||||
uint16_t psm, uint16_t mtu,
|
||||
uint8_t num, struct os_mbuf *sdu_rx[],
|
||||
ble_l2cap_event_fn *cb, void *cb_arg);
|
||||
int ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -74,6 +74,32 @@ struct ble_l2cap_sig_le_con_rsp {
|
|||
uint16_t result;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ble_l2cap_sig_credit_base_connect_req {
|
||||
uint16_t psm;
|
||||
uint16_t mtu;
|
||||
uint16_t mps;
|
||||
uint16_t credits;
|
||||
uint16_t scids[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ble_l2cap_sig_credit_base_connect_rsp {
|
||||
uint16_t mtu;
|
||||
uint16_t mps;
|
||||
uint16_t credits;
|
||||
uint16_t result;
|
||||
uint16_t dcids[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ble_l2cap_sig_credit_base_reconfig_req {
|
||||
uint16_t mtu;
|
||||
uint16_t mps;
|
||||
uint16_t dcids[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ble_l2cap_sig_credit_base_reconfig_rsp {
|
||||
uint16_t result;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ble_l2cap_sig_disc_req {
|
||||
uint16_t dcid;
|
||||
uint16_t scid;
|
||||
|
@ -107,9 +133,43 @@ int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan);
|
|||
int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid,
|
||||
uint16_t credits);
|
||||
#else
|
||||
#define ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg) \
|
||||
BLE_HS_ENOTSUP
|
||||
#define ble_l2cap_sig_disconnect(chan) BLE_HS_ENOTSUP
|
||||
static inline int
|
||||
ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
|
||||
struct os_mbuf *sdu_rx,
|
||||
ble_l2cap_event_fn *cb, void *cb_arg)
|
||||
{
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan)
|
||||
{
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
|
||||
int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle,
|
||||
uint16_t psm, uint16_t mtu,
|
||||
uint8_t num, struct os_mbuf *sdu_rx[],
|
||||
ble_l2cap_event_fn *cb, void *cb_arg);
|
||||
int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[],
|
||||
uint8_t num, uint16_t new_mtu);
|
||||
#else
|
||||
static inline int
|
||||
ble_l2cap_sig_ecoc_connect(uint16_t conn_handle,
|
||||
uint16_t psm, uint16_t mtu,
|
||||
uint8_t num, struct os_mbuf *sdu_rx[],
|
||||
ble_l2cap_event_fn *cb, void *cb_arg)
|
||||
{
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
static inline int
|
||||
ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[],
|
||||
uint8_t num, uint16_t new_mtu)
|
||||
{
|
||||
return BLE_HS_ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue