1 /*
2 * Copyright (C) 2017 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
21 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32 #define BTSTACK_FILE__ "btstack_tlv_esp32.c"
33
34 #include "btstack_tlv.h"
35 #include "btstack_util.h"
36 #include "btstack_debug.h"
37
38 #include "esp_system.h"
39 #include "nvs_flash.h"
40 #include "nvs.h"
41
42 #include <inttypes.h>
43 #include <string.h>
44
45 static nvs_handle the_nvs_handle;
46 static int nvs_active;
47
48 // @param buffer char array of size 9
key_for_tag(uint32_t tag,char * key_buffer)49 static void key_for_tag(uint32_t tag, char * key_buffer){
50 int i;
51 for (i=0;i<8;i++){
52 key_buffer[i] = char_for_nibble( (tag >> (4*(7-i))) & 0x0f);
53 }
54 key_buffer[i] = 0;
55 }
56
57 /**
58 * Get Value for Tag
59 * @param tag
60 * @param buffer
61 * @param buffer_size
62 * @returns size of value
63 */
btstack_tlv_esp32_get_tag(void * context,uint32_t tag,uint8_t * buffer,uint32_t buffer_size)64 static int btstack_tlv_esp32_get_tag(void * context, uint32_t tag, uint8_t * buffer, uint32_t buffer_size){
65 if (!nvs_active) return 0;
66 char key_buffer[9];
67 key_for_tag(tag, key_buffer);
68 log_debug("read tag %s", key_buffer);
69 size_t size = 0;
70 esp_err_t err = nvs_get_blob(the_nvs_handle, key_buffer, NULL, &size);
71 switch (err) {
72 case ESP_OK:
73 if (size > buffer_size){
74 log_error("buffer_size %" PRIu32 " < value size %zu", buffer_size, size);
75 return 0;
76 }
77 nvs_get_blob(the_nvs_handle, key_buffer, buffer, &size);
78 return size;
79 case ESP_ERR_NVS_NOT_FOUND:
80 break;
81 default :
82 log_error("Error (0x%04x) reading %s!\n", err, key_buffer);
83 break;
84 }
85 return 0;
86 }
87
88 /**
89 * Store Tag
90 * @param tag
91 * @param data
92 * @param data_size
93 */
btstack_tlv_esp32_store_tag(void * context,uint32_t tag,const uint8_t * data,uint32_t data_size)94 static int btstack_tlv_esp32_store_tag(void * context, uint32_t tag, const uint8_t * data, uint32_t data_size){
95 if (!nvs_active) return 0;
96 char key_buffer[9];
97 key_for_tag(tag, key_buffer);
98 log_info("store tag %s", key_buffer);
99 esp_err_t err = nvs_set_blob(the_nvs_handle, key_buffer, data, data_size);
100 if (err != ESP_OK){
101 log_error("Error (0x%04x) nvs_set_blob %s!", err, key_buffer);
102 return 1;
103 }
104 err = nvs_commit(the_nvs_handle);
105 if (err != ESP_OK){
106 log_error("Error (0x%04x) nvs_commit %s!", err, key_buffer);
107 return 1;
108 }
109 return 0;
110 }
111
112 /**
113 * Delete Tag
114 * @param tag
115 */
btstack_tlv_esp32_delete_tag(void * context,uint32_t tag)116 static void btstack_tlv_esp32_delete_tag(void * context, uint32_t tag){
117 if (!nvs_active) return;
118 char key_buffer[9];
119 key_for_tag(tag, key_buffer);
120 log_info("delete tag %s", key_buffer);
121 esp_err_t err = nvs_erase_key(the_nvs_handle, key_buffer);
122 switch (err) {
123 case ESP_OK:
124 case ESP_ERR_NVS_NOT_FOUND:
125 break;
126 break;
127 default :
128 log_error("Error (0x%04x) deleting reading %s!\n", err, key_buffer);
129 break;
130 }
131 }
132
133 static const btstack_tlv_t btstack_tlv_esp32 = {
134 /* int (*get_tag)(..); */ &btstack_tlv_esp32_get_tag,
135 /* int (*store_tag)(..); */ &btstack_tlv_esp32_store_tag,
136 /* void (*delete_tag)(v..); */ &btstack_tlv_esp32_delete_tag,
137 };
138
139 /**
140 * Init Tag Length Value Store
141 */
btstack_tlv_esp32_get_instance(void)142 const btstack_tlv_t * btstack_tlv_esp32_get_instance(void){
143 // Initialize NVS
144 esp_err_t err = nvs_flash_init();
145 if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
146 log_info("Error (0x%04x) init flash", err);
147 // NVS partition was truncated and needs to be erased
148 // Retry nvs_flash_init
149 ESP_ERROR_CHECK(nvs_flash_erase());
150 err = nvs_flash_init();
151 }
152 ESP_ERROR_CHECK( err );
153 err = nvs_open("BTstack", NVS_READWRITE, &the_nvs_handle);
154 if (err == ESP_OK) {
155 nvs_active = 1;
156 } else {
157 log_info("Error (0x%04x) open flash 'BTstack' section", err);
158 nvs_active = 0;
159 }
160 return &btstack_tlv_esp32;
161 }
162
163