1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 #include <string.h>
9 
10 #include <zephyr/kernel.h>
11 
12 #include <zephyr/logging/log.h>
13 
14 #include "babblekit/testcase.h"
15 
16 LOG_MODULE_REGISTER(bt_settings_hook, LOG_LEVEL_DBG);
17 
18 struct settings_list_node {
19 	sys_snode_t node;
20 	char *key;
21 };
22 
23 static K_MUTEX_DEFINE(settings_list_mutex);
24 static atomic_t settings_record_enabled = ATOMIC_INIT(0);
25 
26 static sys_slist_t settings_list = SYS_SLIST_STATIC_INIT(settings_list);
27 
add_key(const char * key)28 static void add_key(const char *key)
29 {
30 	struct settings_list_node *new_node;
31 	size_t key_size = strlen(key);
32 	bool key_already_in = false;
33 
34 	struct settings_list_node *loop_node;
35 
36 	if (settings_record_enabled == 1) {
37 		k_mutex_lock(&settings_list_mutex, K_FOREVER);
38 
39 		SYS_SLIST_FOR_EACH_CONTAINER(&settings_list, loop_node, node) {
40 			if (strcmp(loop_node->key, key) == 0) {
41 				key_already_in = true;
42 			}
43 		}
44 
45 		if (!key_already_in) {
46 			new_node = k_malloc(sizeof(struct settings_list_node));
47 			TEST_ASSERT(new_node != NULL, "Failed to malloc new_node");
48 
49 			new_node->key = k_malloc(sizeof(char) * key_size);
50 			TEST_ASSERT(new_node->key != NULL, "Failed to malloc new_node->key");
51 
52 			memcpy(new_node->key, key, sizeof(char) * key_size);
53 
54 			sys_slist_append(&settings_list, &new_node->node);
55 		}
56 
57 		k_mutex_unlock(&settings_list_mutex);
58 	}
59 }
60 
remove_key(const char * key)61 static void remove_key(const char *key)
62 {
63 	struct settings_list_node *loop_node, *prev_loop_node;
64 
65 	prev_loop_node = NULL;
66 
67 	if (settings_record_enabled == 1) {
68 		k_mutex_lock(&settings_list_mutex, K_FOREVER);
69 
70 		SYS_SLIST_FOR_EACH_CONTAINER(&settings_list, loop_node, node) {
71 			if (strcmp(loop_node->key, key) == 0) {
72 				break;
73 			}
74 
75 			prev_loop_node = loop_node;
76 		}
77 
78 		if (loop_node != NULL) {
79 			sys_slist_remove(&settings_list, &prev_loop_node->node, &loop_node->node);
80 
81 			k_free(loop_node->key);
82 			k_free(loop_node);
83 		}
84 
85 		k_mutex_unlock(&settings_list_mutex);
86 	}
87 }
88 
start_settings_record(void)89 void start_settings_record(void)
90 {
91 	atomic_set(&settings_record_enabled, 1);
92 }
93 
stop_settings_record(void)94 void stop_settings_record(void)
95 {
96 	atomic_set(&settings_record_enabled, 0);
97 }
98 
settings_list_cleanup(void)99 void settings_list_cleanup(void)
100 {
101 	struct settings_list_node *loop_node, *next_loop_node, *prev_loop_node;
102 
103 	prev_loop_node =  NULL;
104 
105 	k_mutex_lock(&settings_list_mutex, K_FOREVER);
106 
107 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&settings_list, loop_node, next_loop_node, node) {
108 		sys_slist_remove(&settings_list, &prev_loop_node->node, &loop_node->node);
109 
110 		k_free(loop_node->key);
111 		k_free(loop_node);
112 	}
113 
114 	k_mutex_unlock(&settings_list_mutex);
115 }
116 
get_settings_list_size(void)117 int get_settings_list_size(void)
118 {
119 	struct settings_list_node *loop_node;
120 	int number_of_settings = 0;
121 
122 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_list, loop_node, node) {
123 		LOG_ERR("Setting registered: %s", loop_node->key);
124 		number_of_settings += 1;
125 	}
126 
127 	return number_of_settings;
128 }
129 
bt_testing_settings_store_hook(const char * key,const void * value,size_t val_len)130 void bt_testing_settings_store_hook(const char *key, const void *value, size_t val_len)
131 {
132 	LOG_DBG("Store: %s", key);
133 	LOG_HEXDUMP_DBG(value, val_len, "Data:");
134 
135 	add_key(key);
136 }
137 
bt_testing_settings_delete_hook(const char * key)138 void bt_testing_settings_delete_hook(const char *key)
139 {
140 	LOG_DBG("Delete: %s", key);
141 
142 	remove_key(key);
143 }
144