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(void * raw_buffer){ 144 btstack_assert(raw_buffer != NULL); 145 btstack_memory_buffer_t * buffer = (btstack_memory_buffer_t*) raw_buffer; 146 btstack_memory_malloc_buffers = buffer; 147 buffer->prev = NULL; 148 buffer->next = btstack_memory_malloc_buffers; 149 btstack_memory_malloc_buffers = buffer; 150} 151 152static void btstack_memory_tracking_remove(void * raw_buffer){ 153 btstack_assert(raw_buffer != NULL); 154 btstack_memory_buffer_t * buffer = (btstack_memory_buffer_t*) raw_buffer; 155 if (buffer->prev == NULL){ 156 // first item 157 btstack_memory_malloc_buffers = buffer->next; 158 } else { 159 buffer->prev->next = buffer->next; 160 } 161 if (buffer->next != NULL){ 162 buffer->next->prev = buffer->prev; 163 } 164} 165#endif 166 167void btstack_memory_deinit(void){ 168#ifdef HAVE_MALLOC 169 while (btstack_memory_malloc_buffers != NULL){ 170 btstack_memory_buffer_t * buffer = btstack_memory_malloc_buffers; 171 btstack_memory_malloc_buffers = buffer->next; 172 free(buffer); 173 } 174#endif 175} 176""" 177 178header_template = """STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void); 179void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME);""" 180 181code_template = """ 182// MARK: STRUCT_TYPE 183#if !defined(HAVE_MALLOC) && !defined(POOL_COUNT) 184 #if defined(POOL_COUNT_OLD_NO) 185 #error "Deprecated POOL_COUNT_OLD_NO defined instead of POOL_COUNT. Please update your btstack_config.h to use POOL_COUNT." 186 #else 187 #define POOL_COUNT 0 188 #endif 189#endif 190 191#ifdef POOL_COUNT 192#if POOL_COUNT > 0 193static STRUCT_TYPE STRUCT_NAME_storage[POOL_COUNT]; 194static btstack_memory_pool_t STRUCT_NAME_pool; 195STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 196 void * buffer = btstack_memory_pool_get(&STRUCT_NAME_pool); 197 if (buffer){ 198 memset(buffer, 0, sizeof(STRUCT_TYPE)); 199 } 200 return (STRUCT_NAME_t *) buffer; 201} 202void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 203 btstack_memory_pool_free(&STRUCT_NAME_pool, STRUCT_NAME); 204} 205#else 206STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 207 return NULL; 208} 209void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 210 UNUSED(STRUCT_NAME); 211}; 212#endif 213#elif defined(HAVE_MALLOC) 214STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){ 215 void * buffer = malloc(sizeof(STRUCT_TYPE) + sizeof(btstack_memory_buffer_t)); 216 if (buffer){ 217 memset(buffer, 0, sizeof(STRUCT_TYPE) + sizeof(btstack_memory_buffer_t)); 218 btstack_memory_tracking_add(buffer); 219 return (STRUCT_NAME_t *) (buffer + sizeof(btstack_memory_buffer_t)); 220 } else { 221 return NULL; 222 } 223} 224void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){ 225 void * buffer = ((void *) STRUCT_NAME) - sizeof(btstack_memory_buffer_t); 226 btstack_memory_tracking_remove(buffer); 227 free(buffer); 228} 229#endif 230""" 231 232init_template = """#if POOL_COUNT > 0 233 btstack_memory_pool_create(&STRUCT_NAME_pool, STRUCT_NAME_storage, POOL_COUNT, sizeof(STRUCT_TYPE)); 234#endif""" 235 236def writeln(f, data): 237 f.write(data + "\n") 238 239def replacePlaceholder(template, struct_name): 240 struct_type = struct_name + '_t' 241 if struct_name.endswith('try'): 242 pool_count = "MAX_NR_" + struct_name.upper()[:-3] + "TRIES" 243 else: 244 pool_count = "MAX_NR_" + struct_name.upper() + "S" 245 pool_count_old_no = pool_count.replace("MAX_NR_", "MAX_NO_") 246 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) 247 return snippet 248 249list_of_structs = [ 250 ["hci_connection"], 251 ["l2cap_service", "l2cap_channel"], 252] 253list_of_classic_structs = [ 254 ["rfcomm_multiplexer", "rfcomm_service", "rfcomm_channel"], 255 ["btstack_link_key_db_memory_entry"], 256 ["bnep_service", "bnep_channel"], 257 ["hfp_connection"], 258 ["service_record_item"], 259 ["avdtp_stream_endpoint"], 260 ["avdtp_connection"], 261 ["avrcp_connection"], 262 ["avrcp_browsing_connection"], 263] 264list_of_le_structs = [ 265 ["gatt_client", "whitelist_entry", "sm_lookup_entry"], 266] 267list_of_mesh_structs = [ 268 ['mesh_network_pdu', 'mesh_segmented_pdu', 'mesh_upper_transport_pdu', 'mesh_network_key', 'mesh_transport_key', 'mesh_virtual_address', 'mesh_subnet'] 269] 270 271btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 272file_name = btstack_root + "/src/btstack_memory" 273print ('Generating %s.[h|c]' % file_name) 274 275f = open(file_name+".h", "w") 276writeln(f, copyright) 277writeln(f, hfile_header_begin) 278for struct_names in list_of_structs: 279 writeln(f, "// "+ ", ".join(struct_names)) 280 for struct_name in struct_names: 281 writeln(f, replacePlaceholder(header_template, struct_name)) 282 writeln(f, "") 283writeln(f, "#ifdef ENABLE_CLASSIC") 284for struct_names in list_of_classic_structs: 285 writeln(f, "// "+ ", ".join(struct_names)) 286 for struct_name in struct_names: 287 writeln(f, replacePlaceholder(header_template, struct_name)) 288 writeln(f, "") 289writeln(f, "#endif") 290writeln(f, "#ifdef ENABLE_BLE") 291for struct_names in list_of_le_structs: 292 writeln(f, "// "+ ", ".join(struct_names)) 293 for struct_name in struct_names: 294 writeln(f, replacePlaceholder(header_template, struct_name)) 295writeln(f, "#endif") 296writeln(f, "#ifdef ENABLE_MESH") 297for struct_names in list_of_mesh_structs: 298 writeln(f, "// "+ ", ".join(struct_names)) 299 for struct_name in struct_names: 300 writeln(f, replacePlaceholder(header_template, struct_name)) 301writeln(f, "#endif") 302writeln(f, hfile_header_end) 303f.close(); 304 305 306f = open(file_name+".c", "w") 307writeln(f, copyright) 308writeln(f, cfile_header_begin) 309for struct_names in list_of_structs: 310 for struct_name in struct_names: 311 writeln(f, replacePlaceholder(code_template, struct_name)) 312 writeln(f, "") 313writeln(f, "#ifdef ENABLE_CLASSIC") 314for struct_names in list_of_classic_structs: 315 for struct_name in struct_names: 316 writeln(f, replacePlaceholder(code_template, struct_name)) 317 writeln(f, "") 318writeln(f, "#endif") 319writeln(f, "#ifdef ENABLE_BLE") 320for struct_names in list_of_le_structs: 321 for struct_name in struct_names: 322 writeln(f, replacePlaceholder(code_template, struct_name)) 323 writeln(f, "") 324writeln(f, "#endif") 325writeln(f, "#ifdef ENABLE_MESH") 326for struct_names in list_of_mesh_structs: 327 for struct_name in struct_names: 328 writeln(f, replacePlaceholder(code_template, struct_name)) 329 writeln(f, "") 330writeln(f, "#endif") 331 332 333writeln(f, "// init") 334writeln(f, "void btstack_memory_init(void){") 335for struct_names in list_of_structs: 336 for struct_name in struct_names: 337 writeln(f, replacePlaceholder(init_template, struct_name)) 338writeln(f, "#ifdef ENABLE_CLASSIC") 339for struct_names in list_of_classic_structs: 340 for struct_name in struct_names: 341 writeln(f, replacePlaceholder(init_template, struct_name)) 342writeln(f, "#endif") 343writeln(f, "#ifdef ENABLE_BLE") 344for struct_names in list_of_le_structs: 345 for struct_name in struct_names: 346 writeln(f, replacePlaceholder(init_template, struct_name)) 347writeln(f, "#endif") 348writeln(f, "#ifdef ENABLE_MESH") 349for struct_names in list_of_mesh_structs: 350 for struct_name in struct_names: 351 writeln(f, replacePlaceholder(init_template, struct_name)) 352writeln(f, "#endif") 353writeln(f, "}") 354f.close(); 355 356