fix(ble): Fixed AI review bugs in bt common

This commit is contained in:
zhiweijian
2026-05-12 15:59:04 +08:00
parent fae52f14e8
commit 1c312d0b33
20 changed files with 676 additions and 188 deletions
+14 -3
View File
@@ -323,9 +323,20 @@ bool osi_alarm_is_active(osi_alarm_t *alarm)
{
assert(alarm != NULL);
if (alarm->alarm_hdl != NULL) {
return esp_timer_is_active(alarm->alarm_hdl);
assert(alarm_mutex != NULL);
bool active = false;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
active = false;
goto end;
}
return false;
if (alarm->alarm_hdl != NULL) {
active = esp_timer_is_active(alarm->alarm_hdl);
}
end:
osi_mutex_unlock(&alarm_mutex);
return active;
}
+137 -54
View File
@@ -16,6 +16,7 @@
#include <string.h>
#include "bt_common.h"
#include "esp_assume.h"
#include "osi/allocator.h"
#include "osi/config.h"
#include "osi/list.h"
@@ -40,7 +41,7 @@ struct config_t {
// Empty definition; this type is aliased to list_node_t.
struct config_section_iter_t {};
static void config_parse(nvs_handle_t fp, config_t *config);
static bool config_parse(nvs_handle_t fp, config_t *config);
static section_t *section_new(const char *name);
static void section_free(void *ptr);
@@ -94,8 +95,12 @@ config_t *config_new(const char *filename)
return NULL;
}
config_parse(fp, config);
bool ok = config_parse(fp, config);
nvs_close(fp);
if (!ok) {
config_free(config);
return NULL;
}
return config;
}
@@ -136,7 +141,7 @@ bool config_has_key_in_section(config_t *config, const char *key, char *key_valu
entry_t *entry = list_node(node);
OSI_TRACE_DEBUG("entry->key = %s, entry->value = %s", entry->key, entry->value);
if (!strcmp(entry->key, key) && !strcmp(entry->value, key_value)) {
OSI_TRACE_DEBUG("%s, the irk aready in the flash.", __func__);
OSI_TRACE_DEBUG("%s, the irk already in the flash.", __func__);
return true;
}
}
@@ -221,6 +226,10 @@ void config_set_string(config_t *config, const char *section, const char *key, c
section_t *sec = section_find(config, section);
if (!sec) {
sec = section_new(section);
if (sec == NULL) {
OSI_TRACE_ERROR("%s unable to allocate section\n", __func__);
return;
}
if (insert_back) {
list_append(config->sections, sec);
} else {
@@ -231,13 +240,22 @@ void config_set_string(config_t *config, const char *section, const char *key, c
for (const list_node_t *node = list_begin(sec->entries); node != list_end(sec->entries); node = list_next(node)) {
entry_t *entry = list_node(node);
if (!strcmp(entry->key, key)) {
char *new_value = osi_strdup(value);
if (new_value == NULL) {
OSI_TRACE_ERROR("%s unable to allocate entry value\n", __func__);
return;
}
osi_free(entry->value);
entry->value = osi_strdup(value);
entry->value = new_value;
return;
}
}
entry_t *entry = entry_new(key, value);
if (entry == NULL) {
OSI_TRACE_ERROR("%s unable to allocate entry\n", __func__);
return;
}
list_append(sec->entries, entry);
}
@@ -327,32 +345,57 @@ const char *config_section_name(const config_section_node_t *node)
return section->name;
}
static int get_config_size(const config_t *config)
static bool get_config_size(const config_t *config, size_t *out_size)
{
assert(config != NULL);
assert(out_size != NULL);
int w_len = 0, total_size = 0;
size_t total_size = 0;
for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) {
const section_t *section = (const section_t *)list_node(node);
w_len = strlen(section->name) + strlen("[]\n");// format "[section->name]\n"
/* CONTRACT / PRECONDITION:
* - section->name is guaranteed non-NULL.
* - Upstream guard: section_new() stores osi_strdup(name) from config_set_string().
*/
ESP_ASSUME_NONNULL(section->name);
size_t w_len = strlen(section->name) + strlen("[]\n"); // format "[section->name]\n"
if (total_size > SIZE_MAX - w_len) {
return false;
}
total_size += w_len;
for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) {
const entry_t *entry = (const entry_t *)list_node(enode);
w_len = strlen(entry->key) + strlen(entry->value) + strlen(" = \n");// format "entry->key = entry->value\n"
/* CONTRACT / PRECONDITION:
* - entry->key/value are guaranteed non-NULL.
* - Upstream guard: entry_new() stores osi_strdup(key/value) from config_set_string().
*/
ESP_ASSUME_NONNULL(entry->key);
ESP_ASSUME_NONNULL(entry->value);
w_len = strlen(entry->key) + strlen(entry->value) + strlen(" = \n"); // format "entry->key = entry->value\n"
if (total_size > SIZE_MAX - w_len) {
return false;
}
total_size += w_len;
}
// Only add a separating newline if there are more sections.
if (list_next(node) != list_end(config->sections)) {
total_size ++; //'\n'
if (total_size == SIZE_MAX) {
return false;
}
total_size++; // '\n'
} else {
break;
}
}
total_size ++; //'\0'
return total_size;
if (total_size == SIZE_MAX) {
return false;
}
total_size++; // '\0'
*out_size = total_size;
return true;
}
static int get_config_size_from_flash(nvs_handle_t fp)
@@ -364,7 +407,7 @@ static int get_config_size_from_flash(nvs_handle_t fp)
char *keyname = osi_calloc(keyname_bufsz);
if (!keyname){
OSI_TRACE_ERROR("%s, malloc error\n", __func__);
return 0;
return -1;
}
size_t length = CONFIG_FILE_DEFAULE_LENGTH;
size_t total_length = 0;
@@ -378,7 +421,7 @@ static int get_config_size_from_flash(nvs_handle_t fp)
if (err != ESP_OK) {
OSI_TRACE_ERROR("%s, error %d\n", __func__, err);
osi_free(keyname);
return 0;
return -2;
}
total_length += length;
while (length == CONFIG_FILE_MAX_SIZE) {
@@ -392,7 +435,7 @@ static int get_config_size_from_flash(nvs_handle_t fp)
if (err != ESP_OK) {
OSI_TRACE_ERROR("%s, error %d\n", __func__, err);
osi_free(keyname);
return 0;
return -3;
}
total_length += length;
}
@@ -409,12 +452,21 @@ bool config_save(const config_t *config, const char *filename)
esp_err_t err;
int err_code = 0;
nvs_handle_t fp;
char *line = osi_calloc(1024);
char *buf = NULL;
bool nvs_opened = false;
const size_t keyname_bufsz = sizeof(CONFIG_KEY) + 5 + 1; // including log10(sizeof(i))
char *keyname = osi_calloc(keyname_bufsz);
int config_size = get_config_size(config);
char *buf = osi_calloc(config_size);
if (!line || !buf || !keyname) {
if (!keyname) {
err_code |= 0x01;
goto error;
}
size_t config_size = 0;
if (!get_config_size(config, &config_size) || config_size == 0) {
err_code |= 0x01;
goto error;
}
buf = osi_calloc(config_size);
if (!buf) {
err_code |= 0x01;
goto error;
}
@@ -428,63 +480,67 @@ bool config_save(const config_t *config, const char *filename)
err_code |= 0x02;
goto error;
}
nvs_opened = true;
int w_cnt, w_cnt_total = 0;
int w_cnt;
size_t w_cnt_total = 0;
for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) {
const section_t *section = (const section_t *)list_node(node);
w_cnt = snprintf(line, 1024, "[%s]\n", section->name);
if(w_cnt < 0) {
OSI_TRACE_ERROR("snprintf error w_cnt %d.",w_cnt);
err_code |= 0x10;
goto error;
}
if(w_cnt_total + w_cnt > config_size) {
OSI_TRACE_ERROR("%s, memcpy size (w_cnt + w_cnt_total = %d) is larger than buffer size (config_size = %d).", __func__, (w_cnt + w_cnt_total), config_size);
size_t remaining = (w_cnt_total < config_size) ? (config_size - w_cnt_total) : 0;
if (remaining == 0) {
err_code |= 0x20;
goto error;
}
OSI_TRACE_DEBUG("section name: %s, w_cnt + w_cnt_total = %d\n", section->name, w_cnt + w_cnt_total);
memcpy(buf + w_cnt_total, line, w_cnt);
w_cnt_total += w_cnt;
w_cnt = snprintf(buf + w_cnt_total, remaining, "[%s]\n", section->name);
if (w_cnt < 0 || (size_t)w_cnt >= remaining) {
err_code |= 0x20;
goto error;
}
OSI_TRACE_DEBUG("section name: %s, w_cnt + w_cnt_total = %d\n", section->name, (int)(w_cnt + w_cnt_total));
w_cnt_total += (size_t)w_cnt;
for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) {
const entry_t *entry = (const entry_t *)list_node(enode);
OSI_TRACE_DEBUG("(key, val): (%s, %s)\n", entry->key, entry->value);
w_cnt = snprintf(line, 1024, "%s = %s\n", entry->key, entry->value);
if(w_cnt < 0) {
OSI_TRACE_ERROR("snprintf error w_cnt %d.",w_cnt);
err_code |= 0x10;
goto error;
}
if(w_cnt_total + w_cnt > config_size) {
OSI_TRACE_ERROR("%s, memcpy size (w_cnt + w_cnt_total = %d) is larger than buffer size.(config_size = %d)", __func__, (w_cnt + w_cnt_total), config_size);
remaining = (w_cnt_total < config_size) ? (config_size - w_cnt_total) : 0;
if (remaining == 0) {
err_code |= 0x20;
goto error;
}
OSI_TRACE_DEBUG("%s, w_cnt + w_cnt_total = %d", __func__, w_cnt + w_cnt_total);
memcpy(buf + w_cnt_total, line, w_cnt);
w_cnt_total += w_cnt;
w_cnt = snprintf(buf + w_cnt_total, remaining, "%s = %s\n", entry->key, entry->value);
if (w_cnt < 0 || (size_t)w_cnt >= remaining) {
err_code |= 0x20;
goto error;
}
OSI_TRACE_DEBUG("%s, w_cnt + w_cnt_total = %d", __func__, (int)(w_cnt + w_cnt_total));
w_cnt_total += (size_t)w_cnt;
}
// Only add a separating newline if there are more sections.
if (list_next(node) != list_end(config->sections)) {
buf[w_cnt_total] = '\n';
w_cnt_total += 1;
if (w_cnt_total + 1 >= config_size) {
err_code |= 0x20;
goto error;
}
buf[w_cnt_total++] = '\n';
} else {
break;
}
}
if (w_cnt_total >= config_size) {
err_code |= 0x20;
goto error;
}
buf[w_cnt_total] = '\0';
if (w_cnt_total < CONFIG_FILE_MAX_SIZE) {
snprintf(keyname, keyname_bufsz, "%s%d", CONFIG_KEY, 0);
err = nvs_set_blob(fp, keyname, buf, w_cnt_total);
if (err != ESP_OK) {
nvs_close(fp);
err_code |= 0x04;
goto error;
}
}else {
int count = (w_cnt_total / CONFIG_FILE_MAX_SIZE);
int count = (int)(w_cnt_total / CONFIG_FILE_MAX_SIZE);
assert(count <= 0xFF);
for (uint8_t i = 0; i <= count; i++)
{
@@ -497,7 +553,6 @@ bool config_save(const config_t *config, const char *filename)
OSI_TRACE_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, CONFIG_FILE_MAX_SIZE);
}
if (err != ESP_OK) {
nvs_close(fp);
err_code |= 0x04;
goto error;
}
@@ -506,24 +561,23 @@ bool config_save(const config_t *config, const char *filename)
err = nvs_commit(fp);
if (err != ESP_OK) {
nvs_close(fp);
err_code |= 0x08;
goto error;
}
nvs_close(fp);
osi_free(line);
nvs_opened = false;
osi_free(buf);
osi_free(keyname);
return true;
error:
if (nvs_opened) {
nvs_close(fp);
}
if (buf) {
osi_free(buf);
}
if (line) {
osi_free(line);
}
if (keyname) {
osi_free(keyname);
}
@@ -552,7 +606,7 @@ static char *trim(char *str)
return str;
}
static void config_parse(nvs_handle_t fp, config_t *config)
static bool config_parse(nvs_handle_t fp, config_t *config)
{
assert(fp != 0);
assert(config != NULL);
@@ -570,9 +624,14 @@ static void config_parse(nvs_handle_t fp, config_t *config)
int buf_size = get_config_size_from_flash(fp);
char *buf = NULL;
if(buf_size == 0) { //First use nvs
if (buf_size < 0) {
err_code |= 0x04;
goto error;
}
if(buf_size == 0) { //First use nvs
goto ok;
}
buf = osi_calloc(buf_size);
if (!line || !section || !buf || !keyname) {
err_code |= 0x01;
@@ -581,7 +640,7 @@ static void config_parse(nvs_handle_t fp, config_t *config)
snprintf(keyname, keyname_bufsz, "%s%d", CONFIG_KEY, 0);
err = nvs_get_blob(fp, keyname, buf, &length);
if (err == ESP_ERR_NVS_NOT_FOUND) {
goto error;
goto ok;
}
if (err != ESP_OK) {
err_code |= 0x02;
@@ -644,6 +703,21 @@ static void config_parse(nvs_handle_t fp, config_t *config)
}
}
ok:
if (buf) {
osi_free(buf);
}
if (line) {
osi_free(line);
}
if (section) {
osi_free(section);
}
if (keyname) {
osi_free(keyname);
}
return true;
error:
if (buf) {
osi_free(buf);
@@ -660,6 +734,7 @@ error:
if (err_code) {
OSI_TRACE_ERROR("%s returned with err code: %d\n", __func__, err_code);
}
return false;
}
static section_t *section_new(const char *name)
@@ -671,6 +746,10 @@ static section_t *section_new(const char *name)
section->name = osi_strdup(name);
section->entries = list_new(entry_free);
if (section->name == NULL || section->entries == NULL) {
section_free(section);
return NULL;
}
return section;
}
@@ -707,6 +786,10 @@ static entry_t *entry_new(const char *key, const char *value)
entry->key = osi_strdup(key);
entry->value = osi_strdup(value);
if (entry->key == NULL || entry->value == NULL) {
entry_free(entry);
return NULL;
}
return entry;
}
+7
View File
@@ -22,6 +22,7 @@
#include "osi/osi.h"
#include "osi/mutex.h"
#include "osi/semaphore.h"
#include "esp_assume.h"
typedef struct fixed_queue_t {
@@ -43,6 +44,12 @@ fixed_queue_t *fixed_queue_new(size_t capacity)
}
osi_mutex_new(&ret->lock);
/* CONTRACT / PRECONDITION:
* - ret->lock is guaranteed non-NULL after successful osi_mutex_new().
* - Rationale: treat mutex allocation failure as fatal in debug builds;
* release builds do not add extra code size.
*/
ESP_ASSUME_NONNULL(ret->lock);
ret->capacity = capacity;
ret->list = list_new(NULL);
+24 -13
View File
@@ -138,26 +138,37 @@ bool hash_map_set(hash_map_t *hash_map, const void *key, void *data)
}
list_t *hash_bucket_list = hash_map->bucket[hash_key].list;
hash_map_entry_t *hash_map_entry = find_bucket_entry_(hash_bucket_list, key);
/* Allocate the new entry FIRST, before touching any existing entry.
* This preserves the atomicity of hash_map_set: on failure the map
* stays exactly as it was, and the caller's previously-stored
* key/data remain valid. */
hash_map_entry_t *new_entry = osi_calloc(sizeof(hash_map_entry_t));
if (new_entry == NULL) {
return false;
}
new_entry->key = key;
new_entry->data = data;
new_entry->hash_map = hash_map;
if (hash_map_entry) {
// Calls hash_map callback to delete the hash_map_entry.
bool rc = list_remove(hash_bucket_list, hash_map_entry);
hash_map_entry_t *old_entry = find_bucket_entry_(hash_bucket_list, key);
if (!list_append(hash_bucket_list, new_entry)) {
osi_free(new_entry);
return false;
}
/* Only after the new entry has been successfully inserted do we
* destroy the old one (which frees the previous key/data via
* bucket_free_). For a brand-new key, bump hash_size instead. */
if (old_entry) {
bool rc = list_remove(hash_bucket_list, old_entry);
assert(rc == true);
(void)rc;
} else {
hash_map->hash_size++;
}
hash_map_entry = osi_calloc(sizeof(hash_map_entry_t));
if (hash_map_entry == NULL) {
return false;
}
hash_map_entry->key = key;
hash_map_entry->data = data;
hash_map_entry->hash_map = hash_map;
return list_append(hash_bucket_list, hash_map_entry);
return true;
}
bool hash_map_erase(hash_map_t *hash_map, const void *key)
+8 -4
View File
@@ -181,8 +181,9 @@ bool list_remove(list_t *list, void *data)
}
if (list->head->data == data) {
const bool was_tail = (list->tail == list->head);
list_node_t *next = list_free_node(list, list->head);
if (list->tail == list->head) {
if (was_tail) {
list->tail = next;
}
list->head = next;
@@ -191,8 +192,9 @@ bool list_remove(list_t *list, void *data)
for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
if (node->data == data) {
const bool was_tail = (list->tail == node);
prev->next = list_free_node(list, node);
if (list->tail == node) {
if (was_tail) {
list->tail = prev;
}
return true;
@@ -211,8 +213,9 @@ bool list_delete(list_t *list, void *data)
}
if (list->head->data == data) {
const bool was_tail = (list->tail == list->head);
list_node_t *next = list_delete_node(list, list->head);
if (list->tail == list->head) {
if (was_tail) {
list->tail = next;
}
list->head = next;
@@ -221,8 +224,9 @@ bool list_delete(list_t *list, void *data)
for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
if (node->data == data) {
const bool was_tail = (list->tail == node);
prev->next = list_delete_node(list, node);
if (list->tail == node) {
if (was_tail) {
list->tail = prev;
}
return true;
+8
View File
@@ -16,6 +16,8 @@
*
******************************************************************************/
#include <assert.h>
#include "osi/mutex.h"
@@ -90,15 +92,21 @@ int osi_mutex_global_init(void)
void osi_mutex_global_deinit(void)
{
if (gl_mutex == NULL) {
return;
}
vSemaphoreDelete(gl_mutex);
gl_mutex = NULL;
}
void osi_mutex_global_lock(void)
{
assert(gl_mutex != NULL);
xSemaphoreTakeRecursive(gl_mutex, portMAX_DELAY);
}
void osi_mutex_global_unlock(void)
{
assert(gl_mutex != NULL);
xSemaphoreGiveRecursive(gl_mutex);
}