tags:
- build_docs
artifacts:
+ when: always
paths:
+ - docs/doxygen-warning-log.txt
+ - docs/sphinx-warning-log.txt
- docs/_build/html
expire_in: 1 mos
script:
- cd docs
- doxygen
- # If not building master branch, and there are Doxygen warnings, print them and bail out
- - test -n $IS_PRIVATE && test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
+ # If there are Doxygen warnings, print them and bail out
+ - test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
- make gh-linkcheck
- make html
+ # If there are Sphinx warnings, print them and bail out
+ # Ignore warnings (sphinx-known-warnings.txt) already reported in:
+ # https://github.com/sphinx-doc/sphinx/issues/2683
+ # https://github.com/sphinx-doc/sphinx/issues/4041
+ # If a new warning has to be added, then it should be documented as above
+ # Note: this check is not clever enough to ignore the same warning
+ # but reported for different line of documentation.
+ # If s warning stays the same and the line number has changed,
+ # then update 'sphinx-known-warnings.txt' to reflect the new lines numbers.
+ - DIFF_FORMAT="--changed-group-format=%<%> --unchanged-group-format="
+ - LOG_DIFF=$(diff $DIFF_FORMAT sphinx-known-warnings.txt sphinx-warning-log.txt)
+ - test -z "$LOG_DIFF" || ( echo "Sphinx pass had some new warnings:" && echo "$LOG_DIFF" && false )
test_nvs_on_host:
stage: test
#define ESP_APPTRACE_USR_DATA_LEN_MAX (ESP_APPTRACE_TRAX_BLOCK_SIZE - sizeof(esp_tracedata_hdr_t))
#endif
+#define ESP_APPTRACE_HW_TRAX 0
+#define ESP_APPTRACE_HW_MAX 1
+#define ESP_APPTRACE_HW(_i_) (&s_trace_hw[_i_])
+
/** Trace data header. Every user data chunk is prepended with this header.
* User allocates block with esp_apptrace_buffer_get and then fills it with data,
* in multithreading environment it can happen that tasks gets buffer and then gets interrupted,
static esp_apptrace_lock_t s_log_lock = {.irq_stat = 0, .portmux = portMUX_INITIALIZER_UNLOCKED};
#endif
+typedef struct {
+ uint8_t *(*get_up_buffer)(uint32_t, esp_apptrace_tmo_t *);
+ esp_err_t (*put_up_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_err_t (*flush_up_buffer)(uint32_t, esp_apptrace_tmo_t *);
+ uint8_t *(*get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *);
+ esp_err_t (*put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ bool (*host_is_connected)(void);
+} esp_apptrace_hw_t;
+
static uint32_t esp_apptrace_trax_down_buffer_write_nolock(uint8_t *data, uint32_t size);
static esp_err_t esp_apptrace_trax_flush(uint32_t min_sz, esp_apptrace_tmo_t *tmo);
+static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *tmo);
+static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, esp_apptrace_tmo_t *tmo);
+static bool esp_apptrace_trax_host_is_connected(void);
+static uint8_t *esp_apptrace_trax_down_buffer_get(uint32_t *size, esp_apptrace_tmo_t *tmo);
+static esp_err_t esp_apptrace_trax_down_buffer_put(uint8_t *ptr, esp_apptrace_tmo_t *tmo);
+
+static esp_apptrace_hw_t s_trace_hw[ESP_APPTRACE_HW_MAX] = {
+ {
+ .get_up_buffer = esp_apptrace_trax_get_buffer,
+ .put_up_buffer = esp_apptrace_trax_put_buffer,
+ .flush_up_buffer = esp_apptrace_trax_flush,
+ .get_down_buffer = esp_apptrace_trax_down_buffer_get,
+ .put_down_buffer = esp_apptrace_trax_down_buffer_put,
+ .host_is_connected = esp_apptrace_trax_host_is_connected
+ }
+};
static inline int esp_apptrace_log_lock()
{
return ptr;
}
-static inline esp_err_t esp_apptrace_trax_down_buffer_put(uint8_t *ptr, esp_apptrace_tmo_t *tmo)
+static esp_err_t esp_apptrace_trax_down_buffer_put(uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
/* nothing todo */
return ESP_OK;
uint32_t total_sz = 0;
while (total_sz < size) {
- // ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock WRS %d-%d-%d %d", s_trace_buf.rb_down.wr, s_trace_buf.rb_down.rd,
- // s_trace_buf.rb_down.cur_size, size);
+ ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock WRS %d-%d-%d %d", s_trace_buf.rb_down.wr, s_trace_buf.rb_down.rd,
+ s_trace_buf.rb_down.cur_size, size);
uint32_t wr_sz = esp_apptrace_rb_write_size_get(&s_trace_buf.rb_down);
if (wr_sz == 0) {
break;
if (wr_sz > size - total_sz) {
wr_sz = size - total_sz;
}
- // ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d", wr_sz);
+ ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %d", wr_sz);
uint8_t *ptr = esp_apptrace_rb_produce(&s_trace_buf.rb_down, wr_sz);
if (!ptr) {
assert(false && "Failed to produce bytes to down buffer!");
}
- // ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d to 0x%x from 0x%x", wr_sz, ptr, data + total_sz + wr_sz);
+ ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %d to 0x%x from 0x%x", wr_sz, ptr, data + total_sz + wr_sz);
memcpy(ptr, data + total_sz, wr_sz);
total_sz += wr_sz;
- // ESP_APPTRACE_LOGE("esp_apptrace_trax_down_buffer_write_nolock wr %d/%d", wr_sz, total_sz);
+ ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %d/%d", wr_sz, total_sz);
}
return total_sz;
}
return res;
}
+static bool esp_apptrace_trax_host_is_connected(void)
+{
+ return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
+}
+
static esp_err_t esp_apptrace_trax_dest_init()
{
for (int i = 0; i < ESP_APPTRACE_TRAX_BLOCKS_NUM; i++) {
{
int res = ESP_OK;
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- uint8_t *(*apptrace_get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *);
- esp_err_t (*apptrace_put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_get_down_buffer = esp_apptrace_trax_down_buffer_get;
- apptrace_put_down_buffer = esp_apptrace_trax_down_buffer_put;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
esp_apptrace_tmo_init(&tmo, user_tmo);
uint32_t act_sz = *size;
*size = 0;
- uint8_t * ptr = apptrace_get_down_buffer(&act_sz, &tmo);
+ uint8_t * ptr = hw->get_down_buffer(&act_sz, &tmo);
if (ptr && act_sz > 0) {
ESP_APPTRACE_LOGD("Read %d bytes from host", act_sz);
memcpy(buf, ptr, act_sz);
- res = apptrace_put_down_buffer(ptr, &tmo);
+ res = hw->put_down_buffer(ptr, &tmo);
*size = act_sz;
+ } else {
+ res = ESP_ERR_TIMEOUT;
}
return res;
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- uint8_t *(*apptrace_get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_get_down_buffer = esp_apptrace_trax_down_buffer_get;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return NULL;
// ESP_APPTRACE_LOGE("esp_apptrace_down_buffer_get %d", *size);
esp_apptrace_tmo_init(&tmo, user_tmo);
- return apptrace_get_down_buffer(size, &tmo);
+ return hw->get_down_buffer(size, &tmo);
}
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- esp_err_t (*apptrace_put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_put_down_buffer = esp_apptrace_trax_down_buffer_put;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_init(&tmo, user_tmo);
- return apptrace_put_down_buffer(ptr, &tmo);
+ return hw->put_down_buffer(ptr, &tmo);
}
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t user_tmo)
{
uint8_t *ptr = NULL;
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
- esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_get_buffer = esp_apptrace_trax_get_buffer;
- apptrace_put_buffer = esp_apptrace_trax_put_buffer;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_init(&tmo, user_tmo);
- ptr = apptrace_get_buffer(size, &tmo);
+ ptr = hw->get_up_buffer(size, &tmo);
if (ptr == NULL) {
return ESP_ERR_NO_MEM;
}
memcpy(ptr, data, size);
// now indicate that this buffer is ready to be sent off to host
- return apptrace_put_buffer(ptr, &tmo);
+ return hw->put_up_buffer(ptr, &tmo);
}
int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap)
uint16_t nargs = 0;
uint8_t *pout, *p = (uint8_t *)fmt;
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
- esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_get_buffer = esp_apptrace_trax_get_buffer;
- apptrace_put_buffer = esp_apptrace_trax_put_buffer;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
ESP_APPTRACE_LOGE("Failed to store all printf args!");
}
- pout = apptrace_get_buffer(1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
+ pout = hw->get_up_buffer(1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
if (pout == NULL) {
ESP_APPTRACE_LOGE("Failed to get buffer!");
return -1;
ESP_APPTRACE_LOGD("arg %x", arg);
}
- int ret = apptrace_put_buffer(p, &tmo);
+ int ret = hw->put_up_buffer(p, &tmo);
if (ret != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to put printf buf (%d)!", ret);
return -1;
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- uint8_t *(*apptrace_get_buffer)(uint32_t, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_get_buffer = esp_apptrace_trax_get_buffer;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return NULL;
}
esp_apptrace_tmo_init(&tmo, user_tmo);
- return apptrace_get_buffer(size, &tmo);
+ return hw->get_up_buffer(size, &tmo);
}
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
{
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- esp_err_t (*apptrace_put_buffer)(uint8_t *, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_put_buffer = esp_apptrace_trax_put_buffer;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_init(&tmo, user_tmo);
- return apptrace_put_buffer(ptr, &tmo);
+ return hw->put_up_buffer(ptr, &tmo);
}
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t usr_tmo)
{
esp_apptrace_tmo_t tmo;
- //TODO: use ptr to HW transport iface struct
- esp_err_t (*apptrace_flush)(uint32_t, esp_apptrace_tmo_t *);
+ esp_apptrace_hw_t *hw = NULL;
if (dest == ESP_APPTRACE_DEST_TRAX) {
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
- apptrace_flush = esp_apptrace_trax_flush;
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
#else
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
return ESP_ERR_NOT_SUPPORTED;
}
esp_apptrace_tmo_init(&tmo, usr_tmo);
- return apptrace_flush(min_sz, &tmo);
+ return hw->flush_up_buffer(min_sz, &tmo);
}
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t usr_tmo)
return res;
}
+
+bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
+{
+ esp_apptrace_hw_t *hw = NULL;
+
+ if (dest == ESP_APPTRACE_DEST_TRAX) {
+#if CONFIG_ESP32_APPTRACE_DEST_TRAX
+ hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
+#else
+ ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
+ return ESP_ERR_NOT_SUPPORTED;
+#endif
+ } else {
+ ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
+ return ESP_ERR_NOT_SUPPORTED;
+ }
+ return hw->host_is_connected();
+}
+
#endif
COMPONENT_SRCDIRS := .
-COMPONENT_ADD_INCLUDEDIRS := include
+COMPONENT_ADD_INCLUDEDIRS = include
-COMPONENT_ADD_LDFLAGS := -lapp_trace
+COMPONENT_ADD_LDFLAGS = -lapp_trace
+
+# do not produce gcov info for this module, it is used as transport for gcov
+CFLAGS := $(subst --coverage,,$(CFLAGS))
ifdef CONFIG_SYSVIEW_ENABLE
-#COMPONENT_EXTRA_INCLUDES := freertos
COMPONENT_ADD_INCLUDEDIRS += \
sys_view/Config \
sys_view/Sample/OS
COMPONENT_SRCDIRS += \
+ gcov \
sys_view/SEGGER \
sys_view/Sample/OS \
sys_view/Sample/Config \
sys_view/esp32
+else
+COMPONENT_SRCDIRS += gcov
endif
--- /dev/null
+// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed 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.
+
+// This module implements runtime file I/O API for GCOV.
+
+#include "esp_task_wdt.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "soc/cpu.h"
+#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
+#include "esp_app_trace.h"
+
+#if CONFIG_ESP32_APPTRACE_ENABLE
+
+#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
+#include "esp_log.h"
+const static char *TAG = "esp_gcov_rtio";
+
+static void (*s_gcov_exit)(void);
+static uint8_t s_gcov_down_buf[256];
+
+void esp_gcov_dump()
+{
+#if CONFIG_FREERTOS_UNICORE == 0
+ esp_cpu_stall(!xPortGetCoreID());
+#endif
+
+ while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
+ // to avoid complains that task watchdog got triggered for other tasks
+ TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+ TIMERG0.wdt_feed=1;
+ TIMERG0.wdt_wprotect=0;
+ // to avoid reboot on INT_WDT
+ TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+ TIMERG1.wdt_feed=1;
+ TIMERG1.wdt_wprotect=0;
+ }
+
+ if (s_gcov_exit) {
+ s_gcov_exit();
+ }
+
+ int ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!\n", ret);
+ }
+}
+
+int gcov_rtio_atexit(void (*function)(void))
+{
+ s_gcov_exit = function;
+ esp_apptrace_down_buffer_config(s_gcov_down_buf, sizeof(s_gcov_down_buf));
+ return 0;
+}
+
+void *gcov_rtio_fopen(const char *path, const char *mode)
+{
+ return esp_apptrace_fopen(ESP_APPTRACE_DEST_TRAX, path, mode);
+}
+
+int gcov_rtio_fclose(void *stream)
+{
+ return esp_apptrace_fclose(ESP_APPTRACE_DEST_TRAX, stream);
+}
+
+size_t gcov_rtio_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ return esp_apptrace_fwrite(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
+}
+
+int gcov_rtio_fseek(void *stream, long offset, int whence)
+{
+ return esp_apptrace_fseek(ESP_APPTRACE_DEST_TRAX, stream, offset, whence);
+}
+
+long gcov_rtio_ftell(void *stream)
+{
+ return esp_apptrace_ftell(ESP_APPTRACE_DEST_TRAX, stream);
+}
+
+#endif
--- /dev/null
+// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed 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.
+//
+// Hot It Works
+// ************
+//
+// This module implements host file I/O protocol on top of apptrace module.
+// The protocol is enough simple. It sends command with arguments to the host and receives response from it.
+// Responses contains return values of respective file I/O API. This value is returned to the caller.
+// Commands has the following format:
+// * Header. See esp_apptrace_fcmd_hdr_t.
+// * Operation arguments. See file operation helper structures below.
+
+#include <string.h>
+#include "esp_app_trace.h"
+
+#if CONFIG_ESP32_APPTRACE_ENABLE
+
+#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
+#include "esp_log.h"
+const static char *TAG = "esp_host_file_io";
+
+#define ESP_APPTRACE_FILE_CMD_FOPEN 0x0
+#define ESP_APPTRACE_FILE_CMD_FCLOSE 0x1
+#define ESP_APPTRACE_FILE_CMD_FWRITE 0x2
+#define ESP_APPTRACE_FILE_CMD_FREAD 0x3
+#define ESP_APPTRACE_FILE_CMD_FSEEK 0x4
+#define ESP_APPTRACE_FILE_CMD_FTELL 0x5
+#define ESP_APPTRACE_FILE_CMD_STOP 0x6 // indicates that there is no files to transfer
+
+/** File operation header */
+typedef struct {
+ uint8_t cmd; ///< Command ID
+} esp_apptrace_fcmd_hdr_t;
+
+/** Helper structure for fopen */
+typedef struct {
+ const char *path;
+ uint16_t path_len;
+ const char *mode;
+ uint16_t mode_len;
+} esp_apptrace_fopen_args_t;
+
+/** Helper structure for fclose */
+typedef struct {
+ void *file;
+} esp_apptrace_fclose_args_t;
+
+/** Helper structure for fwrite */
+typedef struct {
+ void * buf;
+ size_t size;
+ void * file;
+} esp_apptrace_fwrite_args_t;
+
+/** Helper structure for fread */
+typedef struct {
+ size_t size;
+ void * file;
+} esp_apptrace_fread_args_t;
+
+/** Helper structure for fseek */
+typedef struct {
+ long offset;
+ int whence;
+ void * file;
+} esp_apptrace_fseek_args_t;
+
+/** Helper structure for ftell */
+typedef struct {
+ void *file;
+} esp_apptrace_ftell_args_t;
+
+static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
+{
+ esp_err_t ret;
+ esp_apptrace_fcmd_hdr_t *hdr;
+
+ uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
+ if (ptr == NULL) {
+ return ESP_ERR_NO_MEM;
+ }
+
+ hdr = (esp_apptrace_fcmd_hdr_t *)ptr;
+ hdr->cmd = cmd;
+ if (prep_args) {
+ prep_args(ptr + sizeof(hdr->cmd), args);
+ }
+
+ // now indicate that this buffer is ready to be sent off to host
+ ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
+ return ret;
+ }
+
+ ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
+ return ret;
+ }
+
+ return ESP_OK;
+}
+
+static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
+{
+ uint32_t tot_rd = 0;
+ while (tot_rd < buf_len) {
+ uint32_t rd_size = buf_len - tot_rd;
+ esp_err_t ret = esp_apptrace_read(dest, buf, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return ret;
+ }
+ tot_rd += rd_size;
+ }
+
+ return ESP_OK;
+}
+
+static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_fopen_args_t *args = priv;
+
+ memcpy(buf, args->path, args->path_len);
+ memcpy(buf + args->path_len, args->mode, args->mode_len);
+}
+
+void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
+{
+ esp_apptrace_fopen_args_t cmd_args;
+
+ cmd_args.path = path;
+ cmd_args.path_len = strlen(path) + 1;
+ cmd_args.mode = mode;
+ cmd_args.mode_len = strlen(mode) + 1;
+
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
+ &cmd_args, cmd_args.path_len+cmd_args.mode_len);
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return NULL;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(void *)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return NULL;
+ }
+
+ return *((void **)resp);
+}
+
+static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_fclose_args_t *args = priv;
+
+ memcpy(buf, &args->file, sizeof(args->file));
+}
+
+int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
+{
+ esp_apptrace_fclose_args_t cmd_args;
+
+ cmd_args.file = stream;
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
+ &cmd_args, sizeof(cmd_args));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return EOF;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(int)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return EOF;
+ }
+
+ return *((int *)resp);
+}
+
+static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_fwrite_args_t *args = priv;
+
+ memcpy(buf, &args->file, sizeof(args->file));
+ memcpy(buf + sizeof(args->file), args->buf, args->size);
+}
+
+size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ esp_apptrace_fwrite_args_t cmd_args;
+
+ cmd_args.buf = (void *)ptr;
+ cmd_args.size = size * nmemb;
+ cmd_args.file = stream;
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
+ &cmd_args, sizeof(cmd_args.file)+cmd_args.size);
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return 0;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(size_t)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return 0;
+ }
+
+ return *((size_t *)resp);
+}
+
+static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_fread_args_t *args = priv;
+
+ memcpy(buf, &args->file, sizeof(args->file));
+ memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
+}
+
+size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ esp_apptrace_fread_args_t cmd_args;
+
+ cmd_args.size = size * nmemb;
+ cmd_args.file = stream;
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
+ &cmd_args, sizeof(cmd_args));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return 0;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(size_t)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return 0;
+ }
+ if (*((size_t *)resp) > 0) {
+ ret = esp_apptrace_file_rsp_recv(dest, ptr, *((size_t *)resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read file data (%d)!", ret);
+ return 0;
+ }
+ }
+ return *((size_t *)resp);
+}
+
+static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_fseek_args_t *args = priv;
+
+ memcpy(buf, &args->file, sizeof(args->file));
+}
+
+int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
+{
+ esp_apptrace_fseek_args_t cmd_args;
+
+ cmd_args.file = stream;
+ cmd_args.offset = offset;
+ cmd_args.whence = whence;
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
+ &cmd_args, sizeof(cmd_args));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return -1;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(int)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return -1;
+ }
+
+ return *((int *)resp);
+}
+
+static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
+{
+ esp_apptrace_ftell_args_t *args = priv;
+
+ memcpy(buf, &args->file, sizeof(args->file));
+}
+
+int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
+{
+ esp_apptrace_ftell_args_t cmd_args;
+
+ cmd_args.file = stream;
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
+ &cmd_args, sizeof(cmd_args));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
+ return -1;
+ }
+
+ // now read the answer
+ uint8_t resp[sizeof(int)];
+ ret = esp_apptrace_file_rsp_recv(dest, resp, sizeof(resp));
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
+ return -1;
+ }
+
+ return *((int *)resp);
+}
+
+int esp_apptrace_fstop(esp_apptrace_dest_t dest)
+{
+ esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
+ }
+ return ret;
+}
+
+#endif
*/
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
+/**
+ * @brief Checks whether host is connected.
+ *
+ * @param dest Indicates HW interface to use.
+ *
+ * @return true if host is connected, otherwise false
+ */
+bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest);
+
+/**
+ * @brief Opens file on host.
+ * This function has the same semantic as 'fopen' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param path Path to file.
+ * @param mode Mode string. See fopen for details.
+ *
+ * @return non zero file handle on success, otherwise 0
+ */
+void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode);
+
+/**
+ * @brief Closes file on host.
+ * This function has the same semantic as 'fclose' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param stream File handle returned by esp_apptrace_fopen.
+ *
+ * @return Zero on success, otherwise non-zero. See fclose for details.
+ */
+int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream);
+
+/**
+ * @brief Writes to file on host.
+ * This function has the same semantic as 'fwrite' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param ptr Address of data to write.
+ * @param size Size of an item.
+ * @param nmemb Number of items to write.
+ * @param stream File handle returned by esp_apptrace_fopen.
+ *
+ * @return Number of written items. See fwrite for details.
+ */
+size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream);
+
+/**
+ * @brief Read file on host.
+ * This function has the same semantic as 'fread' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param ptr Address to store read data.
+ * @param size Size of an item.
+ * @param nmemb Number of items to read.
+ * @param stream File handle returned by esp_apptrace_fopen.
+ *
+ * @return Number of read items. See fread for details.
+ */
+size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream);
+
+/**
+ * @brief Set position indicator in file on host.
+ * This function has the same semantic as 'fseek' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param stream File handle returned by esp_apptrace_fopen.
+ * @param offset Offset. See fseek for details.
+ * @param whence Position in file. See fseek for details.
+ *
+ * @return Zero on success, otherwise non-zero. See fseek for details.
+ */
+int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence);
+
+/**
+ * @brief Get current position indicator for file on host.
+ * This function has the same semantic as 'ftell' except for the first argument.
+ *
+ * @param dest Indicates HW interface to use.
+ * @param stream File handle returned by esp_apptrace_fopen.
+ *
+ * @return Current position in file. See ftell for details.
+ */
+int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream);
+
+/**
+ * @brief Indicates to the host that all file operations are completed.
+ * This function should be called after all file operations are finished and
+ * indicate to the host that it can perform cleanup operations (close open files etc.).
+ *
+ * @param dest Indicates HW interface to use.
+ *
+ * @return ESP_OK on success, otherwise see esp_err_t
+ */
+int esp_apptrace_fstop(esp_apptrace_dest_t dest);
+
+/**
+ * @brief Triggers gcov info dump.
+ * This function waits for the host to connect to target before dumping data.
+ */
+void esp_gcov_dump(void);
+
#endif
#include "bt_trace.h"
#include "btc_manage.h"
#include "btc_gap_ble.h"
+#include "btc_ble_storage.h"
esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
-esp_err_t esp_ble_clear_bond_device_list(void)
+int esp_ble_get_bond_device_num(void)
{
- btc_msg_t msg;
- msg.sig = BTC_SIG_API_CALL;
- msg.pid = BTC_PID_GAP_BLE;
- msg.act = BTC_GAP_BLE_CLEAR_BOND_DEV_EVT;
+ ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
- return (btc_transfer_context(&msg, NULL, 0, NULL)
- == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+ return btc_storage_get_num_ble_bond_devices();
}
-esp_err_t esp_ble_get_bond_device_list(void)
+esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_list)
{
- btc_msg_t msg;
- msg.sig = BTC_SIG_API_CALL;
- msg.pid = BTC_PID_GAP_BLE;
- msg.act = BTC_GAP_BLE_GET_BOND_DEV_EVT;
+ int ret;
+ int dev_num_total;
- return (btc_transfer_context(&msg, NULL, 0, NULL)
- == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+ if (dev_num == NULL || dev_list == NULL) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+ dev_num_total = btc_storage_get_num_ble_bond_devices();
+ if (*dev_num > dev_num_total) {
+ *dev_num = dev_num_total;
+ }
+
+ ret = btc_storage_get_bonded_ble_devices_list(dev_list, *dev_num);
+
+ return (ret == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device)
ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT, /*!< When set pkt lenght complete, the event comes */
ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT, /*!< When Enable/disable privacy on the local device complete, the event comes */
ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT, /*!< When remove the bond device complete, the event comes */
- ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT, /*!< When clear the bond device clear complete, the event comes */
- ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT, /*!< When get the bond device list complete, the event comes */
ESP_GAP_BLE_EVT_MAX,
} esp_gap_ble_cb_event_t;
esp_bt_status_t status; /*!< Indicate the remove bond device operation success status */
esp_bd_addr_t bd_addr; /*!< The device address which has been remove from the bond list */
}remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
- /**
- * @brief ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
- */
- struct ble_clear_bond_dev_cmpl_evt_param {
- esp_bt_status_t status; /*!< Indicate the clear bond device operation success status */
- }clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
- /**
- * @brief ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT
- */
- struct ble_get_bond_dev_cmpl_evt_param {
- esp_bt_status_t status; /*!< Indicate the get bond device operation success status */
- uint8_t dev_num; /*!< Indicate the get number device in the bond list */
- esp_ble_bond_dev_t *bond_dev; /*!< the pointer to the bond device Structure */
- }get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
} esp_ble_gap_cb_param_t;
/**
esp_err_t esp_ble_remove_bond_device(esp_bd_addr_t bd_addr);
/**
-* @brief Removes all of the device from the security database list of
-* peer device. It manages unpairing event while connected.
+* @brief Get the device number from the security database list of peer device.
+* It will return the device bonded number immediately.
*
-* @return - ESP_OK : success
-* - other : failed
+* @return - >= 0 : bonded devices number.
+* - < 0 : failed
*
*/
-esp_err_t esp_ble_clear_bond_device_list(void);
+int esp_ble_get_bond_device_num(void);
+
/**
* @brief Get the device from the security database list of peer device.
-* It will return the device bonded information from the ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT event.
+* It will return the device bonded information immediately.
+* @param[inout] dev_num: Indicate the dev_list array(buffer) size as input.
+* If dev_num is large enough, it means the actual number as output.
+* Suggest that dev_num value equal to esp_ble_get_bond_device_num().
*
-* @return - ESP_OK : success
-* - other : failed
+* @param[out] dev_list: an array(buffer) of `esp_ble_bond_dev_t` type. Use for storing the bonded devices address.
+* The dev_list should be allocated by who call this API.
+* @return - ESP_OK : success
+* - other : failed
*
*/
-esp_err_t esp_ble_get_bond_device_list(void);
+esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_list);
/**
* @brief This function is to disconnect the physical connection of the peer device
#if (SMP_INCLUDED == TRUE)
-btc_dm_pairing_cb_t pairing_cb;
-btc_dm_local_key_cb_t ble_local_key_cb;
-btc_bonded_devices_t bonded_devices;
-
-
-/*******************************************************************************
-**
-** Function btc_storage_load_bonded_devices
-**
-** Description btc storage API - Loads all the bonded devices from NVRAM
-** and adds to the BTA.
-** Additionally, this API also invokes the adaper_properties_cb
-** and remote_device_properties_cb for each of the bonded devices.
-**
-** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
-**
-*******************************************************************************/
-bt_status_t btc_storage_load_bonded_ble_devices(void)
-{
- bt_status_t status;
- status = btc_in_fetch_bonded_ble_devices(1);
- LOG_DEBUG("Storage load rslt %d\n", status);
- return status;
-}
-
-bt_status_t btc_in_fetch_bonded_ble_devices(int add)
+static void _btc_storage_save(void)
{
- bt_status_t status = BT_STATUS_FAIL;
- int device_type = 0;
- for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
- iter = btc_config_section_next(iter)) {
- const char *name = btc_config_section_name(iter);
- if (!string_is_bdaddr(name) ||
- !btc_config_get_int(name, BTC_LE_DEV_TYPE, &device_type) ||
- ((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
- continue;
- }
- LOG_DEBUG("%s, name = %s", __func__, name);
- if (btc_in_fetch_bonded_ble_device(name, add, &bonded_devices) != BT_STATUS_SUCCESS) {
- LOG_DEBUG("Remote device:%s, no link key or ble key found", name);
- } else {
- status = BT_STATUS_SUCCESS;
- }
- }
+ const btc_config_section_iter_t *iter = btc_config_section_begin();
- return status;
-}
+ while (iter != btc_config_section_end()) {
+ //store the next iter, if remove section, then will not loss the point
-bt_status_t btc_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev)
-{
- bt_bdaddr_t bd_addr;
- int device_type = 0;
- char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
- for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
- iter = btc_config_section_next(iter)) {
- const char *name = btc_config_section_name(iter);
- if (!string_is_bdaddr(name) ||
- !btc_config_get_int(name, BTC_LE_DEV_TYPE, &device_type) ||
- ((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
+ const char *section = btc_config_section_name(iter);
+ if (!string_is_bdaddr(section)) {
+ iter = btc_config_section_next(iter);
continue;
}
- string_to_bdaddr(name, &bd_addr);
- memcpy(bond_dev->bd_addr, bd_addr.address, sizeof(bt_bdaddr_t));
- //resolve the peer device long term key
- if (btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PENC, buffer, sizeof(tBTM_LE_PENC_KEYS))
- == BT_STATUS_SUCCESS) {
- bond_dev->bond_key.key_mask |= ESP_BLE_ENC_KEY_MASK;
- memcpy(&bond_dev->bond_key.penc_key, buffer, sizeof(tBTM_LE_PENC_KEYS));
- }
- //resolve the peer device csrk
- if (btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PCSRK, buffer, sizeof(tBTM_LE_PCSRK_KEYS))
- == BT_STATUS_SUCCESS) {
- bond_dev->bond_key.key_mask |= ESP_BLE_CSR_KEY_MASK;
- memcpy(&bond_dev->bond_key.pcsrk_key, buffer, sizeof(tBTM_LE_PCSRK_KEYS));
- }
- //resolve the peer device irk
- if (btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS))
- == BT_STATUS_SUCCESS) {
- bond_dev->bond_key.key_mask |= ESP_BLE_ID_KEY_MASK;
- memcpy(&bond_dev->bond_key.pid_key, buffer, sizeof(tBTM_LE_PID_KEYS));
+ if (!btc_config_exist(section, BTC_BLE_STORAGE_DEV_TYPE_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_ADDR_TYPE_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LINK_KEY_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_PENC_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_PID_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_LENC_STR) &&
+ !btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR)) {
+ iter = btc_config_section_next(iter);
+ btc_config_remove_section(section);
+ continue;
}
- //serch for the next bond device
- bond_dev++;
- }
-
- return BT_STATUS_SUCCESS;
-}
-
-void btc_dm_remove_ble_bonding_keys(void)
-{
- bt_bdaddr_t bd_addr;
- LOG_DEBUG("%s\n",__func__);
-
- bdcpy(bd_addr.address, pairing_cb.bd_addr);
- btc_storage_remove_ble_bonding_keys(&bd_addr);
-}
-
-void btc_save_ble_bonding_keys(void)
-{
- bt_bdaddr_t bd_addr;
-
- bdcpy(bd_addr.address, pairing_cb.bd_addr);
- bdstr_t bdstr;
- bdaddr_to_string(&bd_addr, bdstr, sizeof(bdstr));
- btc_config_set_int(bdstr, BTC_LE_DEV_TYPE, BT_DEVICE_TYPE_BLE);
- LOG_DEBUG("%s, penc = %d, pid = %d", __func__, pairing_cb.ble.is_penc_key_rcvd, pairing_cb.ble.is_pid_key_rcvd);
- if (pairing_cb.ble.is_penc_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- (char *) &pairing_cb.ble.penc_key,
- BTM_LE_KEY_PENC,
- sizeof(tBTM_LE_PENC_KEYS));
- }
-
- if (pairing_cb.ble.is_pid_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- (char *) &pairing_cb.ble.pid_key,
- BTM_LE_KEY_PID,
- sizeof(tBTM_LE_PID_KEYS));
- }
-
-
- if (pairing_cb.ble.is_pcsrk_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- (char *) &pairing_cb.ble.pcsrk_key,
- BTM_LE_KEY_PCSRK,
- sizeof(tBTM_LE_PCSRK_KEYS));
- }
-
-
- if (pairing_cb.ble.is_lenc_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- (char *) &pairing_cb.ble.lenc_key,
- BTM_LE_KEY_LENC,
- sizeof(tBTM_LE_LENC_KEYS));
- }
- if (pairing_cb.ble.is_lcsrk_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- (char *) &pairing_cb.ble.lcsrk_key,
- BTM_LE_KEY_LCSRK,
- sizeof(tBTM_LE_LCSRK_KEYS));
+ iter = btc_config_section_next(iter);
}
- if (pairing_cb.ble.is_lidk_key_rcvd) {
- btc_storage_add_ble_bonding_key(&bd_addr,
- NULL,
- BTM_LE_KEY_LID,
- 0);
- }
+ btc_config_flush();
}
-static void btc_read_le_key(const uint8_t key_type, const size_t key_len, bt_bdaddr_t bd_addr,
- const uint8_t addr_type, const bool add_key, bool *device_added, bool *key_found)
+void btc_storage_save(void)
{
- assert(device_added);
- assert(key_found);
-
- char buffer[100];
- memset(buffer, 0, sizeof(buffer));
- if (btc_storage_get_ble_bonding_key(&bd_addr, key_type, buffer, key_len) == BT_STATUS_SUCCESS) {
- if (add_key) {
- BD_ADDR bta_bd_addr;
- bdcpy(bta_bd_addr, bd_addr.address);
-
- if (!*device_added) {
- BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
- *device_added = true;
- }
-
- char bd_str[20] = {0};
- LOG_DEBUG("%s() Adding key type %d for %s", __func__,
- key_type, bdaddr_to_string(&bd_addr, bd_str, sizeof(bd_str)));
- BTA_DmAddBleKey(bta_bd_addr, (tBTA_LE_KEY_VALUE *)buffer, key_type);
- }
-
- *key_found = true;
- }
+ btc_config_lock();
+ _btc_storage_save();
+ btc_config_unlock();
}
-bt_status_t btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+static bt_status_t _btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
char *key,
uint8_t key_type,
uint8_t key_length)
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
const char* name;
+
switch (key_type) {
case BTM_LE_KEY_PENC:
- name = "LE_KEY_PENC";
+ name = BTC_BLE_STORAGE_LE_KEY_PENC_STR;
break;
case BTM_LE_KEY_PID:
- name = "LE_KEY_PID";
+ name = BTC_BLE_STORAGE_LE_KEY_PID_STR;
break;
case BTM_LE_KEY_PCSRK:
- name = "LE_KEY_PCSRK";
+ name = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR;
break;
case BTM_LE_KEY_LENC:
- name = "LE_KEY_LENC";
+ name = BTC_BLE_STORAGE_LE_KEY_LENC_STR;
break;
case BTM_LE_KEY_LCSRK:
- name = "LE_KEY_LCSRK";
+ name = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR;
break;
case BTM_LE_KEY_LID:
- name = "LE_KEY_LID";
+ name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
break;
default:
return BT_STATUS_FAIL;
}
int ret = btc_config_set_bin(bdstr, name, (const uint8_t *)key, key_length);
- btc_config_save();
+ _btc_storage_save();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
+bt_status_t btc_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+ char *key,
+ uint8_t key_type,
+ uint8_t key_length)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_add_ble_bonding_key(remote_bd_addr, key, key_type, key_length);
+ btc_config_unlock();
+
+ return ret;
+}
/*******************************************************************************
**
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+static bt_status_t _btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
uint8_t key_type,
char *key_value,
int key_length)
const char* name;
switch (key_type) {
case BTM_LE_KEY_PENC:
- name = "LE_KEY_PENC";
+ name = BTC_BLE_STORAGE_LE_KEY_PENC_STR;
break;
case BTM_LE_KEY_PID:
- name = "LE_KEY_PID";
+ name = BTC_BLE_STORAGE_LE_KEY_PID_STR;
break;
case BTM_LE_KEY_PCSRK:
- name = "LE_KEY_PCSRK";
+ name = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR;
break;
case BTM_LE_KEY_LENC:
- name = "LE_KEY_LENC";
+ name = BTC_BLE_STORAGE_LE_KEY_LENC_STR;
break;
case BTM_LE_KEY_LCSRK:
- name = "LE_KEY_LCSRK";
+ name = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR;
break;
case BTM_LE_KEY_LID:
- name = "LE_KEY_LID";
+ name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
default:
return BT_STATUS_FAIL;
}
}
-bool btc_storage_compare_address_key_value(bt_bdaddr_t *remote_bd_addr,
- uint8_t key_type, void *key_value, int key_length)
+bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+ uint8_t key_type,
+ char *key_value,
+ int key_length)
{
- bdstr_t bdstr;
- bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
- char *key_type_str;
- switch (key_type) {
- case BTM_LE_KEY_PENC:
- key_type_str = "LE_KEY_PENC";
- break;
- case BTM_LE_KEY_PID:
- key_type_str = "LE_KEY_PID";
- break;
- case BTM_LE_KEY_PCSRK:
- key_type_str = "LE_KEY_PCSRK";
- break;
- case BTM_LE_KEY_LENC:
- key_type_str = "LE_KEY_LENC";
- break;
- case BTM_LE_KEY_LCSRK:
- key_type_str = "LE_KEY_LCSRK";
- break;
- case BTM_LE_KEY_LID:
- key_type_str = "LE_KEY_LID";
- default:
- return false;
- }
+ bt_status_t ret;
- return btc_compare_address_key_value(bdstr, key_type_str, key_value, key_length);
-}
+ btc_config_lock();
+ ret = _btc_storage_get_ble_bonding_key(remote_bd_addr, key_type, key_value, key_length);
+ btc_config_unlock();
+ return ret;
+}
/*******************************************************************************
**
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
+static bt_status_t _btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
{
+ int ret = 1;
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+
BTIF_TRACE_DEBUG(" %s in bd addr:%s",__FUNCTION__, bdstr);
- int ret = 1;
- if (btc_config_exist(bdstr, BTC_LE_DEV_TYPE)) {
- ret &= btc_config_remove(bdstr, BTC_LE_DEV_TYPE);
+
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR);
}
- if (btc_config_exist(bdstr, "LE_KEY_PENC")) {
- ret &= btc_config_remove(bdstr, "LE_KEY_PENC");
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PENC_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PENC_STR);
}
- if (btc_config_exist(bdstr, "LE_KEY_PID")) {
- ret &= btc_config_remove(bdstr, "LE_KEY_PID");
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PID_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PID_STR);
}
- if (btc_config_exist(bdstr, "LE_KEY_PCSRK")) {
- ret &= btc_config_remove(bdstr, "LE_KEY_PCSRK");
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR);
}
- if (btc_config_exist(bdstr, "LE_KEY_LENC")) {
- ret &= btc_config_remove(bdstr, "LE_KEY_LENC");
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_LENC_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LENC_STR);
}
- if (btc_config_exist(bdstr, "LE_KEY_LCSRK")) {
- ret &= btc_config_remove(bdstr, "LE_KEY_LCSRK");
+ if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR);
}
- //remove the address information after delete the ble key.
- ret = btc_config_remove_section(bdstr);
- btc_config_save();
+ //here don't remove section, because config_save will check it
+ _btc_storage_save();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
-bt_status_t btc_storage_clear_bond_devices(void)
+bt_status_t btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
{
- bt_bdaddr_t bd_addr;
- int device_type = 0;
- for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
- iter = btc_config_section_next(iter)) {
- const char *name = btc_config_section_name(iter);
- if (!string_is_bdaddr(name) &&
- !btc_config_get_int(name, BTC_LE_DEV_TYPE, &device_type) &&
- ((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
- continue;
- }
+ bt_status_t ret;
- string_to_bdaddr(name, &bd_addr);
- //remove the ble bonding keys from the config and then save the config to the flash
- if (btc_storage_remove_ble_bonding_keys(&bd_addr) != BT_STATUS_SUCCESS) {
- LOG_ERROR("%s, remove bonding key faild", __func__);
- return BT_STATUS_FAIL;
- }
- // the bonded_devices Structure record the devices which has been added to the BTM layer global variable
- for (int i = 0; i < bonded_devices.num_devices; i++) {
- //if the address is equal to the record device address, remove it from the BTM layer global variable
- if (!memcmp(bd_addr.address, bonded_devices.devices[i].address, sizeof(bt_bdaddr_t))) {
- BD_ADDR bta_addr;
- memcpy(bta_addr, bd_addr.address, sizeof(BD_ADDR));
- if(BTA_DmRemoveDevice(bta_addr) != BTA_SUCCESS) {
- LOG_ERROR("%s, remove device faild", __func__);
- return BT_STATUS_FAIL;
- }
- }
- }
- }
+ btc_config_lock();
+ ret = _btc_storage_remove_ble_bonding_keys(remote_bd_addr);
+ btc_config_unlock();
- return BT_STATUS_SUCCESS;
+ return ret;
}
/*******************************************************************************
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_add_ble_local_key(char *key,
+static bt_status_t _btc_storage_add_ble_local_key(char *key,
uint8_t key_type,
uint8_t key_length)
{
const char* name;
switch (key_type) {
case BTC_LE_LOCAL_KEY_IR:
- name = "LE_LOCAL_KEY_IR";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_IR_STR;
break;
case BTC_LE_LOCAL_KEY_IRK:
- name = "LE_LOCAL_KEY_IRK";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_IRK_STR;
break;
case BTC_LE_LOCAL_KEY_DHK:
- name = "LE_LOCAL_KEY_DHK";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_DHK_STR;
break;
case BTC_LE_LOCAL_KEY_ER:
- name = "LE_LOCAL_KEY_ER";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_ER_STR;
break;
default:
return BT_STATUS_FAIL;
}
- int ret = btc_config_set_bin("Adapter", name, (const uint8_t *)key, key_length);
- btc_config_save();
+
+ int ret = btc_config_set_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (const uint8_t *)key, key_length);
+ _btc_storage_save();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
+bt_status_t btc_storage_add_ble_local_key(char *key,
+ uint8_t key_type,
+ uint8_t key_length)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_add_ble_local_key(key, key_type, key_length);
+ btc_config_unlock();
+
+ return ret;
+}
+
/*******************************************************************************
**
** Function btc_storage_get_ble_local_key
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_get_ble_local_key(uint8_t key_type,
+static bt_status_t _btc_storage_get_ble_local_key(uint8_t key_type,
char *key_value,
int key_length)
{
const char* name;
switch (key_type) {
case BTC_LE_LOCAL_KEY_IR:
- name = "LE_LOCAL_KEY_IR";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_IR_STR;
break;
case BTC_LE_LOCAL_KEY_IRK:
- name = "LE_LOCAL_KEY_IRK";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_IRK_STR;
break;
case BTC_LE_LOCAL_KEY_DHK:
- name = "LE_LOCAL_KEY_DHK";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_DHK_STR;
break;
case BTC_LE_LOCAL_KEY_ER:
- name = "LE_LOCAL_KEY_ER";
+ name = BTC_BLE_STORAGE_LE_LOCAL_KEY_ER_STR;
break;
default:
return BT_STATUS_FAIL;
}
size_t length = key_length;
- int ret = btc_config_get_bin("Adapter", name, (uint8_t *)key_value, &length);
+
+ int ret = btc_config_get_bin(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, name, (uint8_t *)key_value, &length);
+
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
+bt_status_t btc_storage_get_ble_local_key(uint8_t key_type,
+ char *key_value,
+ int key_length)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_get_ble_local_key(key_type, key_value, key_length);
+ btc_config_unlock();
+
+ return ret;
+}
+
/*******************************************************************************
**
** Function btc_storage_remove_ble_local_keys
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_remove_ble_local_keys(void)
+static bt_status_t _btc_storage_remove_ble_local_keys(void)
{
int ret = 1;
- if (btc_config_exist("Adapter", "LE_LOCAL_KEY_IR")) {
- ret &= btc_config_remove("Adapter", "LE_LOCAL_KEY_IR");
+
+ if (btc_config_exist(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_IR_STR)) {
+ ret &= btc_config_remove(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_IR_STR);
+ }
+ if (btc_config_exist(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_IRK_STR)) {
+ ret &= btc_config_remove(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_IRK_STR);
+ }
+ if (btc_config_exist(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_DHK_STR)) {
+ ret &= btc_config_remove(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_DHK_STR);
+ }
+ if (btc_config_exist(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_ER_STR)) {
+ ret &= btc_config_remove(BTC_BLE_STORAGE_LOCAL_ADAPTER_STR, BTC_BLE_STORAGE_LE_LOCAL_KEY_ER_STR);
+ }
+ _btc_storage_save();
+
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+bt_status_t btc_storage_remove_ble_local_keys(void)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_remove_ble_local_keys();
+ btc_config_unlock();
+
+ return ret;
+}
+
+bool _btc_storage_compare_address_key_value(bt_bdaddr_t *remote_bd_addr,
+ uint8_t key_type, void *key_value, int key_length)
+{
+ bdstr_t bdstr;
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+ char *key_type_str;
+ switch (key_type) {
+ case BTM_LE_KEY_PENC:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_PENC_STR;
+ break;
+ case BTM_LE_KEY_PID:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_PID_STR;
+ break;
+ case BTM_LE_KEY_PCSRK:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_PCSRK_STR;
+ break;
+ case BTM_LE_KEY_LENC:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_LENC_STR;
+ break;
+ case BTM_LE_KEY_LCSRK:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_LCSRK_STR;
+ break;
+ case BTM_LE_KEY_LID:
+ key_type_str = BTC_BLE_STORAGE_LE_KEY_LID_STR;
+ default:
+ return false;
+ }
+
+ return btc_compare_address_key_value(bdstr, key_type_str, key_value, key_length);
+}
+
+bool btc_storage_compare_address_key_value(bt_bdaddr_t *remote_bd_addr,
+ uint8_t key_type, void *key_value, int key_length)
+{
+ bool ret;
+
+ btc_config_lock();
+ ret = _btc_storage_compare_address_key_value(remote_bd_addr, key_type, key_value, key_length);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static bt_status_t _btc_storage_set_ble_dev_type(bt_bdaddr_t *bd_addr, bool flush)
+{
+ bool ret = 1;
+ bdstr_t bdstr;
+ uint32_t dev_type = 0;
+
+ bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr));
+
+ btc_config_get_int(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&dev_type);
+ ret = btc_config_set_int(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BLE|dev_type);
+ if (ret == false) {
+ return BT_STATUS_FAIL;
+ }
+
+ if (flush) {
+ _btc_storage_save();
+ }
+
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t btc_storage_set_ble_dev_type(bt_bdaddr_t *bd_addr, bool flush)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_set_ble_dev_type(bd_addr, flush);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static bool _btc_storage_get_ble_dev_type(bt_bdaddr_t *bd_addr)
+{
+ bool ret = 1;
+ bdstr_t bdstr;
+ uint32_t dev_type = 0;
+
+ bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr));
+
+ BTIF_TRACE_DEBUG(" %s in bd addr:%s",__FUNCTION__, bdstr);
+
+ ret = btc_config_get_int(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&dev_type);
+ if (ret == false) {
+ return false;
}
- if (btc_config_exist("Adapter", "LE_LOCAL_KEY_IRK")) {
- ret &= btc_config_remove("Adapter", "LE_LOCAL_KEY_IRK");
+
+ return (dev_type & BT_DEVICE_TYPE_BLE);
+}
+
+bool btc_storage_get_ble_dev_type(bt_bdaddr_t *bd_addr)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_get_ble_dev_type(bd_addr);
+ btc_config_unlock();
+
+ return ret;
+}
+
+
+static bt_status_t _btc_storage_remove_ble_dev_type(bt_bdaddr_t *remote_bd_addr, bool flush)
+{
+ bool ret = true;
+ bdstr_t bdstr;
+ uint32_t dev_type = 0;
+
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+
+ BTIF_TRACE_DEBUG(" %s in bd addr:%s",__FUNCTION__, bdstr);
+
+ ret = btc_config_get_int(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&dev_type);
+ if (ret == false) {
+ //cannot find the key, just return SUCCESS, indicate already removed
+ return BT_STATUS_SUCCESS;
}
- if (btc_config_exist("Adapter", "LE_LOCAL_KEY_DHK")) {
- ret &= btc_config_remove("Adapter", "LE_LOCAL_KEY_DHK");
+
+ if (dev_type == BT_DEVICE_TYPE_DUMO) {
+ ret = btc_config_set_int(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR, BT_DEVICE_TYPE_BREDR);
+ } else if (dev_type == BT_DEVICE_TYPE_BLE) {
+ ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_DEV_TYPE_STR);
}
- if (btc_config_exist("Adapter", "LE_LOCAL_KEY_ER")) {
- ret &= btc_config_remove("Adapter", "LE_LOCAL_KEY_ER");
+
+ if (ret == false) {
+ return BT_STATUS_FAIL;
}
- btc_config_save();
+
+ if (flush) {
+ _btc_storage_save();
+ }
+
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t btc_storage_remove_ble_dev_type(bt_bdaddr_t *remote_bd_addr, bool flush)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_remove_ble_dev_type(remote_bd_addr, flush);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static bt_status_t _btc_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr, uint8_t addr_type, bool flush)
+{
+ int ret;
+ bdstr_t bdstr;
+
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
+ ret = btc_config_set_int(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR, (int)addr_type);
+ if (ret == false) {
+ return BT_STATUS_FAIL;
+ }
+
+ if (flush) {
+ _btc_storage_save();
+ }
+
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t btc_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr, uint8_t addr_type, bool flush)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_set_remote_addr_type(remote_bd_addr, addr_type, flush);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static bt_status_t _btc_storage_remove_remote_addr_type(bt_bdaddr_t *remote_bd_addr, bool flush)
+{
+ bool ret = true;
+ bdstr_t bdstr;
+ uint32_t dev_type = 0;
+
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+
+ ret = btc_config_get_int(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR, (int *)&dev_type);
+ if (ret == false) {
+ //cannot find the key, just return SUCCESS, indicate already removed
+ return BT_STATUS_SUCCESS;
+ }
+
+ ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR);
+ if (ret == false) {
+ return BT_STATUS_FAIL;
+ }
+
+ if (flush) {
+ _btc_storage_save();
+ }
+
+ return BT_STATUS_SUCCESS;
+}
+
+bt_status_t btc_storage_remove_remote_addr_type(bt_bdaddr_t *remote_bd_addr, bool flush)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_remove_remote_addr_type(remote_bd_addr, flush);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static bt_status_t _btc_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ int*addr_type)
+{
+ bdstr_t bdstr;
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+ int ret = btc_config_get_int(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR, addr_type);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
+bt_status_t btc_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ int*addr_type)
+{
+ bt_status_t ret;
+
+ btc_config_lock();
+ ret = _btc_storage_get_remote_addr_type(remote_bd_addr, addr_type);
+ btc_config_unlock();
+
+ return ret;
+}
+
+static void _btc_read_le_key(const uint8_t key_type, const size_t key_len, bt_bdaddr_t bd_addr,
+ const uint8_t addr_type, const bool add_key, bool *device_added, bool *key_found)
+{
+ assert(device_added);
+ assert(key_found);
+
+ char buffer[100];
+ memset(buffer, 0, sizeof(buffer));
+
+ bt_status_t ret = _btc_storage_get_ble_bonding_key(&bd_addr, key_type, buffer, key_len);
+
+ if (ret == BT_STATUS_SUCCESS) {
+ if (add_key) {
+ BD_ADDR bta_bd_addr;
+ bdcpy(bta_bd_addr, bd_addr.address);
+
+ if (!*device_added) {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ *device_added = true;
+ }
+
+ char bd_str[20] = {0};
+ LOG_DEBUG("%s() Adding key type %d for %s", __func__,
+ key_type, bdaddr_to_string(&bd_addr, bd_str, sizeof(bd_str)));
+ BTA_DmAddBleKey(bta_bd_addr, (tBTA_LE_KEY_VALUE *)buffer, key_type);
+ }
-bt_status_t btc_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add,
- btc_bonded_devices_t *p_bonded_devices)
+ *key_found = true;
+ }
+}
+static bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add)
{
- int device_type;
+ uint32_t device_type;
int addr_type;
bt_bdaddr_t bd_addr;
BD_ADDR bta_bd_addr;
bool device_added = false;
bool key_found = false;
- if (!btc_config_get_int(remote_bd_addr, BTC_LE_DEV_TYPE, &device_type)) {
+ if (!btc_config_get_int(remote_bd_addr, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type)) {
LOG_ERROR("%s, device_type = %x", __func__, device_type);
return BT_STATUS_FAIL;
}
string_to_bdaddr(remote_bd_addr, &bd_addr);
bdcpy(bta_bd_addr, bd_addr.address);
- if (btc_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS) {
+ if (_btc_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS) {
addr_type = BLE_ADDR_PUBLIC;
- btc_storage_set_remote_addr_type(&bd_addr, BLE_ADDR_PUBLIC);
+ _btc_storage_set_remote_addr_type(&bd_addr, BLE_ADDR_PUBLIC, true);
}
- btc_read_le_key(BTM_LE_KEY_PENC, sizeof(tBTM_LE_PENC_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_PENC, sizeof(tBTM_LE_PENC_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- btc_read_le_key(BTM_LE_KEY_PID, sizeof(tBTM_LE_PID_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_PID, sizeof(tBTM_LE_PID_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- btc_read_le_key(BTM_LE_KEY_LID, sizeof(tBTM_LE_PID_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_LID, sizeof(tBTM_LE_PID_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- btc_read_le_key(BTM_LE_KEY_PCSRK, sizeof(tBTM_LE_PCSRK_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_PCSRK, sizeof(tBTM_LE_PCSRK_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- btc_read_le_key(BTM_LE_KEY_LENC, sizeof(tBTM_LE_LENC_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_LENC, sizeof(tBTM_LE_LENC_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- btc_read_le_key(BTM_LE_KEY_LCSRK, sizeof(tBTM_LE_LCSRK_KEYS),
+ _btc_read_le_key(BTM_LE_KEY_LCSRK, sizeof(tBTM_LE_LCSRK_KEYS),
bd_addr, addr_type, add, &device_added, &key_found);
- // Fill in the bonded devices
- if (device_added)
- {
- memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++],
- &bd_addr, sizeof(bt_bdaddr_t));
- }
-
if (key_found) {
return BT_STATUS_SUCCESS;
}
return BT_STATUS_FAIL;
}
-bt_status_t btc_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
- uint8_t addr_type)
+static bt_status_t btc_storage_in_fetch_bonded_ble_devices(int add)
{
- bdstr_t bdstr;
- bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bt_bdaddr_t));
- int ret = btc_config_set_int(bdstr, "AddrType", (int)addr_type);
- btc_config_save();
- return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+ bt_status_t status = BT_STATUS_FAIL;
+ uint32_t device_type = 0;
+
+ btc_config_lock();
+ for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
+ iter = btc_config_section_next(iter)) {
+ const char *name = btc_config_section_name(iter);
+
+ if (!string_is_bdaddr(name) ||
+ !btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
+ ((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) {
+ continue;
+ }
+ LOG_DEBUG("%s, name = %s", __func__, name);
+ if (_btc_storage_in_fetch_bonded_ble_device(name, add) != BT_STATUS_SUCCESS) {
+ LOG_DEBUG("Remote device:%s, no link key or ble key found", name);
+ } else {
+ status = BT_STATUS_SUCCESS;
+ }
+ }
+ btc_config_unlock();
+
+ return status;
}
/*******************************************************************************
**
-** Function btc_storage_get_remote_addr_type
+** Function btc_storage_load_bonded_devices
**
-** Description btc storage API - Fetches the remote addr type
+** Description btc storage API - Loads all the bonded devices from NVRAM
+** and adds to the BTA.
+** Additionally, this API also invokes the adaper_properties_cb
+** and remote_device_properties_cb for each of the bonded devices.
**
-** Returns BT_STATUS_SUCCESS if the fetch was successful,
-** BT_STATUS_FAIL otherwise
+** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
- int*addr_type)
+bt_status_t btc_storage_load_bonded_ble_devices(void)
{
- bdstr_t bdstr;
- bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
- int ret = btc_config_get_int(bdstr, "AddrType", addr_type);
- return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+ bt_status_t status;
+ status = btc_storage_in_fetch_bonded_ble_devices(1);
+ LOG_DEBUG("Storage load rslt %d\n", status);
+ return status;
}
-int btc_storage_get_num_ble_bond_devices(void)
+bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev, int dev_num)
{
- int num_dev = 0;
- int device_type = 0;
+ bt_bdaddr_t bd_addr;
+ uint32_t device_type = 0;
+ char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0};
+
+ btc_config_lock();
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
iter = btc_config_section_next(iter)) {
+
+ if (dev_num-- <= 0) {
+ break;
+ }
+
const char *name = btc_config_section_name(iter);
- if (!string_is_bdaddr(name) &&
- !btc_config_get_int(name, BTC_LE_DEV_TYPE, &device_type) &&
- device_type != BT_DEVICE_TYPE_BLE) {
+
+ if (!string_is_bdaddr(name) ||
+ !btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
+ !(device_type & BT_DEVICE_TYPE_BLE)) {
continue;
}
- num_dev++;
+ string_to_bdaddr(name, &bd_addr);
+ memcpy(bond_dev->bd_addr, bd_addr.address, sizeof(bt_bdaddr_t));
+ //resolve the peer device long term key
+ if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PENC, buffer, sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) {
+ bond_dev->bond_key.key_mask |= ESP_BLE_ENC_KEY_MASK;
+ memcpy(&bond_dev->bond_key.penc_key, buffer, sizeof(tBTM_LE_PENC_KEYS));
+ }
+ //resolve the peer device csrk
+ if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PCSRK, buffer, sizeof(tBTM_LE_PCSRK_KEYS)) == BT_STATUS_SUCCESS) {
+ bond_dev->bond_key.key_mask |= ESP_BLE_CSR_KEY_MASK;
+ memcpy(&bond_dev->bond_key.pcsrk_key, buffer, sizeof(tBTM_LE_PCSRK_KEYS));
+ }
+ //resolve the peer device irk
+ if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PID, buffer, sizeof(tBTM_LE_PID_KEYS)) == BT_STATUS_SUCCESS) {
+ bond_dev->bond_key.key_mask |= ESP_BLE_ID_KEY_MASK;
+ memcpy(&bond_dev->bond_key.pid_key, buffer, sizeof(tBTM_LE_PID_KEYS));
+ }
+ //serch for the next bond device
+ bond_dev++;
}
+ btc_config_unlock();
- return num_dev;
+ return BT_STATUS_SUCCESS;
}
-void btc_dm_load_ble_local_keys(void)
+int btc_storage_get_num_ble_bond_devices(void)
{
- memset(&ble_local_key_cb, 0, sizeof(btc_dm_local_key_cb_t));
-
- if (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0],
- BT_OCTET16_LEN)== BT_STATUS_SUCCESS) {
- ble_local_key_cb.is_er_rcvd = TRUE;
- LOG_DEBUG("%s BLE ER key loaded",__func__ );
- }
+ int num_dev = 0;
+ uint32_t device_type = 0;
- if ((btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0],
- BT_OCTET16_LEN)== BT_STATUS_SUCCESS )&&
- (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IRK, (char*)&ble_local_key_cb.id_keys.irk[0],
- BT_OCTET16_LEN)== BT_STATUS_SUCCESS)&&
- (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0],
- BT_OCTET16_LEN)== BT_STATUS_SUCCESS)) {
- ble_local_key_cb.is_id_keys_rcvd = TRUE;
- LOG_DEBUG("%s BLE ID keys loaded", __func__);
- }
+ btc_config_lock();
+ for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
+ iter = btc_config_section_next(iter)) {
+ const char *name = btc_config_section_name(iter);
+ if (!string_is_bdaddr(name) ||
+ !btc_config_get_int(name, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type) ||
+ !(device_type & BT_DEVICE_TYPE_BLE)) {
+ continue;
+ }
-}
-void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
- tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
-{
- if (ble_local_key_cb.is_er_rcvd ) {
- memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16));
- *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER;
+ num_dev++;
}
+ btc_config_unlock();
- if (ble_local_key_cb.is_id_keys_rcvd) {
- memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0], sizeof(BT_OCTET16));
- memcpy(&p_id_keys->irk[0], &ble_local_key_cb.id_keys.irk[0], sizeof(BT_OCTET16));
- memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16));
- *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID;
- }
- LOG_DEBUG("%s *p_key_mask=0x%02x",__func__, *p_key_mask);
+ return num_dev;
}
-
#endif ///SMP_INCLUDED == TRUE
static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000;
static void btc_key_value_to_string(uint8_t *key_vaule, char *value_str, int key_length);
-
-// TODO(zachoverflow): Move these two functions out, because they are too specific for this file
-// {grumpy-cat/no, monty-python/you-make-me-sad}
-bool btc_get_device_type(const BD_ADDR bd_addr, int *p_device_type)
-{
- if (p_device_type == NULL) {
- return FALSE;
- }
-
- bt_bdaddr_t bda;
- bdcpy(bda.address, bd_addr);
-
- bdstr_t bd_addr_str;
- bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
-
- if (!btc_config_get_int(bd_addr_str, BTC_LE_DEV_TYPE, p_device_type)) {
- return FALSE;
- }
-
- LOG_DEBUG("%s: Device [%s] type %d\n", __FUNCTION__, bd_addr_str, *p_device_type);
- return TRUE;
-}
-
-bool btc_get_address_type(const BD_ADDR bd_addr, int *p_addr_type)
-{
- if (p_addr_type == NULL) {
- return FALSE;
- }
-
- bt_bdaddr_t bda;
- bdcpy(bda.address, bd_addr);
-
- bdstr_t bd_addr_str;
- bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
-
- if (!btc_config_get_int(bd_addr_str, "AddrType", p_addr_type)) {
- return FALSE;
- }
-
- LOG_DEBUG("%s: Device [%s] address type %d\n", __FUNCTION__, bd_addr_str, *p_addr_type);
- return TRUE;
-}
-
static osi_mutex_t lock; // protects operations on |config|.
static config_t *config;
return false;
}
btc_key_value_to_string((uint8_t *)key_value, value_str, key_length);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
if ((status = config_has_key_in_section(config, key_type, value_str)) == true) {
config_remove_section(config, section);
}
- osi_mutex_unlock(&lock);
return status;
}
assert(config != NULL);
assert(section != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
- bool ret = config_has_section(config, section);
- osi_mutex_unlock(&lock);
-
- return ret;
+ return config_has_section(config, section);
}
bool btc_config_exist(const char *section, const char *key)
assert(section != NULL);
assert(key != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
- bool ret = config_has_key(config, section, key);
- osi_mutex_unlock(&lock);
-
- return ret;
+ return config_has_key(config, section, key);
}
bool btc_config_get_int(const char *section, const char *key, int *value)
assert(key != NULL);
assert(value != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
bool ret = config_has_key(config, section, key);
if (ret) {
*value = config_get_int(config, section, key, *value);
}
- osi_mutex_unlock(&lock);
return ret;
}
assert(section != NULL);
assert(key != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
config_set_int(config, section, key, value);
- osi_mutex_unlock(&lock);
return true;
}
assert(value != NULL);
assert(size_bytes != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
const char *stored_value = config_get_string(config, section, key, NULL);
- osi_mutex_unlock(&lock);
if (!stored_value) {
return false;
assert(key != NULL);
assert(value != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
config_set_string(config, section, key, value, false);
- osi_mutex_unlock(&lock);
return true;
}
assert(value != NULL);
assert(length != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
const char *value_str = config_get_string(config, section, key, NULL);
- osi_mutex_unlock(&lock);
if (!value_str) {
return false;
assert(section != NULL);
assert(key != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
const char *value_str = config_get_string(config, section, key, NULL);
- osi_mutex_unlock(&lock);
if (!value_str) {
return 0;
str[(i * 2) + 1] = lookup[value[i] & 0x0F];
}
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
config_set_string(config, section, key, str, false);
- osi_mutex_unlock(&lock);
osi_free(str);
return true;
return config_section_name((const config_section_node_t *)section);
}
+
+
bool btc_config_remove(const char *section, const char *key)
{
assert(config != NULL);
assert(section != NULL);
assert(key != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
- bool ret = config_remove_key(config, section, key);
- osi_mutex_unlock(&lock);
-
- return ret;
+ return config_remove_key(config, section, key);
}
bool btc_config_remove_section(const char *section)
assert(config != NULL);
assert(section != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
- bool ret = config_remove_section(config, section);
- osi_mutex_unlock(&lock);
-
- return ret;
-}
-
-void btc_config_save(void)
-{
- assert(config != NULL);
- // Garbage collection process: the config file accumulates
- // cached information about remote devices during regular
- // inquiry scans. We remove some of these junk entries
- // so the file doesn't grow indefinitely. We have to take care
- // to make sure we don't remove information about bonded
- // devices (hence the check for link keys).
- static const size_t CACHE_MAX = 256;
- const char *keys[CACHE_MAX];
- size_t num_keys = 0;
- size_t total_candidates = 0;
-
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
- for (const config_section_node_t *snode = config_section_begin(config); snode != config_section_end(config); snode = config_section_next(snode)) {
- const char *section = config_section_name(snode);
- if (!string_is_bdaddr(section)) {
- continue;
- }
-
- if (config_has_key(config, section, "LinkKey") ||
- config_has_key(config, section, "LE_KEY_PENC") ||
- config_has_key(config, section, "LE_KEY_PID") ||
- config_has_key(config, section, "LE_KEY_PCSRK") ||
- config_has_key(config, section, "LE_KEY_LENC") ||
- config_has_key(config, section, "LE_KEY_LCSRK")) {
- continue;
- }
-
- if (num_keys < CACHE_MAX) {
- keys[num_keys++] = section;
- }
-
- ++total_candidates;
- }
-
- if (total_candidates > CACHE_MAX * 2)
- while (num_keys > 0) {
- config_remove_section(config, keys[--num_keys]);
- }
- config_save(config, CONFIG_FILE_PATH);
- osi_mutex_unlock(&lock);
+ return config_remove_section(config, section);
}
void btc_config_flush(void)
{
assert(config != NULL);
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
+
config_save(config, CONFIG_FILE_PATH);
- osi_mutex_unlock(&lock);
}
int btc_config_clear(void)
{
assert(config != NULL);
-
- osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
config_free(config);
config = config_new_empty();
if (config == NULL) {
- osi_mutex_unlock(&lock);
return false;
}
int ret = config_save(config, CONFIG_FILE_PATH);
- osi_mutex_unlock(&lock);
return ret;
}
+void btc_config_lock(void)
+{
+ osi_mutex_lock(&lock, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+void btc_config_unlock(void)
+{
+ osi_mutex_unlock(&lock);
+}
+
** Static variables
******************************************************************************/
static tBTA_SERVICE_MASK btc_enabled_services = 0;
+#if (SMP_INCLUDED == TRUE)
+static btc_dm_pairing_cb_t pairing_cb;
+static btc_dm_local_key_cb_t ble_local_key_cb;
+#endif
+
/******************************************************************************
** Static functions
******************************************************************************/
}
#if (SMP_INCLUDED == TRUE)
+void btc_dm_load_ble_local_keys(void)
+{
+ memset(&ble_local_key_cb, 0, sizeof(btc_dm_local_key_cb_t));
+
+ if (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS) {
+ ble_local_key_cb.is_er_rcvd = TRUE;
+ LOG_DEBUG("%s BLE ER key loaded",__func__ );
+ }
+
+ if ((btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS )&&
+ (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IRK, (char*)&ble_local_key_cb.id_keys.irk[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS)&&
+ (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS)) {
+ ble_local_key_cb.is_id_keys_rcvd = TRUE;
+ LOG_DEBUG("%s BLE ID keys loaded", __func__);
+ }
+
+}
+void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+ tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
+{
+ if (ble_local_key_cb.is_er_rcvd ) {
+ memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16));
+ *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER;
+ }
+
+ if (ble_local_key_cb.is_id_keys_rcvd) {
+ memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0], sizeof(BT_OCTET16));
+ memcpy(&p_id_keys->irk[0], &ble_local_key_cb.id_keys.irk[0], sizeof(BT_OCTET16));
+ memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16));
+ *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID;
+ }
+ LOG_DEBUG("%s *p_key_mask=0x%02x",__func__, *p_key_mask);
+}
+
+
+static void btc_dm_remove_ble_bonding_keys(void)
+{
+ bt_bdaddr_t bd_addr;
+ LOG_DEBUG("%s\n",__func__);
+
+ bdcpy(bd_addr.address, pairing_cb.bd_addr);
+
+ btc_storage_remove_remote_addr_type(&bd_addr, false);
+ btc_storage_remove_ble_dev_type(&bd_addr, false);
+ btc_storage_remove_ble_bonding_keys(&bd_addr);
+}
+
+static void btc_dm_save_ble_bonding_keys(void)
+{
+ bt_bdaddr_t bd_addr;
+
+ bdcpy(bd_addr.address, pairing_cb.bd_addr);
+
+ btc_storage_set_ble_dev_type(&bd_addr, false);
+ LOG_DEBUG("%s, penc = %d, pid = %d", __func__, pairing_cb.ble.is_penc_key_rcvd, pairing_cb.ble.is_pid_key_rcvd);
+ if (pairing_cb.ble.is_penc_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.penc_key,
+ BTM_LE_KEY_PENC,
+ sizeof(tBTM_LE_PENC_KEYS));
+ }
+
+ if (pairing_cb.ble.is_pid_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.pid_key,
+ BTM_LE_KEY_PID,
+ sizeof(tBTM_LE_PID_KEYS));
+ }
+
+
+ if (pairing_cb.ble.is_pcsrk_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.pcsrk_key,
+ BTM_LE_KEY_PCSRK,
+ sizeof(tBTM_LE_PCSRK_KEYS));
+ }
+
+
+ if (pairing_cb.ble.is_lenc_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.lenc_key,
+ BTM_LE_KEY_LENC,
+ sizeof(tBTM_LE_LENC_KEYS));
+ }
+
+ if (pairing_cb.ble.is_lcsrk_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.lcsrk_key,
+ BTM_LE_KEY_LCSRK,
+ sizeof(tBTM_LE_LCSRK_KEYS));
+ }
+
+ if (pairing_cb.ble.is_lidk_key_rcvd) {
+ btc_storage_add_ble_bonding_key(&bd_addr,
+ NULL,
+ BTM_LE_KEY_LID,
+ 0);
+ }
+}
+
static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
{
/* Save link key, if not temporary */
(pairing_cb.bd_addr[0] << 24) + (pairing_cb.bd_addr[1] << 16) + (pairing_cb.bd_addr[2] << 8) + pairing_cb.bd_addr[3],
(pairing_cb.bd_addr[4] << 8) + pairing_cb.bd_addr[5]);
if (btc_storage_get_remote_addr_type(&bdaddr, &addr_type) != BT_STATUS_SUCCESS) {
- btc_storage_set_remote_addr_type(&bdaddr, p_auth_cmpl->addr_type);
+ btc_storage_set_remote_addr_type(&bdaddr, p_auth_cmpl->addr_type, true);
}
/* check the irk has been save in the flash or not, if the irk has already save, means that the peer device has bonding
before. */
btc_storage_compare_address_key_value(&bdaddr, BTM_LE_KEY_PID,
(void *)&pairing_cb.ble.pid_key, sizeof(tBTM_LE_PID_KEYS));
}
- btc_save_ble_bonding_keys();
+ btc_dm_save_ble_bonding_keys();
} else {
/*Map the HCI fail reason to bt status */
switch (p_auth_cmpl->fail_reason) {
memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR));
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
//remove the bonded key in the config and nvs flash.
- //btc_storage_remove_ble_bonding_keys(&bd_addr);
+ btc_storage_remove_ble_dev_type(&bd_addr, false);
+ btc_storage_remove_remote_addr_type(&bd_addr, false);
+ btc_storage_remove_ble_bonding_keys(&bd_addr);
ble_msg.act = ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT;
param.remove_bond_dev_cmpl.status = (p_data->link_down.status == HCI_SUCCESS) ? ESP_BT_STATUS_SUCCESS : ESP_BT_STATUS_FAIL;
memcpy(param.remove_bond_dev_cmpl.bd_addr, p_data->link_down.bd_addr, sizeof(BD_ADDR));
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
LOG_DEBUG("add to storage: Remote device:%s\n", bdstr);
- int ret = btc_config_set_int(bdstr, "LinkKeyType", (int)key_type);
- ret &= btc_config_set_int(bdstr, "PinLength", (int)pin_length);
- ret &= btc_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY));
+ btc_config_lock();
+ int ret = btc_config_set_int(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR, (int)key_type);
+ ret &= btc_config_set_int(bdstr, BTC_STORAGE_PIN_LENGTH_STR, (int)pin_length);
+ ret &= btc_config_set_bin(bdstr, BTC_STORAGE_LINK_KEY_STR, link_key, sizeof(LINK_KEY));
/* write bonded info immediately */
btc_config_flush();
+ btc_config_unlock();
+
LOG_DEBUG("Storage add rslt %d\n", ret);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
{
BOOLEAN bt_linkkey_file_found = FALSE;
+ btc_config_lock();
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); iter = btc_config_section_next(iter)) {
const char *name = btc_config_section_name(iter);
if (!string_is_bdaddr(name)) {
LOG_DEBUG("Remote device:%s\n", name);
LINK_KEY link_key;
size_t size = sizeof(link_key);
- if (btc_config_get_bin(name, "LinkKey", link_key, &size)) {
+ if (btc_config_get_bin(name, BTC_STORAGE_LINK_KEY_STR, link_key, &size)) {
int linkkey_type;
- if (btc_config_get_int(name, "LinkKeyType", &linkkey_type)) {
- //int pin_len;
- //btc_config_get_int(name, "PinLength", &pin_len))
+ if (btc_config_get_int(name, BTC_STORAGE_LINK_KEY_TYPE_STR, &linkkey_type)) {
bt_bdaddr_t bd_addr;
string_to_bdaddr(name, &bd_addr);
if (add) {
DEV_CLASS dev_class = {0, 0, 0};
int cod;
int pin_length = 0;
- if (btc_config_get_int(name, "DevClass", &cod)) {
+ if (btc_config_get_int(name, BTC_STORAGE_DEV_CLASS_STR, &cod)) {
uint2devclass((UINT32)cod, dev_class);
}
- btc_config_get_int(name, "PinLength", &pin_length);
+ btc_config_get_int(name, BTC_STORAGE_PIN_LENGTH_STR, &pin_length);
#if (SMP_INCLUDED == TRUE)
BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0,
(UINT8)linkkey_type, 0, pin_length);
LOG_DEBUG("Remote device:%s, no link key\n", name);
}
}
+ btc_config_unlock();
+
return BT_STATUS_SUCCESS;
}
{
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+ int ret = 1;
LOG_DEBUG("Add to storage: Remote device:%s\n", bdstr);
- int ret = 1;
- if (btc_config_exist(bdstr, "LinkKeyType")) {
- ret &= btc_config_remove(bdstr, "LinkKeyType");
+ btc_config_lock();
+ if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR);
}
- if (btc_config_exist(bdstr, "PinLength")) {
- ret &= btc_config_remove(bdstr, "PinLength");
+ if (btc_config_exist(bdstr, BTC_STORAGE_PIN_LENGTH_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_STORAGE_PIN_LENGTH_STR);
}
- if (btc_config_exist(bdstr, "LinkKey")) {
- ret &= btc_config_remove(bdstr, "LinkKey");
+ if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_STR)) {
+ ret &= btc_config_remove(bdstr, BTC_STORAGE_LINK_KEY_STR);
}
/* write bonded info immediately */
btc_config_flush();
+ btc_config_unlock();
+
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
#define BTC_LE_LOCAL_KEY_DHK (1<<2)
#define BTC_LE_LOCAL_KEY_ER (1<<3)
+#define BTC_BLE_STORAGE_DEV_TYPE_STR "DevType"
+#define BTC_BLE_STORAGE_ADDR_TYPE_STR "AddrType"
+#define BTC_BLE_STORAGE_LINK_KEY_STR "LinkKey"
+#define BTC_BLE_STORAGE_LE_KEY_PENC_STR "LE_KEY_PENC"
+#define BTC_BLE_STORAGE_LE_KEY_PID_STR "LE_KEY_PID"
+#define BTC_BLE_STORAGE_LE_KEY_PCSRK_STR "LE_KEY_PCSRK"
+#define BTC_BLE_STORAGE_LE_KEY_LENC_STR "LE_KEY_LENC"
+#define BTC_BLE_STORAGE_LE_KEY_LID_STR "LE_KEY_LID"
+#define BTC_BLE_STORAGE_LE_KEY_LCSRK_STR "LE_KEY_LCSRK"
+
+#define BTC_BLE_STORAGE_LOCAL_ADAPTER_STR "Adapter"
+#define BTC_BLE_STORAGE_LE_LOCAL_KEY_IR_STR "LE_LOCAL_KEY_IR"
+#define BTC_BLE_STORAGE_LE_LOCAL_KEY_IRK_STR "LE_LOCAL_KEY_IRK"
+#define BTC_BLE_STORAGE_LE_LOCAL_KEY_DHK_STR "LE_LOCAL_KEY_DHK"
+#define BTC_BLE_STORAGE_LE_LOCAL_KEY_ER_STR "LE_LOCAL_KEY_ER"
+
/************************************************************************************
** Local type definitions
************************************************************************************/
-typedef struct
-{
- uint32_t num_devices;
- bt_bdaddr_t devices[BTM_SEC_MAX_DEVICE_RECORDS];
-} btc_bonded_devices_t;
-
-typedef struct
-{
- bool is_penc_key_rcvd;
- tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */
- bool is_pcsrk_key_rcvd;
- tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
- bool is_pid_key_rcvd;
- tBTM_LE_PID_KEYS pid_key; /* peer device ID key */
- bool is_lenc_key_rcvd;
- tBTM_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
- bool is_lcsrk_key_rcvd;
- tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
- bool is_lidk_key_rcvd; /* local identity key received */
-} btc_dm_ble_cb_t;
-
-typedef struct
-{
- bt_bdaddr_t static_bdaddr;
- BD_ADDR bd_addr;
- btc_dm_ble_cb_t ble;
-} btc_dm_pairing_cb_t;
-
-typedef struct
-{
- uint8_t ir[BT_OCTET16_LEN];
- uint8_t irk[BT_OCTET16_LEN];
- uint8_t dhk[BT_OCTET16_LEN];
-}btc_dm_local_key_id_t;
-
-typedef struct
-{
- bool is_er_rcvd;
- uint8_t er[BT_OCTET16_LEN];
- bool is_id_keys_rcvd;
- btc_dm_local_key_id_t id_keys; /* ID kyes */
-}btc_dm_local_key_cb_t;
-
typedef struct
{
BT_OCTET16 sp_c;
} btc_dm_oob_cb_t;
-extern btc_dm_pairing_cb_t pairing_cb;
-extern btc_dm_local_key_cb_t ble_local_key_cb;
-extern btc_bonded_devices_t bonded_devices;
+void btc_storage_save(void);
-bt_status_t btc_storage_load_bonded_ble_devices(void);
-
-bt_status_t btc_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev);
+bt_status_t btc_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr, char *key, uint8_t key_type, uint8_t key_length);
-bt_status_t btc_in_fetch_bonded_ble_devices(int add);
+bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr, uint8_t key_type, char *key_value, int key_length);
-void btc_dm_remove_ble_bonding_keys(void);
+bt_status_t btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr);
-bt_status_t btc_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr,
- char *key,
- uint8_t key_type,
- uint8_t key_length);
+bool btc_storage_compare_address_key_value(bt_bdaddr_t *remote_bd_addr, uint8_t key_type, void *key_value, int key_length);
-bool btc_compare_le_key_value(const uint8_t key_type, const size_t key_len, const tBTA_LE_KEY_VALUE *key_vaule,
- bt_bdaddr_t bd_addr);
+bt_status_t btc_storage_add_ble_local_key(char *key, uint8_t key_type, uint8_t key_length);
-void btc_save_ble_bonding_keys(void);
+bt_status_t btc_storage_remove_ble_local_keys(void);
-bt_status_t btc_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add,
- btc_bonded_devices_t *p_bonded_devices);
+bt_status_t btc_storage_get_ble_local_key(uint8_t key_type, char *key_value, int key_len);
-bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
- uint8_t key_type,
- char *key_value,
- int key_length);
+bt_status_t btc_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr, int *addr_type);
-bool btc_storage_compare_address_key_value(bt_bdaddr_t *remote_bd_addr,
- uint8_t key_type, void *key_value, int key_length);
-bt_status_t btc_storage_add_ble_local_key(char *key,
- uint8_t key_type,
- uint8_t key_length);
+bt_status_t btc_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr, uint8_t addr_type, bool flush);
-bt_status_t btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr);
+bt_status_t btc_storage_remove_remote_addr_type(bt_bdaddr_t *remote_bd_addr, bool flush);
-bt_status_t btc_storage_clear_bond_devices(void);
+bt_status_t btc_storage_set_ble_dev_type(bt_bdaddr_t *bd_addr, bool flush);
-bt_status_t btc_storage_remove_ble_local_keys(void);
+bt_status_t btc_storage_remove_ble_dev_type(bt_bdaddr_t *remote_bd_addr, bool flush);
-bt_status_t btc_storage_get_ble_local_key(uint8_t key_type,
- char *key_value,
- int key_len);
+bt_status_t btc_storage_load_bonded_ble_devices(void);
-bt_status_t btc_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
- int *addr_type);
+bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev, int dev_num);
int btc_storage_get_num_ble_bond_devices(void);
-bt_status_t btc_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
- uint8_t addr_type);
-
-void btc_dm_load_ble_local_keys(void);
-
-void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
- tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
#endif ///SMP_INCLUDED == TRUE
-#endif ///__BTC_BLE_STORAGE_H__
\ No newline at end of file
+#endif ///__BTC_BLE_STORAGE_H__
#include "bt_types.h"
-#define BTC_LE_DEV_TYPE "DevType"
-
typedef struct btc_config_section_iter_t btc_config_section_iter_t;
bool btc_config_init(void);
const btc_config_section_iter_t *btc_config_section_next(const btc_config_section_iter_t *section);
const char *btc_config_section_name(const btc_config_section_iter_t *section);
-void btc_config_save(void);
void btc_config_flush(void);
int btc_config_clear(void);
bool btc_compare_address_key_value(const char *section, char *key_type, void *key_value, int key_length);
bool btc_get_device_type(const BD_ADDR bd_addr, int *p_device_type);
+void btc_config_lock(void);
+void btc_config_unlock(void);
+
#endif
tBTA_DM_SEC sec;
} btc_dm_sec_args_t;
+typedef struct
+{
+ bool is_penc_key_rcvd;
+ tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */
+ bool is_pcsrk_key_rcvd;
+ tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
+ bool is_pid_key_rcvd;
+ tBTM_LE_PID_KEYS pid_key; /* peer device ID key */
+ bool is_lenc_key_rcvd;
+ tBTM_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+ bool is_lcsrk_key_rcvd;
+ tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+ bool is_lidk_key_rcvd; /* local identity key received */
+} btc_dm_ble_cb_t;
+
+typedef struct
+{
+ bt_bdaddr_t static_bdaddr;
+ BD_ADDR bd_addr;
+ btc_dm_ble_cb_t ble;
+} btc_dm_pairing_cb_t;
+
+typedef struct
+{
+ uint8_t ir[BT_OCTET16_LEN];
+ uint8_t irk[BT_OCTET16_LEN];
+ uint8_t dhk[BT_OCTET16_LEN];
+} btc_dm_local_key_id_t;
+
+typedef struct
+{
+ bool is_er_rcvd;
+ uint8_t er[BT_OCTET16_LEN];
+ bool is_id_keys_rcvd;
+ btc_dm_local_key_id_t id_keys; /* ID kyes */
+} btc_dm_local_key_cb_t;
+
+
+
// void btc_dm_call_handler(btc_msg_t *msg);
void btc_dm_sec_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *data);
void btc_dm_sec_cb_handler(btc_msg_t *msg);
bt_status_t btc_dm_enable_service(tBTA_SERVICE_ID service_id);
bt_status_t btc_dm_disable_service(tBTA_SERVICE_ID service_id);
+#if (SMP_INCLUDED == TRUE)
+void btc_dm_load_ble_local_keys(void);
+
+void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+ tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+#endif
+
#endif /* __BTC_DM_H__ */
#include "bt_defs.h"
#include "bt_types.h"
+
+#define BTC_STORAGE_DEV_CLASS_STR "DevClass"
+#define BTC_STORAGE_LINK_KEY_STR "LinkKey" /* same as the ble */
+#define BTC_STORAGE_LINK_KEY_TYPE_STR "LinkKeyType"
+#define BTC_STORAGE_PIN_LENGTH_STR "PinLength"
+
/*******************************************************************************
**
** Function btc_storage_add_bonded_device
#include "esp_bt_defs.h"
#include "esp_gap_ble_api.h"
#include "btc_ble_storage.h"
+#include "btc_dm.h"
static tBTA_BLE_ADV_DATA gl_bta_adv_data;
static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data;
}
}
-#if (SMP_INCLUDED)
-static void btc_ble_remove_bond_device(esp_bt_status_t status)
-{
- int ret;
- esp_ble_gap_cb_param_t param;
- btc_msg_t msg;
- param.remove_bond_dev_cmpl.status = status;
- msg.sig = BTC_SIG_API_CB;
- msg.pid = BTC_PID_GAP_BLE;
- msg.act = ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT;
-
- ret = btc_transfer_context(&msg, ¶m,
- sizeof(esp_ble_gap_cb_param_t), NULL);
-
- if (ret != BT_STATUS_SUCCESS) {
- LOG_ERROR("%s btc_transfer_context failed", __func__);
- }
-}
-
-static void btc_ble_clear_bond_device(void)
-{
- int ret;
- esp_ble_gap_cb_param_t param;
- btc_msg_t msg;
- ret = btc_storage_clear_bond_devices();
- param.clear_bond_dev_cmpl.status = ret;
- msg.sig = BTC_SIG_API_CB;
- msg.pid = BTC_PID_GAP_BLE;
- msg.act = ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT;
-
- ret = btc_transfer_context(&msg, ¶m,
- sizeof(esp_ble_gap_cb_param_t), NULL);
-
- if (ret != BT_STATUS_SUCCESS) {
- LOG_ERROR("%s btc_transfer_context failed", __func__);
- }
-
-}
-
-static void btc_ble_get_bond_device_list(void)
-{
- int ret;
- esp_ble_gap_cb_param_t param;
- esp_ble_bond_dev_t *bond_dev;
- btc_msg_t msg;
- int num_dev = btc_storage_get_num_ble_bond_devices();
- bond_dev = (esp_ble_bond_dev_t *)osi_malloc(sizeof(esp_ble_bond_dev_t)*num_dev);
-
- param.get_bond_dev_cmpl.status = btc_get_bonded_ble_devices_list(bond_dev);
- param.get_bond_dev_cmpl.dev_num = num_dev;
- param.get_bond_dev_cmpl.bond_dev = bond_dev;
- msg.sig = BTC_SIG_API_CB;
- msg.pid = BTC_PID_GAP_BLE;
- msg.act = ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT;
-
- ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), btc_gap_ble_cb_deep_copy);
-
- if (ret != BT_STATUS_SUCCESS) {
- LOG_ERROR("%s btc_transfer_context failed", __func__);
- }
- // release the buffer after used.
- osi_free(bond_dev);
-}
-#endif /* #if (SMP_INCLUDED) */
-
static void btc_ble_config_local_privacy(bool privacy_enable, tBTA_SET_LOCAL_PRIVACY_CBACK *set_local_privacy_cback)
{
BTA_DmBleConfigLocalPrivacy(privacy_enable, set_local_privacy_cback);
void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
{
switch (msg->act) {
- case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT: {
- esp_ble_gap_cb_param_t *src = (esp_ble_gap_cb_param_t *)p_src;
- esp_ble_gap_cb_param_t *dst = (esp_ble_gap_cb_param_t *)p_dest;
- uint16_t length = 0;
- if (src->get_bond_dev_cmpl.bond_dev) {
- length = (src->get_bond_dev_cmpl.dev_num)*sizeof(esp_ble_bond_dev_t);
- dst->get_bond_dev_cmpl.bond_dev = (esp_ble_bond_dev_t *)osi_malloc(length);
- if (dst->get_bond_dev_cmpl.bond_dev != NULL) {
- memcpy(dst->get_bond_dev_cmpl.bond_dev, src->get_bond_dev_cmpl.bond_dev, length);
- } else {
- LOG_ERROR("%s %d no mem", __func__, msg->act);
- }
- }
- break;
- }
default:
LOG_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act);
break;
{
LOG_DEBUG("%s", __func__);
switch (msg->act) {
- case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT: {
- esp_ble_bond_dev_t *bond_dev = ((esp_ble_gap_cb_param_t *)msg->arg)->get_bond_dev_cmpl.bond_dev;
- if (bond_dev) {
- osi_free(bond_dev);
- }
- break;
- }
default:
LOG_DEBUG("Unhandled deep free %d", msg->act);
break;
}
case BTC_GAP_BLE_REMOVE_BOND_DEV_EVT: {
BD_ADDR bd_addr;
- bt_bdaddr_t bt_addr;
memcpy(bd_addr, arg->remove_bond_device.bd_addr, sizeof(BD_ADDR));
- memcpy(bt_addr.address, arg->remove_bond_device.bd_addr, sizeof(bt_bdaddr_t));
- LOG_DEBUG("BTC_GAP_BLE_REMOVE_BOND_DEV_EVT");
- if (btc_storage_remove_ble_bonding_keys(&bt_addr) == BT_STATUS_SUCCESS) {
- BTA_DmRemoveDevice(bd_addr);
- } else {
- LOG_ERROR("remove device failed: the address[%x:%x:%x:%x:%x:%x] didn't in the bonding list", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
- btc_ble_remove_bond_device(ESP_BT_STATUS_FAIL);
- }
+ BTA_DmRemoveDevice(bd_addr);
break;
}
- case BTC_GAP_BLE_CLEAR_BOND_DEV_EVT:
- btc_ble_clear_bond_device();
- break;
- case BTC_GAP_BLE_GET_BOND_DEV_EVT:
- btc_ble_get_bond_device_list();
- break;
#endif ///SMP_INCLUDED == TRUE
case BTC_GAP_BLE_DISCONNECT_EVT:
btc_ble_disconnect(arg->disconnect.remote_device);
BTC_GAP_BLE_CONFIRM_REPLY_EVT,
BTC_GAP_BLE_DISCONNECT_EVT,
BTC_GAP_BLE_REMOVE_BOND_DEV_EVT,
- BTC_GAP_BLE_CLEAR_BOND_DEV_EVT,
- BTC_GAP_BLE_GET_BOND_DEV_EVT,
} btc_gap_ble_act_t;
/* btc_ble_gap_args_t */
#include "bta_sys.h"
#include "bta_dm_co.h"
#include "bta_dm_ci.h"
-#include "btc_ble_storage.h"
+#include "btc_dm.h"
#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
#include "bt_utils.h"
#if (BTM_OOB_INCLUDED == TRUE)
#include "alarm.h"
#include "thread.h"
#include "mutex.h"
+#include "fixed_queue.h"
typedef struct {
uint16_t opcode;
#include "bt_types.h"
#include "allocator.h"
-#include "fixed_queue.h"
#include "osi.h"
#include "future.h"
///// LEGACY DEFINITIONS /////
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_CMD_STARTED;
- if (p_inq->adv_mode != BTM_BLE_ADV_DISABLE) {
+ /* start scan, disable duplicate filtering */
+ if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
status = BTM_NO_RESOURCES;
} else {
- /* start scan, disable duplicate filtering */
- if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
- status = BTM_NO_RESOURCES;
+ btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_SCANNING;
+ if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
+ btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
} else {
- btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_SCANNING;
- if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
- btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
- } else {
- btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
- }
+ btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
}
}
+
return status;
}
{
BTM_TRACE_EVENT ("btm_ble_stop_scan ");
- if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_DISABLE) {
- /* Clear the inquiry callback if set */
- btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
- btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_STOP_SCAN;
- /* stop discovery now */
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+ /* Clear the inquiry callback if set */
+ btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
+ btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_STOP_SCAN;
+ /* stop discovery now */
+ btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
- btm_update_scanner_filter_policy(SP_ADV_ALL);
+ btm_update_scanner_filter_policy(SP_ADV_ALL);
- btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
- }
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
}
+
/*******************************************************************************
**
** Function btm_ble_stop_inquiry
*******************************************************************************/
tBTM_STATUS btm_ble_start_adv(void)
{
- tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS rt = BTM_NO_RESOURCES;
BTM_TRACE_EVENT ("btm_ble_start_adv\n");
- if (BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
- return BTM_NO_RESOURCES;
- }
if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) {
return BTM_WRONG_MODE;
*******************************************************************************/
tBTM_STATUS btm_ble_stop_adv(void)
{
- tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS rt = BTM_SUCCESS;
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE
- && !BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) {
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) {
p_cb->fast_adv_on = FALSE;
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
gatt_free_pending_ind(p_tcb);
gatt_free_pending_enc_queue(p_tcb);
gatt_free_pending_prepare_write_queue(p_tcb);
+#if (GATTS_INCLUDED == TRUE)
fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, osi_free_func);
p_tcb->sr_cmd.multi_rsp_q = NULL;
-
+#endif ///GATTS_INCLUDED == TRUE
for (i = 0; i < GATT_MAX_APPS; i ++) {
p_reg = &gatt_cb.cl_rcb[i];
if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< For connection handle 6 */
ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< For connection handle 7 */
ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< For connection handle 8 */
- ESP_BLE_PWR_TYPE_CONN_HDL9 = 9, /*!< For connection handle 9 */
- ESP_BLE_PWR_TYPE_ADV = 10, /*!< For advertising */
- ESP_BLE_PWR_TYPE_SCAN = 11, /*!< For scan */
- ESP_BLE_PWR_TYPE_DEFAULT = 12, /*!< For default, if not set other, it will use default value */
- ESP_BLE_PWR_TYPE_NUM = 13, /*!< TYPE numbers */
+ ESP_BLE_PWR_TYPE_ADV = 9, /*!< For advertising */
+ ESP_BLE_PWR_TYPE_SCAN = 10, /*!< For scan */
+ ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< For default, if not set other, it will use default value */
+ ESP_BLE_PWR_TYPE_NUM = 12, /*!< TYPE numbers */
} esp_ble_power_type_t;
/**
-Subproject commit 2651a662d8ccda03c06a2b775fdaf938270855bd
+Subproject commit d41e3512971612a4903e1ea1189968408811a1ae
*/
esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
+/**
+ * @brief Set software flow control.
+ *
+ * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
+ * @param enable switch on or off
+ * @param rx_thresh_xon low water mark
+ * @param rx_thresh_xoff high water mark
+ *
+ * @return
+ * - ESP_OK Success
+ * - ESP_FAIL Parameter error
+ */
+ esp_err_t uart_set_sw_flow_ctrl(uart_port_t uart_num, bool enable, uint8_t rx_thresh_xon, uint8_t rx_thresh_xoff);
+
/**
* @brief Get hardware flow control mode
*
#include "driver/uart.h"
#include "driver/gpio.h"
+#define XOFF (char)0x13
+#define XON (char)0x11
+
static const char* UART_TAG = "uart";
#define UART_CHECK(a, str, ret_val) \
if (!(a)) { \
return ESP_OK;
}
+esp_err_t uart_set_sw_flow_ctrl(uart_port_t uart_num, bool enable, uint8_t rx_thresh_xon, uint8_t rx_thresh_xoff)
+{
+ UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+ UART_CHECK((rx_thresh_xon < UART_FIFO_LEN), "rx flow xon thresh error", ESP_FAIL);
+ UART_CHECK((rx_thresh_xoff < UART_FIFO_LEN), "rx flow xon thresh error", ESP_FAIL);
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ UART[uart_num]->flow_conf.sw_flow_con_en = enable? 1:0;
+ UART[uart_num]->flow_conf.xonoff_del = enable?1:0;
+ UART[uart_num]->swfc_conf.xon_threshold = rx_thresh_xon;
+ UART[uart_num]->swfc_conf.xoff_threshold = rx_thresh_xoff;
+ UART[uart_num]->swfc_conf.xon_char = XON;
+ UART[uart_num]->swfc_conf.xoff_char = XOFF;
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ return ESP_OK;
+}
+
//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)
{
*libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
*libapp_trace.a:(.literal .text .literal.* .text.*)
*libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*)
- *libesp32.a:app_trace.o(.literal .text .literal.* .text.*)
*libphy.a:(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libsoc.a:(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.o(.literal .text .literal.* .text.*)
*libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
+ *libgcov.a:(.literal .text .literal.* .text.*)
+ INCLUDE esp32.spiram.rom-functions-iram.ld
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
*libesp32.a:panic.o(.rodata .rodata.*)
*libphy.a:(.rodata .rodata.*)
*libapp_trace.a:(.rodata .rodata.*)
+ *libgcov.a:(.rodata .rodata.*)
*libheap.a:multi_heap.o(.rodata .rodata.*)
*libheap.a:multi_heap_poisoning.o(.rodata .rodata.*)
+ INCLUDE esp32.spiram.rom-functions-dram.ld
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} >dram0_0_seg
PROVIDE ( lldesc_build_chain = 0x4000a850 );
PROVIDE ( lldesc_num2link = 0x4000a948 );
PROVIDE ( lldesc_set_owner = 0x4000a974 );
+PROVIDE ( lld_evt_deferred_elt_push = 0x400466b4 );
+PROVIDE ( lld_evt_deferred_elt_pop = 0x400466dc );
+PROVIDE ( lld_evt_winsize_change = 0x40046730 );
+PROVIDE ( lld_evt_rxwin_compute = 0x400467c8 );
+PROVIDE ( lld_evt_slave_time_compute = 0x40046818 );
PROVIDE ( lld_evt_env = 0x3ffb9704 );
+PROVIDE ( lld_evt_elt_wait_get = 0x400468e4 );
+PROVIDE ( lld_evt_get_next_free_slot = 0x4004692c );
PROVIDE ( lld_pdu_adv_pk_desc_tab = 0x3ff98c70 );
PROVIDE ( lld_pdu_llcp_pk_desc_tab = 0x3ff98b68 );
+PROVIDE ( lld_pdu_pack = 0x4004ab14 );
PROVIDE ( LLM_AA_CT1 = 0x3ff98d8a );
PROVIDE ( LLM_AA_CT2 = 0x3ff98d88 );
PROVIDE ( llm_default_handler = 0x3ff98d80 );
PROVIDE ( prbs_64bytes = 0x3ff98992 );
PROVIDE ( nvds_env = 0x3ffb8364 );
PROVIDE ( nvds_magic_number = 0x3ff9912a );
+PROVIDE ( TASK_DESC_LLD = 0x3ff98b58 );
/* Above are static data, but can be used, not generated by script >>>>> btdm data */
--- /dev/null
+/*
+ If the Newlib functions in ROM aren't used (eg because the external SPI RAM workaround is active), these functions will
+ be linked into the application directly instead. Normally, they would end up in flash, which is undesirable because esp-idf
+ and/or applications may assume that because these functions normally are in ROM, they are accessible even when flash is
+ inaccessible. To work around this, this ld fragment places these functions in RAM instead. If the ROM functions are used,
+ these defines do nothing, so they can still be included in that situation.
+
+ This file is responsible for placing the rodata segment in DRAM.
+*/
+
+ *lib_a-utoa.o(.rodata .rodata.*)
+ *lib_a-longjmp.o(.rodata .rodata.*)
+ *lib_a-setjmp.o(.rodata .rodata.*)
+ *lib_a-abs.o(.rodata .rodata.*)
+ *lib_a-div.o(.rodata .rodata.*)
+ *lib_a-labs.o(.rodata .rodata.*)
+ *lib_a-ldiv.o(.rodata .rodata.*)
+ *lib_a-quorem.o(.rodata .rodata.*)
+ *lib_a-qsort.o(.rodata .rodata.*)
+ *lib_a-utoa.o(.rodata .rodata.*)
+ *lib_a-itoa.o(.rodata .rodata.*)
+ *lib_a-atoi.o(.rodata .rodata.*)
+ *lib_a-atol.o(.rodata .rodata.*)
+ *lib_a-strtol.o(.rodata .rodata.*)
+ *lib_a-strtoul.o(.rodata .rodata.*)
+ *lib_a-wcrtomb.o(.rodata .rodata.*)
+ *lib_a-fvwrite.o(.rodata .rodata.*)
+ *lib_a-wbuf.o(.rodata .rodata.*)
+ *lib_a-wsetup.o(.rodata .rodata.*)
+ *lib_a-fputwc.o(.rodata .rodata.*)
+ *lib_a-wctomb_r.o(.rodata .rodata.*)
+ *lib_a-ungetc.o(.rodata .rodata.*)
+ *lib_a-makebuf.o(.rodata .rodata.*)
+ *lib_a-fflush.o(.rodata .rodata.*)
+ *lib_a-refill.o(.rodata .rodata.*)
+ *lib_a-s_fpclassify.o(.rodata .rodata.*)
+ *lib_a-locale.o(.rodata .rodata.*)
+ *lib_a-asctime.o(.rodata .rodata.*)
+ *lib_a-ctime.o(.rodata .rodata.*)
+ *lib_a-ctime_r.o(.rodata .rodata.*)
+ *lib_a-lcltime.o(.rodata .rodata.*)
+ *lib_a-lcltime_r.o(.rodata .rodata.*)
+ *lib_a-gmtime.o(.rodata .rodata.*)
+ *lib_a-gmtime_r.o(.rodata .rodata.*)
+ *lib_a-strftime.o(.rodata .rodata.*)
+ *lib_a-mktime.o(.rodata .rodata.*)
+ *lib_a-syswrite.o(.rodata .rodata.*)
+ *lib_a-tzset_r.o(.rodata .rodata.*)
+ *lib_a-tzset.o(.rodata .rodata.*)
+ *lib_a-toupper.o(.rodata .rodata.*)
+ *lib_a-tolower.o(.rodata .rodata.*)
+ *lib_a-toascii.o(.rodata .rodata.*)
+ *lib_a-systimes.o(.rodata .rodata.*)
+ *lib_a-time.o(.rodata .rodata.*)
+ *lib_a-bsd_qsort_r.o(.rodata .rodata.*)
+ *lib_a-qsort_r.o(.rodata .rodata.*)
+ *lib_a-gettzinfo.o(.rodata .rodata.*)
+ *lib_a-strupr.o(.rodata .rodata.*)
+ *lib_a-asctime_r.o(.rodata .rodata.*)
+ *lib_a-bzero.o(.rodata .rodata.*)
+ *lib_a-close.o(.rodata .rodata.*)
+ *lib_a-creat.o(.rodata .rodata.*)
+ *lib_a-environ.o(.rodata .rodata.*)
+ *lib_a-fclose.o(.rodata .rodata.*)
+ *lib_a-isalnum.o(.rodata .rodata.*)
+ *lib_a-isalpha.o(.rodata .rodata.*)
+ *lib_a-isascii.o(.rodata .rodata.*)
+ *lib_a-isblank.o(.rodata .rodata.*)
+ *lib_a-iscntrl.o(.rodata .rodata.*)
+ *lib_a-isdigit.o(.rodata .rodata.*)
+ *lib_a-isgraph.o(.rodata .rodata.*)
+ *lib_a-islower.o(.rodata .rodata.*)
+ *lib_a-isprint.o(.rodata .rodata.*)
+ *lib_a-ispunct.o(.rodata .rodata.*)
+ *lib_a-isspace.o(.rodata .rodata.*)
+ *lib_a-isupper.o(.rodata .rodata.*)
+ *lib_a-memccpy.o(.rodata .rodata.*)
+ *lib_a-memchr.o(.rodata .rodata.*)
+ *lib_a-memcmp.o(.rodata .rodata.*)
+ *lib_a-memcpy.o(.rodata .rodata.*)
+ *lib_a-memmove.o(.rodata .rodata.*)
+ *lib_a-memrchr.o(.rodata .rodata.*)
+ *lib_a-memset.o(.rodata .rodata.*)
+ *lib_a-open.o(.rodata .rodata.*)
+ *lib_a-rand.o(.rodata .rodata.*)
+ *lib_a-rand_r.o(.rodata .rodata.*)
+ *lib_a-read.o(.rodata .rodata.*)
+ *lib_a-rshift.o(.rodata .rodata.*)
+ *lib_a-sbrk.o(.rodata .rodata.*)
+ *lib_a-srand.o(.rodata .rodata.*)
+ *lib_a-strcasecmp.o(.rodata .rodata.*)
+ *lib_a-strcasestr.o(.rodata .rodata.*)
+ *lib_a-strcat.o(.rodata .rodata.*)
+ *lib_a-strchr.o(.rodata .rodata.*)
+ *lib_a-strcmp.o(.rodata .rodata.*)
+ *lib_a-strcoll.o(.rodata .rodata.*)
+ *lib_a-strcpy.o(.rodata .rodata.*)
+ *lib_a-strcspn.o(.rodata .rodata.*)
+ *lib_a-strdup.o(.rodata .rodata.*)
+ *lib_a-strlcat.o(.rodata .rodata.*)
+ *lib_a-strlcpy.o(.rodata .rodata.*)
+ *lib_a-strlen.o(.rodata .rodata.*)
+ *lib_a-strlwr.o(.rodata .rodata.*)
+ *lib_a-strncasecmp.o(.rodata .rodata.*)
+ *lib_a-strncat.o(.rodata .rodata.*)
+ *lib_a-strncmp.o(.rodata .rodata.*)
+ *lib_a-strncpy.o(.rodata .rodata.*)
+ *lib_a-strndup.o(.rodata .rodata.*)
+ *lib_a-strnlen.o(.rodata .rodata.*)
+ *lib_a-strrchr.o(.rodata .rodata.*)
+ *lib_a-strsep.o(.rodata .rodata.*)
+ *lib_a-strspn.o(.rodata .rodata.*)
+ *lib_a-strstr.o(.rodata .rodata.*)
+ *lib_a-strtok_r.o(.rodata .rodata.*)
+ *lib_a-strupr.o(.rodata .rodata.*)
+ *lib_a-stdio.o(.rodata .rodata.*)
+ *lib_a-syssbrk.o(.rodata .rodata.*)
+ *lib_a-sysclose.o(.rodata .rodata.*)
+ *lib_a-sysopen.o(.rodata .rodata.*)
+ *creat.o(.rodata .rodata.*)
+ *lib_a-sysread.o(.rodata .rodata.*)
+ *lib_a-syswrite.o(.rodata .rodata.*)
+ *lib_a-impure.o(.rodata .rodata.*)
+ *lib_a-tzvars.o(.rodata .rodata.*)
+ *lib_a-sf_nan.o(.rodata .rodata.*)
+ *lib_a-tzcalc_limits.o(.rodata .rodata.*)
+ *lib_a-month_lengths.o(.rodata .rodata.*)
+ *lib_a-timelocal.o(.rodata .rodata.*)
+ *lib_a-findfp.o(.rodata .rodata.*)
+ *lock.o(.rodata .rodata.*)
+ *lib_a-getenv_r.o(.rodata .rodata.*)
+ *isatty.o(.rodata .rodata.*)
+ *lib_a-fwalk.o(.rodata .rodata.*)
+ *lib_a-getenv_r.o(.rodata .rodata.*)
+ *lib_a-tzlock.o(.rodata .rodata.*)
+ *lib_a-ctype_.o(.rodata .rodata.*)
+ *lib_a-sccl.o(.rodata .rodata.*)
+ *lib_a-strptime.o(.rodata .rodata.*)
+ *lib_a-envlock.o(.rodata .rodata.*)
+ *lib_a-raise.o(.rodata .rodata.*)
+ *lib_a-strdup_r.o(.rodata .rodata.*)
+ *lib_a-system.o(.rodata .rodata.*)
+ *lib_a-strndup_r.o(.rodata .rodata.*)
--- /dev/null
+/*
+ If the Newlib functions in ROM aren't used (eg because the external SPI RAM workaround is active), these functions will
+ be linked into the application directly instead. Normally, they would end up in flash, which is undesirable because esp-idf
+ and/or applications may assume that because these functions normally are in ROM, they are accessible even when flash is
+ inaccessible. To work around this, this ld fragment places these functions in RAM instead. If the ROM functions are used,
+ these defines do nothing, so they can still be included in that situation.
+
+ This file is responsible for placing the literal and text segments in IRAM.
+*/
+
+
+ *lib_a-utoa.o(.literal .text .literal.* .text.*)
+ *lib_a-longjmp.o(.literal .text .literal.* .text.*)
+ *lib_a-setjmp.o(.literal .text .literal.* .text.*)
+ *lib_a-abs.o(.literal .text .literal.* .text.*)
+ *lib_a-div.o(.literal .text .literal.* .text.*)
+ *lib_a-labs.o(.literal .text .literal.* .text.*)
+ *lib_a-ldiv.o(.literal .text .literal.* .text.*)
+ *lib_a-quorem.o(.literal .text .literal.* .text.*)
+ *lib_a-qsort.o(.literal .text .literal.* .text.*)
+ *lib_a-utoa.o(.literal .text .literal.* .text.*)
+ *lib_a-itoa.o(.literal .text .literal.* .text.*)
+ *lib_a-atoi.o(.literal .text .literal.* .text.*)
+ *lib_a-atol.o(.literal .text .literal.* .text.*)
+ *lib_a-strtol.o(.literal .text .literal.* .text.*)
+ *lib_a-strtoul.o(.literal .text .literal.* .text.*)
+ *lib_a-wcrtomb.o(.literal .text .literal.* .text.*)
+ *lib_a-fvwrite.o(.literal .text .literal.* .text.*)
+ *lib_a-wbuf.o(.literal .text .literal.* .text.*)
+ *lib_a-wsetup.o(.literal .text .literal.* .text.*)
+ *lib_a-fputwc.o(.literal .text .literal.* .text.*)
+ *lib_a-wctomb_r.o(.literal .text .literal.* .text.*)
+ *lib_a-ungetc.o(.literal .text .literal.* .text.*)
+ *lib_a-makebuf.o(.literal .text .literal.* .text.*)
+ *lib_a-fflush.o(.literal .text .literal.* .text.*)
+ *lib_a-refill.o(.literal .text .literal.* .text.*)
+ *lib_a-s_fpclassify.o(.literal .text .literal.* .text.*)
+ *lib_a-locale.o(.literal .text .literal.* .text.*)
+ *lib_a-asctime.o(.literal .text .literal.* .text.*)
+ *lib_a-ctime.o(.literal .text .literal.* .text.*)
+ *lib_a-ctime_r.o(.literal .text .literal.* .text.*)
+ *lib_a-lcltime.o(.literal .text .literal.* .text.*)
+ *lib_a-lcltime_r.o(.literal .text .literal.* .text.*)
+ *lib_a-gmtime.o(.literal .text .literal.* .text.*)
+ *lib_a-gmtime_r.o(.literal .text .literal.* .text.*)
+ *lib_a-strftime.o(.literal .text .literal.* .text.*)
+ *lib_a-mktime.o(.literal .text .literal.* .text.*)
+ *lib_a-syswrite.o(.literal .text .literal.* .text.*)
+ *lib_a-tzset_r.o(.literal .text .literal.* .text.*)
+ *lib_a-tzset.o(.literal .text .literal.* .text.*)
+ *lib_a-toupper.o(.literal .text .literal.* .text.*)
+ *lib_a-tolower.o(.literal .text .literal.* .text.*)
+ *lib_a-toascii.o(.literal .text .literal.* .text.*)
+ *lib_a-systimes.o(.literal .text .literal.* .text.*)
+ *lib_a-time.o(.literal .text .literal.* .text.*)
+ *lib_a-bsd_qsort_r.o(.literal .text .literal.* .text.*)
+ *lib_a-qsort_r.o(.literal .text .literal.* .text.*)
+ *lib_a-gettzinfo.o(.literal .text .literal.* .text.*)
+ *lib_a-strupr.o(.literal .text .literal.* .text.*)
+ *lib_a-asctime_r.o(.literal .text .literal.* .text.*)
+ *lib_a-bzero.o(.literal .text .literal.* .text.*)
+ *lib_a-close.o(.literal .text .literal.* .text.*)
+ *lib_a-creat.o(.literal .text .literal.* .text.*)
+ *lib_a-environ.o(.literal .text .literal.* .text.*)
+ *lib_a-fclose.o(.literal .text .literal.* .text.*)
+ *lib_a-isalnum.o(.literal .text .literal.* .text.*)
+ *lib_a-isalpha.o(.literal .text .literal.* .text.*)
+ *lib_a-isascii.o(.literal .text .literal.* .text.*)
+ *lib_a-isblank.o(.literal .text .literal.* .text.*)
+ *lib_a-iscntrl.o(.literal .text .literal.* .text.*)
+ *lib_a-isdigit.o(.literal .text .literal.* .text.*)
+ *lib_a-isgraph.o(.literal .text .literal.* .text.*)
+ *lib_a-islower.o(.literal .text .literal.* .text.*)
+ *lib_a-isprint.o(.literal .text .literal.* .text.*)
+ *lib_a-ispunct.o(.literal .text .literal.* .text.*)
+ *lib_a-isspace.o(.literal .text .literal.* .text.*)
+ *lib_a-isupper.o(.literal .text .literal.* .text.*)
+ *lib_a-memccpy.o(.literal .text .literal.* .text.*)
+ *lib_a-memchr.o(.literal .text .literal.* .text.*)
+ *lib_a-memcmp.o(.literal .text .literal.* .text.*)
+ *lib_a-memcpy.o(.literal .text .literal.* .text.*)
+ *lib_a-memmove.o(.literal .text .literal.* .text.*)
+ *lib_a-memrchr.o(.literal .text .literal.* .text.*)
+ *lib_a-memset.o(.literal .text .literal.* .text.*)
+ *lib_a-open.o(.literal .text .literal.* .text.*)
+ *lib_a-rand.o(.literal .text .literal.* .text.*)
+ *lib_a-rand_r.o(.literal .text .literal.* .text.*)
+ *lib_a-read.o(.literal .text .literal.* .text.*)
+ *lib_a-rshift.o(.literal .text .literal.* .text.*)
+ *lib_a-sbrk.o(.literal .text .literal.* .text.*)
+ *lib_a-srand.o(.literal .text .literal.* .text.*)
+ *lib_a-strcasecmp.o(.literal .text .literal.* .text.*)
+ *lib_a-strcasestr.o(.literal .text .literal.* .text.*)
+ *lib_a-strcat.o(.literal .text .literal.* .text.*)
+ *lib_a-strchr.o(.literal .text .literal.* .text.*)
+ *lib_a-strcmp.o(.literal .text .literal.* .text.*)
+ *lib_a-strcoll.o(.literal .text .literal.* .text.*)
+ *lib_a-strcpy.o(.literal .text .literal.* .text.*)
+ *lib_a-strcspn.o(.literal .text .literal.* .text.*)
+ *lib_a-strdup.o(.literal .text .literal.* .text.*)
+ *lib_a-strlcat.o(.literal .text .literal.* .text.*)
+ *lib_a-strlcpy.o(.literal .text .literal.* .text.*)
+ *lib_a-strlen.o(.literal .text .literal.* .text.*)
+ *lib_a-strlwr.o(.literal .text .literal.* .text.*)
+ *lib_a-strncasecmp.o(.literal .text .literal.* .text.*)
+ *lib_a-strncat.o(.literal .text .literal.* .text.*)
+ *lib_a-strncmp.o(.literal .text .literal.* .text.*)
+ *lib_a-strncpy.o(.literal .text .literal.* .text.*)
+ *lib_a-strndup.o(.literal .text .literal.* .text.*)
+ *lib_a-strnlen.o(.literal .text .literal.* .text.*)
+ *lib_a-strrchr.o(.literal .text .literal.* .text.*)
+ *lib_a-strsep.o(.literal .text .literal.* .text.*)
+ *lib_a-strspn.o(.literal .text .literal.* .text.*)
+ *lib_a-strstr.o(.literal .text .literal.* .text.*)
+ *lib_a-strtok_r.o(.literal .text .literal.* .text.*)
+ *lib_a-strupr.o(.literal .text .literal.* .text.*)
+ *lib_a-stdio.o(.literal .text .literal.* .text.*)
+ *lib_a-syssbrk.o(.literal .text .literal.* .text.*)
+ *lib_a-sysclose.o(.literal .text .literal.* .text.*)
+ *lib_a-sysopen.o(.literal .text .literal.* .text.*)
+ *creat.o(.literal .text .literal.* .text.*)
+ *lib_a-sysread.o(.literal .text .literal.* .text.*)
+ *lib_a-syswrite.o(.literal .text .literal.* .text.*)
+ *lib_a-impure.o(.literal .text .literal.* .text.*)
+ *lib_a-tzvars.o(.literal .text .literal.* .text.*)
+ *lib_a-sf_nan.o(.literal .text .literal.* .text.*)
+ *lib_a-tzcalc_limits.o(.literal .text .literal.* .text.*)
+ *lib_a-month_lengths.o(.literal .text .literal.* .text.*)
+ *lib_a-timelocal.o(.literal .text .literal.* .text.*)
+ *lib_a-findfp.o(.literal .text .literal.* .text.*)
+ *lock.o(.literal .text .literal.* .text.*)
+ *lib_a-getenv_r.o(.literal .text .literal.* .text.*)
+ *isatty.o(.literal .text .literal.* .text.*)
+ *lib_a-fwalk.o(.literal .text .literal.* .text.*)
+ *lib_a-getenv_r.o(.literal .text .literal.* .text.*)
+ *lib_a-tzlock.o(.literal .text .literal.* .text.*)
+ *lib_a-ctype_.o(.literal .text .literal.* .text.*)
+ *lib_a-sccl.o(.literal .text .literal.* .text.*)
+ *lib_a-strptime.o(.literal .text .literal.* .text.*)
+ *lib_a-envlock.o(.literal .text .literal.* .text.*)
+ *lib_a-raise.o(.literal .text .literal.* .text.*)
+ *lib_a-strdup_r.o(.literal .text .literal.* .text.*)
+ *lib_a-system.o(.literal .text .literal.* .text.*)
+ *lib_a-strndup_r.o(.literal .text .literal.* .text.*)
*/
#include "FreeRTOS.h"
+#include "esp_attr.h"
#include "sdkconfig.h"
#ifdef __GNUC__
#endif
#ifdef CONFIG_ESP32_DEBUG_OCDAWARE
-const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1;
-#endif
\ No newline at end of file
+const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1;
+#endif
#define configXT_BOARD 1 /* Board mode */
#define configXT_SIMULATOR 0
-#if CONFIG_ESP32_ENABLE_COREDUMP
#define configENABLE_TASK_SNAPSHOT 1
-#endif
#if CONFIG_SYSVIEW_ENABLE
#ifndef __ASSEMBLER__
#endif /* configUSE_TASK_NOTIFICATIONS */
#if ( configENABLE_TASK_SNAPSHOT == 1 )
-
- static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB )
- {
- pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
- pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack;
- #if( portSTACK_GROWTH < 0 )
- {
- pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack;
- }
- #else
- {
- pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack;
- }
- #endif
- (*uxTask)++;
- }
+ static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB )
+ {
+ if (pxTCB == NULL) {
+ return;
+ }
+ pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
+ pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack;
+ #if( portSTACK_GROWTH < 0 )
+ {
+ pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack;
+ }
+ #else
+ {
+ pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack;
+ }
+ #endif
+ (*uxTask)++;
+ }
static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList )
{
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
do
{
- listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
-
if( *uxTask >= uxArraySize )
break;
- prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
+ prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
} while( pxNextTCB != pxFirstTCB );
}
else
{
UBaseType_t uxTask = 0, i = 0;
-PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB[ portNUM_PROCESSORS ] = { NULL };
-
*pxTcbSz = sizeof(TCB_t);
/* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList );
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList );
- for (i = 0; i < portNUM_PROCESSORS; i++) {
- if( uxTask >= uxArraySize )
- break;
- prvTaskGetSnapshot( pxTaskSnapshotArray, &uxTask, pxCurrentTCB[ i ] );
- prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( xPendingReadyList[ i ] ) );
- }
+ for (i = 0; i < portNUM_PROCESSORS; i++) {
+ if( uxTask >= uxArraySize )
+ break;
+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( xPendingReadyList[ i ] ) );
+ }
#if( INCLUDE_vTaskDelete == 1 )
{
--- /dev/null
+/*
+ Test FreeRTOS support for core dump.
+*/
+
+#include <stdio.h>
+#include "soc/cpu.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "unity.h"
+
+#define TEST_MAX_TASKS_NUM 32
+
+/* simple test to check that in normal conditions uxTaskGetSnapshotAll does not generate exception */
+TEST_CASE("Tasks snapshot", "[freertos]")
+{
+ TaskSnapshot_t tasks[TEST_MAX_TASKS_NUM];
+ UBaseType_t tcb_sz;
+ int other_core_id = xPortGetCoreID() == 0 ? 1 : 0;
+
+ // uxTaskGetSnapshotAll is supposed to be called when all tasks on both CPUs are
+ // inactive and can not alter FreeRTOS internal tasks lists, e.g. from panic handler
+ unsigned state = portENTER_CRITICAL_NESTED();
+#if CONFIG_FREERTOS_UNICORE == 0
+ esp_cpu_stall(other_core_id);
+#endif
+ UBaseType_t task_num = uxTaskGetSnapshotAll(tasks, TEST_MAX_TASKS_NUM, &tcb_sz);
+#if CONFIG_FREERTOS_UNICORE == 0
+ esp_cpu_unstall(other_core_id);
+#endif
+ portEXIT_CRITICAL_NESTED(state);
+
+ printf("Dumped %d tasks. TCB size %d\n", task_num, tcb_sz);
+ TEST_ASSERT_NOT_EQUAL(0, task_num);
+ TEST_ASSERT_NOT_EQUAL(0, tcb_sz);
+}
#include "tcpip_adapter.h"
#include "apps/dhcpserver.h"
+#include "apps/dhcpserver_options.h"
#if ESP_DHCP
#define DHCPS_STATE_IDLE 5
#define DHCPS_STATE_RELEASE 6
+typedef struct _list_node {
+ void *pnode;
+ struct _list_node *pnext;
+} list_node;
+
////////////////////////////////////////////////////////////////////////////////////
static const u32_t magic_cookie = 0x63538263;
* pinsert -- the insert node of the list
* Returns : none
*******************************************************************************/
-void node_insert_to_list(list_node **phead, list_node *pinsert)
+static void node_insert_to_list(list_node **phead, list_node *pinsert)
{
list_node *plist = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
u8_t options[312];
}dhcps_msg;
-/** DHCP OPTIONS CODE **/
-typedef enum
-{
- /* RFC 1497 Vendor Extensions */
-
- PAD = 0,
- END = 255,
-
- SUBNET_MASK = 1,
- TIME_OFFSET = 2,
- ROUTER = 3,
- TIME_SERVER = 4,
- NAME_SERVER = 5,
- DOMAIN_NAME_SERVER = 6,
- LOG_SERVER = 7,
- COOKIE_SERVER = 8,
- LPR_SERVER = 9,
- IMPRESS_SERVER = 10,
- RESOURCE_LOCATION_SERVER = 11,
- HOST_NAME = 12,
- BOOT_FILE_SIZE = 13,
- MERIT_DUMP_FILE = 14,
- DOMAIN_NAME = 15,
- SWAP_SERVER = 16,
- ROOT_PATH = 17,
- EXTENSIONS_PATH = 18,
-
- /* IP Layer Parameters per Host */
-
- IP_FORWARDING = 19,
- NON_LOCAL_SOURCE_ROUTING = 20,
- POLICY_FILTER = 21,
- MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22,
- DEFAULT_IP_TIME_TO_LIVE = 23,
- PATH_MTU_AGING_TIMEOUT = 24,
- PATH_MTU_PLATEAU_TABLE = 25,
-
- /* IP Layer Parameters per Interface */
-
- INTERFACE_MTU = 26,
- ALL_SUBNETS_ARE_LOCAL = 27,
- BROADCAST_ADDRESS = 28,
- PERFORM_MASK_DISCOVERY = 29,
- MASK_SUPPLIER = 30,
- PERFORM_ROUTER_DISCOVERY = 31,
- ROUTER_SOLICITATION_ADDRESS = 32,
- STATIC_ROUTE = 33,
-
- /* Link Layer Parameters per Interface */
-
- TRAILER_ENCAPSULATION = 34,
- ARP_CACHE_TIMEOUT = 35,
- ETHERNET_ENCAPSULATION = 36,
-
- /* TCP Parameters */
-
- TCP_DEFAULT_TTL = 37,
- TCP_KEEPALIVE_INTERVAL = 38,
- TCP_KEEPALIVE_GARBAGE = 39,
-
- /* Application and Service Parameters */
-
- NETWORK_INFORMATION_SERVICE_DOMAIN = 40,
- NETWORK_INFORMATION_SERVERS = 41,
- NETWORK_TIME_PROTOCOL_SERVERS = 42,
- VENDOR_SPECIFIC_INFORMATION = 43,
- NETBIOS_OVER_TCP_IP_NAME_SERVER = 44,
- NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 45,
- NETBIOS_OVER_TCP_IP_NODE_TYPE = 46,
- NETBIOS_OVER_TCP_IP_SCOPE = 47,
- X_WINDOW_SYSTEM_FONT_SERVER = 48,
- X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49,
- NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64,
- NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65,
- MOBILE_IP_HOME_AGENT = 68,
- SMTP_SERVER = 69,
- POP3_SERVER = 70,
- NNTP_SERVER = 71,
- DEFAULT_WWW_SERVER = 72,
- DEFAULT_FINGER_SERVER = 73,
- DEFAULT_IRC_SERVER = 74,
- STREETTALK_SERVER = 75,
- STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76,
-
- /* DHCP Extensions */
-
- REQUESTED_IP_ADDRESS = 50,
- IP_ADDRESS_LEASE_TIME = 51,
- OPTION_OVERLOAD = 52,
- TFTP_SERVER_NAME = 66,
- BOOTFILE_NAME = 67,
- DHCP_MESSAGE_TYPE = 53,
- SERVER_IDENTIFIER = 54,
- PARAMETER_REQUEST_LIST = 55,
- MESSAGE = 56,
- MAXIMUM_DHCP_MESSAGE_SIZE = 57,
- RENEWAL_T1_TIME_VALUE = 58,
- REBINDING_T2_TIME_VALUE = 59,
- VENDOR_CLASS_IDENTIFIER = 60,
- CLIENT_IDENTIFIER = 61,
-
- USER_CLASS = 77,
- FQDN = 81,
- DHCP_AGENT_OPTIONS = 82,
- NDS_SERVERS = 85,
- NDS_TREE_NAME = 86,
- NDS_CONTEXT = 87,
- CLIENT_LAST_TRANSACTION_TIME = 91,
- ASSOCIATED_IP = 92,
- USER_AUTHENTICATION_PROTOCOL = 98,
- AUTO_CONFIGURE = 116,
- NAME_SERVICE_SEARCH = 117,
- SUBNET_SELECTION = 118,
- DOMAIN_SEARCH = 119,
- CLASSLESS_ROUTE = 121,
-} dhcp_msg_option;
-
/* Defined in esp_misc.h */
typedef struct {
bool enable;
u32_t lease_timer;
};
-typedef struct _list_node{
- void *pnode;
- struct _list_node *pnext;
-}list_node;
-
typedef u32_t dhcps_time_t;
typedef u8_t dhcps_offer_t;
--- /dev/null
+// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed 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.
+#pragma once
+
+/** DHCP Options
+
+ This macros are not part of the public dhcpserver.h interface.
+ **/
+typedef enum
+{
+ /* RFC 1497 Vendor Extensions */
+
+ PAD = 0,
+ END = 255,
+
+ SUBNET_MASK = 1,
+ TIME_OFFSET = 2,
+ ROUTER = 3,
+ TIME_SERVER = 4,
+ NAME_SERVER = 5,
+ DOMAIN_NAME_SERVER = 6,
+ LOG_SERVER = 7,
+ COOKIE_SERVER = 8,
+ LPR_SERVER = 9,
+ IMPRESS_SERVER = 10,
+ RESOURCE_LOCATION_SERVER = 11,
+ HOST_NAME = 12,
+ BOOT_FILE_SIZE = 13,
+ MERIT_DUMP_FILE = 14,
+ DOMAIN_NAME = 15,
+ SWAP_SERVER = 16,
+ ROOT_PATH = 17,
+ EXTENSIONS_PATH = 18,
+
+ /* IP Layer Parameters per Host */
+
+ IP_FORWARDING = 19,
+ NON_LOCAL_SOURCE_ROUTING = 20,
+ POLICY_FILTER = 21,
+ MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22,
+ DEFAULT_IP_TIME_TO_LIVE = 23,
+ PATH_MTU_AGING_TIMEOUT = 24,
+ PATH_MTU_PLATEAU_TABLE = 25,
+
+ /* IP Layer Parameters per Interface */
+
+ INTERFACE_MTU = 26,
+ ALL_SUBNETS_ARE_LOCAL = 27,
+ BROADCAST_ADDRESS = 28,
+ PERFORM_MASK_DISCOVERY = 29,
+ MASK_SUPPLIER = 30,
+ PERFORM_ROUTER_DISCOVERY = 31,
+ ROUTER_SOLICITATION_ADDRESS = 32,
+ STATIC_ROUTE = 33,
+
+ /* Link Layer Parameters per Interface */
+
+ TRAILER_ENCAPSULATION = 34,
+ ARP_CACHE_TIMEOUT = 35,
+ ETHERNET_ENCAPSULATION = 36,
+
+ /* TCP Parameters */
+
+ TCP_DEFAULT_TTL = 37,
+ TCP_KEEPALIVE_INTERVAL = 38,
+ TCP_KEEPALIVE_GARBAGE = 39,
+
+ /* Application and Service Parameters */
+
+ NETWORK_INFORMATION_SERVICE_DOMAIN = 40,
+ NETWORK_INFORMATION_SERVERS = 41,
+ NETWORK_TIME_PROTOCOL_SERVERS = 42,
+ VENDOR_SPECIFIC_INFORMATION = 43,
+ NETBIOS_OVER_TCP_IP_NAME_SERVER = 44,
+ NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 45,
+ NETBIOS_OVER_TCP_IP_NODE_TYPE = 46,
+ NETBIOS_OVER_TCP_IP_SCOPE = 47,
+ X_WINDOW_SYSTEM_FONT_SERVER = 48,
+ X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49,
+ NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64,
+ NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65,
+ MOBILE_IP_HOME_AGENT = 68,
+ SMTP_SERVER = 69,
+ POP3_SERVER = 70,
+ NNTP_SERVER = 71,
+ DEFAULT_WWW_SERVER = 72,
+ DEFAULT_FINGER_SERVER = 73,
+ DEFAULT_IRC_SERVER = 74,
+ STREETTALK_SERVER = 75,
+ STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76,
+
+ /* DHCP Extensions */
+
+ REQUESTED_IP_ADDRESS = 50,
+ IP_ADDRESS_LEASE_TIME = 51,
+ OPTION_OVERLOAD = 52,
+ TFTP_SERVER_NAME = 66,
+ BOOTFILE_NAME = 67,
+ DHCP_MESSAGE_TYPE = 53,
+ SERVER_IDENTIFIER = 54,
+ PARAMETER_REQUEST_LIST = 55,
+ MESSAGE = 56,
+ MAXIMUM_DHCP_MESSAGE_SIZE = 57,
+ RENEWAL_T1_TIME_VALUE = 58,
+ REBINDING_T2_TIME_VALUE = 59,
+ VENDOR_CLASS_IDENTIFIER = 60,
+ CLIENT_IDENTIFIER = 61,
+
+ USER_CLASS = 77,
+ FQDN = 81,
+ DHCP_AGENT_OPTIONS = 82,
+ NDS_SERVERS = 85,
+ NDS_TREE_NAME = 86,
+ NDS_CONTEXT = 87,
+ CLIENT_LAST_TRANSACTION_TIME = 91,
+ ASSOCIATED_IP = 92,
+ USER_AUTHENTICATION_PROTOCOL = 98,
+ AUTO_CONFIGURE = 116,
+ NAME_SERVICE_SEARCH = 117,
+ SUBNET_SELECTION = 118,
+ DOMAIN_SEARCH = 119,
+ CLASSLESS_ROUTE = 121,
+} dhcp_msg_option;
return ESP_ERR_NVS_INVALID_LENGTH;
}
+ *length = dataSize;
return entry.mStoragePtr->readItem(entry.mNsIndex, type, key, out_value, dataSize);
}
TEST_ESP_ERR(ESP_ERR_NVS_INVALID_LENGTH, nvs_get_str(handle_2, "key", buf, &buf_len_short));
CHECK(buf_len_short == buf_len);
+ size_t buf_len_long = buf_len + 1;
+ TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len_long));
+ CHECK(buf_len_long == buf_len);
+
TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len));
CHECK(0 == strcmp(buf, str));
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_PRIV_INCLUDEDIRS := spiffs/src
COMPONENT_SRCDIRS := . spiffs/src
+
+COMPONENT_SUBMODULES := spiffs
#include "netif/ethernetif.h"
#include "apps/dhcpserver.h"
+#include "apps/dhcpserver_options.h"
#include "esp_event.h"
#include "esp_log.h"
By default, the build process will print a warning if an undefined variable is referenced (like ``$(DOES_NOT_EXIST)``). This can be useful to find errors in variable names.
-If you don't want this behaviour, it can be disabled by disabling :ref:`CONFIG_MAKE_WARN_UNDEFINED_VARIABLES`.
+If you don't want this behaviour, it can be disabled in menuconfig's top level menu under `SDK tool configuration`.
Note that this option doesn't trigger a warning if ``ifdef`` or ``ifndef`` are used in Makefiles.
``trans_conf.rx_length`` respectively. ** Note that a half duplex transaction with both a read and
write phase is not supported when using DMA. ** If such transaction is needed, you have to use one
of the alternative solutions:
+
1. use full-duplex mode instead.
2. disable the DMA by set the last parameter to 0 in bus initialization function just as belows:
``ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);``
Normally, data to be transferred to or from a device will be read from or written to a chunk of memory
indicated by the ``rx_buffer`` and ``tx_buffer`` members of the transaction structure.
When DMA is enabled for transfers, these buffers are highly recommended to meet the requirements as belows:
+
1. allocated in DMA-capable memory using ``pvPortMallocCaps(size, MALLOC_CAP_DMA)``;
2. 32-bit aligned (start from the boundary and have length of multiples of 4 bytes).
+
If these requirements are not satisfied, efficiency of the transaction will suffer due to the allocation and
memcpy of temporary buffers.
\r
.. note::\r
\r
- Most ESP32 development boards have a 40MHz crystal installed. However, some boards use a 26MHz crystal. If your board uses a 26MHz crystal, or you get garbage output from serial port after code upload, adjust the :ref:`CONFIG_ESP32_XTAL_FREQ` option in menuconfig.\r
+ Most ESP32 development boards have a 40MHz crystal installed. However, some boards use a 26MHz crystal. If your board uses a 26MHz crystal, or you get garbage output from serial port after code upload, adjust the :ref:`CONFIG_ESP32_XTAL_FREQ_SEL` option in menuconfig.\r
\r
.. _get-started-build-flash:\r
\r
import os
import re
import sys
+import platform
# File layout:
#
self.m = register_special_symbol(TRISTATE, "m", "m")
self.y = register_special_symbol(TRISTATE, "y", "y")
# DEFCONFIG_LIST uses this
- register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
+ # changed os.uname to platform.uname for compatibility with Windows
+ register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
# The symbol with "option defconfig_list" set, containing a list of
# default .config files
--- /dev/null
+_build/inc/esp_a2dp_api.inc:26: WARNING: Invalid definition: Expected identifier in nested name. [error at 21]
+ union esp_a2d_mcc_t::@1 esp_a2d_mcc_t::cie
+ ---------------------^
+_build/inc/esp_bt_defs.inc:11: WARNING: Invalid definition: Expected identifier in nested name. [error at 21]
+ union esp_bt_uuid_t::@0 esp_bt_uuid_t::uuid
+ ---------------------^
+/builds/idf/esp-idf/docs/api-reference/storage/sdmmc.rst:24: WARNING: cpp:typeOrConcept targets a member (sdmmc_host_t::slot).
+/builds/idf/esp-idf/docs/api-reference/storage/sdmmc.rst:24: WARNING: cpp:typeOrConcept targets a member (sdmmc_host_t::slot).
+/builds/idf/esp-idf/docs/api-reference/storage/sdmmc.rst:24: WARNING: cpp:typeOrConcept targets a member (sdmmc_host_t::slot).
return key_str;
}
+static void show_bonded_devices(void)
+{
+ int dev_num = esp_ble_get_bond_device_num();
+
+ esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
+ esp_ble_get_bond_device_list(&dev_num, dev_list);
+ ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices number : %d\n", dev_num);
+
+ ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices list : %d\n", dev_num);
+ for (int i = 0; i < dev_num; i++) {
+ esp_log_buffer_hex(GATTS_TABLE_TAG, (void *)dev_list[i].bd_addr, sizeof(esp_bd_addr_t));
+ }
+
+ free(dev_list);
+}
+
+static void __attribute__((unused)) remove_all_bonded_devices(void)
+{
+ int dev_num = esp_ble_get_bond_device_num();
+
+ esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
+ esp_ble_get_bond_device_list(&dev_num, dev_list);
+ for (int i = 0; i < dev_num; i++) {
+ esp_ble_remove_bond_device(dev_list[i].bd_addr);
+ }
+
+ free(dev_list);
+}
+
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
ESP_LOGV(GATTS_TABLE_TAG, "GAP_EVT, event %d\n", event);
(bd_addr[4] << 8) + bd_addr[5]);
ESP_LOGI(GATTS_TABLE_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
+ show_bonded_devices();
break;
}
case ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT: {
- ESP_LOGI(GATTS_TABLE_TAG, "ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT status = %d", param->remove_bond_dev_cmpl.status);
- break;
- }
- case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT: {
- ESP_LOGI(GATTS_TABLE_TAG, "ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT status = %d", param->clear_bond_dev_cmpl.status);
- break;
- }
- case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT: {
- ESP_LOGI(GATTS_TABLE_TAG, "ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT status = %d, num = %d", param->get_bond_dev_cmpl.status, param->get_bond_dev_cmpl.dev_num);
- esp_ble_bond_dev_t *bond_dev = param->get_bond_dev_cmpl.bond_dev;
- for(int i = 0; i < param->get_bond_dev_cmpl.dev_num; i++) {
- ESP_LOGI(GATTS_TABLE_TAG, "mask = %x", bond_dev[i].bond_key.key_mask);
- esp_log_buffer_hex(GATTS_TABLE_TAG, (void *)bond_dev[i].bd_addr, sizeof(esp_bd_addr_t));
- }
+ ESP_LOGD(GATTS_TABLE_TAG, "ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT status = %d", param->remove_bond_dev_cmpl.status);
+ ESP_LOGI(GATTS_TABLE_TAG, "ESP_GAP_BLE_REMOVE_BOND_DEV");
+ ESP_LOGI(GATTS_TABLE_TAG, "-----ESP_GAP_BLE_REMOVE_BOND_DEV----");
+ esp_log_buffer_hex(GATTS_TABLE_TAG, (void *)param->remove_bond_dev_cmpl.bd_addr, sizeof(esp_bd_addr_t));
+ ESP_LOGI(GATTS_TABLE_TAG, "------------------------------------");
break;
}
case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT:
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
+ /* Just show how to clear all the bonded devices
+ * Delay 30s, clear all the bonded devices
+ *
+ * vTaskDelay(30000 / portTICK_PERIOD_MS);
+ * remove_all_bonded_devices();
+ */
}
break;
}
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
- gl_profile_tab[PROFILE_A_APP_ID].descr_handle = param->add_char.attr_handle;
+ gl_profile_tab[PROFILE_A_APP_ID].descr_handle = param->add_char_descr.attr_handle;
ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n",
- param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
+ param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle);
break;
case ESP_GATTS_DELETE_EVT:
break;
NULL, NULL);
break;
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
- gl_profile_tab[PROFILE_B_APP_ID].descr_handle = param->add_char.attr_handle;
+ gl_profile_tab[PROFILE_B_APP_ID].descr_handle = param->add_char_descr.attr_handle;
ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n",
- param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
+ param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle);
break;
case ESP_GATTS_DELETE_EVT:
break;
--- /dev/null
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := gcov_example
+
+include $(IDF_PATH)/make/project.mk
+
+GCOV := $(call dequote,$(CONFIG_TOOLPREFIX))gcov
+REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report
+
+lcov-report:
+ echo "Generating coverage report in: $(REPORT_DIR)"
+ echo "Using gcov: $(GCOV)"
+ mkdir -p $(REPORT_DIR)/html
+ lcov --gcov-tool $(GCOV) -c -d $(BUILD_DIR_BASE) -o $(REPORT_DIR)/$(PROJECT_NAME).info
+ genhtml -o $(REPORT_DIR)/html $(REPORT_DIR)/$(PROJECT_NAME).info
+
+cov-data-clean:
+ echo "Remove coverage data files..."
+ find $(BUILD_DIR_BASE) -name "*.gcda" -exec rm {} +
+ rm -rf $(REPORT_DIR)
+
+.PHONY: lcov-report cov-data-clean
--- /dev/null
+# Blink Example with Coverage Info
+
+See the README.md file in the upper level 'examples' directory for more information about examples.
+
+GCC has useful feature which allows to generate code coverage information. Generated data show how many times every program execution paths has been taken.
+Basing on coverage data developers can detect untested pieces of code and also it gives valuable information about critical (frequently used) execution paths.
+In general case when coverage option is enabled GCC generates additional code to accumulate necessary data and save them into files. File system is not always available
+in ESP32 based projects or size of the file storage can be very limited to keep all the coverage data. To overcome those limitations IDF provides functionality
+to transfer the data to the host and save them on host file system. The data transfer is done via JTAG.
+This example shows how to generate coverage information for the program.
+
+
+## How To Gather Coverage Info
+
+Below are the steps which should be performed to obtain coverage info. Steps 1-3 are already done for this example project. They should be performed if user wants to fork new IDF-based project and needs to collect coverage info.
+
+1. Enable application tracing module in menuconfig. Choose `Trace memory` in `Component config -> Application Level Tracing -> Data Destination`.
+2. Enable coverage info generation for necessary source files. To do this add the following line to the 'component.mk' files of your project:
+`CFLAGS += --coverage`
+It will enable coverage info for all source files of your component. If you need to enable the option only for certain files you need to add the following line for every file of interest:
+`gcov_example.o: CFLAGS += --coverage`
+Replace `gcov_example.o` with path to your file.
+3. Add call to `esp_gcov_dump` function in your program. This function will wait for command from the host and dump coverage data. The exact place where to put call to `esp_gcov_dump` depends on the program.
+Usually it should be placed at the end of the program execution (at exit). See `gcov_example.c` for example.
+4. Build, flash and run program.
+5. Wait until `esp_gcov_dump` is called. To detect this a call to `printf` can be used (see `gcov_example.c`) or, for example, you can use a LED to indicate the readiness to dump data.
+6. Connect OpenOCD to the target and start telnet session with it.
+7. Run the following OpenOCD command:
+`esp32 gcov`
+Example of the command output:
+
+```
+> esp32 gcov
+Total trace memory: 16384 bytes
+Connect targets...
+Target halted. PRO_CPU: PC=0x400D0CDC (active) APP_CPU: PC=0x00000000
+esp32: target state: halted
+Resume targets
+Targets connected.
+Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda'
+Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda'
+Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda'
+Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda'
+Disconnect targets...
+Target halted. PRO_CPU: PC=0x400D17CA (active) APP_CPU: PC=0x400D0CDC
+esp32: target state: halted
+Resume targets
+Targets disconnected.
+>
+```
+
+As shown in the output above there can be errors reported. This is because GCOV code tries to open non-existing coverage data files for reading before writing to them. It is normal situation and actually is not an error.
+GCOV will save coverage data for every source file in directories for corresponding object files, usually under root build directory `build`.
+
+## How To Process Coverage Info
+
+There are several ways to process collected data. Two of the most common are:
+
+1. Using `gcov` tool supplied along with xtensa toolchain. See [GCOV documentation](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) for details.
+2. Using `lcov` and `genhtml` tools. This way allows to generate pretty looking coverage reports in html. This example shows how to add build target to generate such kind of reports.
+Add the following lines to you project's `Makefile` after the line including `project.mk`:
+
+```
+GCOV := $(call dequote,$(CONFIG_TOOLPREFIX))gcov
+REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report
+
+lcov-report:
+ echo "Generating coverage report in: $(REPORT_DIR)"
+ echo "Using gcov: $(GCOV)"
+ mkdir -p $(REPORT_DIR)/html
+ lcov --gcov-tool $(GCOV) -c -d $(BUILD_DIR_BASE) -o $(REPORT_DIR)/$(PROJECT_NAME).info
+ genhtml -o $(REPORT_DIR)/html $(REPORT_DIR)/$(PROJECT_NAME).info
+
+cov-data-clean:
+ echo "Remove coverage data files..."
+ find $(BUILD_DIR_BASE) -name "*.gcda" -exec rm {} +
+ rm -rf $(REPORT_DIR)
+
+.PHONY: lcov-report cov-data-clean
+```
+
+Those lines add two build targets:
+* `lcov-report` - generates html coverage report in `$(BUILD_DIR_BASE)/coverage_report/html` directory.
+* `cov-data-clean` - removes all coverage data files and reports.
+
+To generate report type the following command:
+`make lcov-report`
+
+The sample output of the command is below:
+
+```
+Generating coverage report in: /home/alexey/projects/esp/esp-idf/examples/system/gcov/build/coverage_report
+Using gcov: ~/projects/esp/crosstool-NG/builds/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcov
+Capturing coverage data from /home/alexey/projects/esp/esp-idf/examples/system/gcov/build
+Found gcov version: 5.2.0
+Scanning /home/alexey/projects/esp/esp-idf/examples/system/gcov/build for .gcda files ...
+Found 2 data files in /home/alexey/projects/esp/esp-idf/examples/system/gcov/build
+Processing main/gcov_example_func.gcda
+Processing main/gcov_example.gcda
+Finished .info-file creation
+Reading data file /home/alexey/projects/esp/esp-idf/examples/system/gcov/build/coverage_report/gcov_example.info
+Found 2 entries.
+Found common filename prefix "/home/alexey/projects/esp/esp-idf/examples/system/gcov"
+Writing .css and .png files.
+Generating output.
+Processing file main/gcov_example.c
+Processing file main/gcov_example_func.c
+Writing directory view page.
+Overall coverage rate:
+ lines......: 90.0% (18 of 20 lines)
+ functions..: 100.0% (3 of 3 functions)
+```
\ No newline at end of file
--- /dev/null
+menu "Example Configuration"
+
+config BLINK_GPIO
+ int "Blink GPIO number"
+ range 0 34
+ default 5
+ help
+ GPIO number (IOxx) to blink on and off.
+
+ Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
+
+ GPIOs 35-39 are input-only so cannot be used as outputs.
+
+endmenu
--- /dev/null
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+
+CFLAGS += --coverage
--- /dev/null
+/* Blink Example with covergae info
+
+ This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+ Unless required by applicable law or agreed to in writing, this
+ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/gpio.h"
+#include "esp_app_trace.h"
+#include "sdkconfig.h"
+
+/* Can run 'make menuconfig' to choose the GPIO to blink,
+ or you can edit the following line and set a number here.
+*/
+#define BLINK_GPIO CONFIG_BLINK_GPIO
+
+void blink_dummy_func(void);
+
+void blink_task(void *pvParameter)
+{
+ int dump_gcov_after = 2;
+ /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
+ muxed to GPIO on reset already, but some default to other
+ functions and need to be switched to GPIO. Consult the
+ Technical Reference for a list of pads and their default
+ functions.)
+ */
+ gpio_pad_select_gpio(BLINK_GPIO);
+ /* Set the GPIO as a push/pull output */
+ gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
+ while(dump_gcov_after-- > 0) {
+ /* Blink off (output low) */
+ gpio_set_level(BLINK_GPIO, 0);
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+ /* Blink on (output high) */
+ gpio_set_level(BLINK_GPIO, 1);
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+ blink_dummy_func();
+ }
+
+ // Dump gcov data
+ printf("Ready to dump GCOV data...\n");
+ esp_gcov_dump();
+ printf("GCOV data have been dumped.\n");
+ while(1);
+}
+
+void app_main()
+{
+ xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
+}
--- /dev/null
+#include <stdio.h>
+
+
+void blink_dummy_func(void)
+{
+ static int i;
+ printf("Counter = %d\n", i++);
+}
+
--- /dev/null
+CONFIG_ESP32_APPTRACE_DEST_TRAX=y
+# CONFIG_ESP32_APPTRACE_DEST_NONE is not set
+CONFIG_ESP32_APPTRACE_ENABLE=y
+CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
+CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1
+CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH=0
+CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX=0
endif
# The project Makefile can define a list of components, but if it does not do this we just take all available components
-# in the component dirs. A component is COMPONENT_DIRS directory, or immediate subdirectory,
+# in the component dirs. A component is COMPONENT_DIRS directory, or immediate subdirectory,
# which contains a component.mk file.
#
# Use the "make list-components" target to debug this step.
$(COMPONENT_LDFLAGS) \
-lgcc \
-lstdc++ \
+ -lgcov \
-Wl,--end-group \
-Wl,-EL