1#!/usr/bin/env python3 2import os 3import sys 4 5import os 6import sys 7 8copyright = """/* 9 * Copyright (C) 2014 BlueKitchen GmbH 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the copyright holders nor the names of 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 4. Any redistribution, use, or modification is done solely for 24 * personal benefit and not for any commercial purpose or for 25 * monetary gain. 26 * 27 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 31 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 34 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 37 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * Please inquire about commercial licensing options at 41 * [email protected] 42 * 43 */ 44""" 45 46hfile_header_begin = """ 47 48/* 49 * btstack_memory.h 50 * 51 * @brief BTstack memory management via configurable memory pools 52 * 53 */ 54 55#ifndef BTSTACK_MEMORY_H 56#define BTSTACK_MEMORY_H 57 58#if defined __cplusplus 59extern "C" { 60#endif 61 62#include "btstack_config.h" 63 64// Core 65#include "hci.h" 66#include "l2cap.h" 67 68// Classic 69#include "classic/bnep.h" 70#include "classic/hfp.h" 71#include "classic/btstack_link_key_db.h" 72#include "classic/btstack_link_key_db_memory.h" 73#include "classic/rfcomm.h" 74#include "classic/sdp_server.h" 75#include "classic/avdtp_sink.h" 76#include "classic/avdtp_source.h" 77#include "classic/avrcp.h" 78 79// BLE 80#ifdef ENABLE_BLE 81#include "ble/gatt_client.h" 82#include "ble/sm.h" 83#endif 84 85#ifdef ENABLE_MESH 86#include "mesh/mesh_network.h" 87#include "mesh/mesh_keys.h" 88#include "mesh/mesh_virtual_addresses.h" 89#endif 90 91/* API_START */ 92 93/** 94 * @brief Initializes BTstack memory pools. 95 */ 96void btstack_memory_init(void); 97 98/** 99 * @brief Deinitialize BTstack memory pools 100 * @note if HAVE_MALLOC is defined, all previously allocated buffers are free'd 101 */ 102void btstack_memory_deinit(void); 103 104/* API_END */ 105""" 106 107hfile_header_end = """ 108#if defined __cplusplus 109} 110#endif 111 112#endif // BTSTACK_MEMORY_H 113""" 114 115cfile_header_begin = """ 116#define BTSTACK_FILE__ "btstack_memory.c" 117 118 119/* 120 * btstack_memory.c 121 * 122 * @brief BTstack memory management via configurable memory pools 123 * 124 * @note code generated by tool/btstack_memory_generator.py 125 * @note returnes buffers are initialized with 0 126 * 127 */ 128 129#include "btstack_memory.h" 130#include "btstack_memory_pool.h" 131#include "btstack_debug.h" 132 133#include <stdlib.h> 134 135#ifdef HAVE_MALLOC 136typedef struct btstack_memory_buffer { 137 struct btstack_memory_buffer * next; 138 struct btstack_memory_buffer * prev; 139} btstack_memory_buffer_t; 140 141static btstack_memory_buffer_t * btstack_memory_malloc_buffers; 142 143static void btstack_memory_tracking_add(btstack_memory_buffer_t * buffer){ 144 btstack_assert(buffer != NULL); 145 btstack_memory_malloc_buffers = buffer; 146 buffer->prev = NULL; 147 buffer->next = btstack_memory_malloc_buffers; 148 btstack_memory_malloc_buffers = buffer; 149} 150 151static void btstack_memory_tracking_remove(btstack_memory_buffer_t * buffer){ 152 btstack_assert(buffer != NULL); 153 if (buffer->prev == NULL){ 154 // first item 155 btstack_memory_malloc_buffers = buffer->next; 156 } else { 157 buffer->prev->next = buffer->next; 158 } 159 if (buffer->next != NULL){ 160 buffer->next->prev = buffer->prev; 161 } 162} 163#endif 164 165void btstack_memory_deinit(void){ 166#ifdef HAVE_MALLOC 167 while (btstack_memory_malloc_buffers != NULL){ 168 btstack_memory_buffer_t * buffer = btstack_memory_malloc_buffers; 169 btstack_memory_malloc_buffers = buffer->next; 170 free(buffer); 171 } 172#endif 173} 174""" 175 176header_template = """STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void); 177void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME);""" 178 179code_template = """ 180// MARK: STRUCT_TYPE 181#if !defined(HAVE_MALLOC) && !defined(POOL_COUNT) 182 #if defined(POOL_COUNT_OLD_NO) 183 #error "Deprecated POOL_COUNT_OLD_NO defined instead of POOL_COUNT. Please update your btstack_config.h to use POOL_COUNT." 184 #else 185 #define POOL_COUNT 0 186 #endif 187#endif 188 189#ifdef POOL_COUNT 190#if POOL_COUNT > 0 191static STRUCT_TYPE STRUCT_NAME_storage[POOL_COUNT]; 192static btstack_memory_pool_t STRUCT_NAME_pool; 193STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 194 void * buffer = btstack_memory_pool_get(&STRUCT_NAME_pool); 195 if (buffer){ 196 memset(buffer, 0, sizeof(STRUCT_TYPE)); 197 } 198 return (STRUCT_NAME_t *) buffer; 199} 200void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 201 btstack_memory_pool_free(&STRUCT_NAME_pool, STRUCT_NAME); 202} 203#else 204STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 205 return NULL; 206} 207void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 208 UNUSED(STRUCT_NAME); 209}; 210#endif 211#elif defined(HAVE_MALLOC) 212 213typedef struct { 214 STRUCT_NAME_t data; 215 btstack_memory_buffer_t tracking; 216} btstack_memory_STRUCT_NAME_t; 217 218STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 219 btstack_memory_STRUCT_NAME_t * buffer = (btstack_memory_STRUCT_NAME_t *) malloc(sizeof(btstack_memory_STRUCT_NAME_t)); 220 if (buffer){ 221 memset(buffer, 0, sizeof(STRUCT_NAME_t)); 222 btstack_memory_tracking_add(&buffer->tracking); 223 return &buffer->data; 224 } else { 225 return NULL; 226 } 227} 228void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 229 btstack_memory_STRUCT_NAME_t * buffer = (btstack_memory_STRUCT_NAME_t *) STRUCT_NAME; 230 btstack_memory_tracking_remove(&buffer->tracking); 231 free(buffer); 232} 233#endif 234""" 235 236init_template = """#if POOL_COUNT > 0 237 btstack_memory_pool_create(&STRUCT_NAME_pool, STRUCT_NAME_storage, POOL_COUNT, sizeof(STRUCT_TYPE)); 238#endif""" 239 240def writeln(f, data): 241 f.write(data + "\n") 242 243def replacePlaceholder(template, struct_name): 244 struct_type = struct_name + '_t' 245 if struct_name.endswith('try'): 246 pool_count = "MAX_NR_" + struct_name.upper()[:-3] + "TRIES" 247 else: 248 pool_count = "MAX_NR_" + struct_name.upper() + "S" 249 pool_count_old_no = pool_count.replace("MAX_NR_", "MAX_NO_") 250 snippet = template.replace("STRUCT_TYPE", struct_type).replace("STRUCT_NAME", struct_name).replace("POOL_COUNT_OLD_NO", pool_count_old_no).replace("POOL_COUNT", pool_count) 251 return snippet 252 253list_of_structs = [ 254 ["hci_connection"], 255 ["l2cap_service", "l2cap_channel"], 256] 257list_of_classic_structs = [ 258 ["rfcomm_multiplexer", "rfcomm_service", "rfcomm_channel"], 259 ["btstack_link_key_db_memory_entry"], 260 ["bnep_service", "bnep_channel"], 261 ["hfp_connection"], 262 ["service_record_item"], 263 ["avdtp_stream_endpoint"], 264 ["avdtp_connection"], 265 ["avrcp_connection"], 266 ["avrcp_browsing_connection"], 267] 268list_of_le_structs = [ 269 ["gatt_client", "whitelist_entry", "sm_lookup_entry"], 270] 271list_of_mesh_structs = [ 272 ['mesh_network_pdu', 'mesh_segmented_pdu', 'mesh_upper_transport_pdu', 'mesh_network_key', 'mesh_transport_key', 'mesh_virtual_address', 'mesh_subnet'] 273] 274 275btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 276file_name = btstack_root + "/src/btstack_memory" 277print ('Generating %s.[h|c]' % file_name) 278 279f = open(file_name+".h", "w") 280writeln(f, copyright) 281writeln(f, hfile_header_begin) 282for struct_names in list_of_structs: 283 writeln(f, "// "+ ", ".join(struct_names)) 284 for struct_name in struct_names: 285 writeln(f, replacePlaceholder(header_template, struct_name)) 286 writeln(f, "") 287writeln(f, "#ifdef ENABLE_CLASSIC") 288for struct_names in list_of_classic_structs: 289 writeln(f, "// "+ ", ".join(struct_names)) 290 for struct_name in struct_names: 291 writeln(f, replacePlaceholder(header_template, struct_name)) 292 writeln(f, "") 293writeln(f, "#endif") 294writeln(f, "#ifdef ENABLE_BLE") 295for struct_names in list_of_le_structs: 296 writeln(f, "// "+ ", ".join(struct_names)) 297 for struct_name in struct_names: 298 writeln(f, replacePlaceholder(header_template, struct_name)) 299writeln(f, "#endif") 300writeln(f, "#ifdef ENABLE_MESH") 301for struct_names in list_of_mesh_structs: 302 writeln(f, "// "+ ", ".join(struct_names)) 303 for struct_name in struct_names: 304 writeln(f, replacePlaceholder(header_template, struct_name)) 305writeln(f, "#endif") 306writeln(f, hfile_header_end) 307f.close(); 308 309 310f = open(file_name+".c", "w") 311writeln(f, copyright) 312writeln(f, cfile_header_begin) 313for struct_names in list_of_structs: 314 for struct_name in struct_names: 315 writeln(f, replacePlaceholder(code_template, struct_name)) 316 writeln(f, "") 317writeln(f, "#ifdef ENABLE_CLASSIC") 318for struct_names in list_of_classic_structs: 319 for struct_name in struct_names: 320 writeln(f, replacePlaceholder(code_template, struct_name)) 321 writeln(f, "") 322writeln(f, "#endif") 323writeln(f, "#ifdef ENABLE_BLE") 324for struct_names in list_of_le_structs: 325 for struct_name in struct_names: 326 writeln(f, replacePlaceholder(code_template, struct_name)) 327 writeln(f, "") 328writeln(f, "#endif") 329writeln(f, "#ifdef ENABLE_MESH") 330for struct_names in list_of_mesh_structs: 331 for struct_name in struct_names: 332 writeln(f, replacePlaceholder(code_template, struct_name)) 333 writeln(f, "") 334writeln(f, "#endif") 335 336 337writeln(f, "// init") 338writeln(f, "void btstack_memory_init(void){") 339for struct_names in list_of_structs: 340 for struct_name in struct_names: 341 writeln(f, replacePlaceholder(init_template, struct_name)) 342writeln(f, "#ifdef ENABLE_CLASSIC") 343for struct_names in list_of_classic_structs: 344 for struct_name in struct_names: 345 writeln(f, replacePlaceholder(init_template, struct_name)) 346writeln(f, "#endif") 347writeln(f, "#ifdef ENABLE_BLE") 348for struct_names in list_of_le_structs: 349 for struct_name in struct_names: 350 writeln(f, replacePlaceholder(init_template, struct_name)) 351writeln(f, "#endif") 352writeln(f, "#ifdef ENABLE_MESH") 353for struct_names in list_of_mesh_structs: 354 for struct_name in struct_names: 355 writeln(f, replacePlaceholder(init_template, struct_name)) 356writeln(f, "#endif") 357writeln(f, "}") 358f.close(); 359 360