diff --git a/tool/btstack_rtos_generator.py b/tool/btstack_rtos_generator.py index 565901523..6c85acced 100755 --- a/tool/btstack_rtos_generator.py +++ b/tool/btstack_rtos_generator.py @@ -39,7 +39,7 @@ copyright = """/* */ """ -hfile_header_begin = """ +single_hfile_header_begin = """ /* * btstack_rtos.h @@ -73,11 +73,11 @@ extern "C" { """ -hfile_api_header = """ +single_hfile_api_header = """ #include "API_NAME" """ -hfile_header_end = """ +single_hfile_header_end = """ /* API_END */ @@ -88,6 +88,52 @@ hfile_header_end = """ #endif // __BTSTACK_RTOS_H """ +multiple_header_begin = """ + +/* + * FILENAME + * + * @brief BTstack Wrapper for use with Real-Time OS + * Wraps each public BTstack function into a thread-safe version + * + * @note Don't edit - generated by tool/btstack_rtos_generator.py + * + */ + +#ifndef GUARD +#define GUARD + +#if defined __cplusplus +extern "C" { +#endif + +#include "btstack_config.h" +#include "HEADER" + +#ifndef BTSTACK_RTOS_ENTER +#error Please define BTSTACK_RTOS_ENTER that locks a recursive mutex when using the RTOS wrapper btstack_rtos.h +#endif + +#ifndef BTSTACK_RTOS_EXIT +#error Please define BTSTACK_RTOS_EXIT that releases a recursive mutex when using the RTOS wrapper btstack_rtos.h +#endif + +/* API_START */ + + +""" + +multiple_header_end = """ + +/* API_END */ + +#if defined __cplusplus +} +#endif + +#endif // GUARD +""" + class State: SearchStartAPI = 0 SearchEndAPI = 1 @@ -118,25 +164,21 @@ apis = [ ["src/classic/sdp_server.h", "SDP Server", "sdpSrv", True], ["src/classic/sdp_util.h","SDP Utils", "sdpUtil", True], - ["src/ad_parser.h", "BLE Advertisements Parser", "advParser", True], - ["src/btstack_chipset.h","BTstack Chipset","btMemory", True], - ["src/btstack_control.h","BTstack Hardware Control","btControl", True], + ["src/ad_parser.h", "BLE Advertisements Parser", "advParser", False], + # ["src/btstack_chipset.h","BTstack Chipset","btMemory", True], + # ["src/btstack_control.h","BTstack Hardware Control","btControl", True], ["src/btstack_event.h","HCI Event Getter","btEvent", False], - ["src/btstack_memory.h","BTstack Memory Management","btMemory", True], - ["src/btstack_linked_list.h","BTstack Linked List","btList", True], + # ["src/btstack_memory.h","BTstack Memory Management","btMemory", True], + ["src/btstack_linked_list.h","BTstack Linked List","btList", False], ["src/btstack_run_loop.h", "Run Loop", "runLoop", True], - ["src/btstack_util.h", "Common Utils", "btUtil", True], + ["src/btstack_util.h", "Common Utils", "btUtil", False], ["src/gap.h", "GAP", "gap", True], ["src/hci.h", "HCI", "hci", True], ["src/hci_dump.h","HCI Logging","hciTrace", True], - ["src/hci_transport.h","HCI Transport","hciTransport", True], + # ["src/hci_transport.h","HCI Transport","hciTransport", True], ["src/l2cap.h", "L2CAP", "l2cap", True], ] - -def codeReference(fname, filepath, linenr): - return fname - def split_arguments(args_string): args = [] brace_level = 0 @@ -214,132 +256,166 @@ def create_wrapper(fout, type_and_name, arg_string, need_lock): fout.write(' ' + orig_call+';\n') else: fout.write(' return ' + orig_call + ';\n') - fout.write('}\n') fout.write('\n') num_functions += 1 -def create_wrapper_file(btstackfolder, apis, wrapper_file): - with open(wrapper_file, 'w') as fout: - fout.write(copyright) - fout.write(hfile_header_begin) +def write_wrappers_for_file(fout, file, header_name, need_lock): + with open(file, 'rb') as fin: + typedefFound = 0 + multiline_function_def = 0 + multiline = '' + multiline_comment = 0 + inline_function = 0 + state = State.SearchStartAPI - for api_tuple in apis: - api_filename = btstackfolder + "/" + api_tuple[0] - api_title = api_tuple[1] - api_lable = api_tuple[2] - need_lock = api_tuple[3] + for line in fin: + if state == State.DoneAPI: + continue + + if state == State.SearchStartAPI: + parts = re.match('.*API_START.*',line) + if parts: + state = State.SearchEndAPI + continue + + if state == State.SearchEndAPI: + parts = re.match('.*API_END.*',line) + if parts: + state = State.DoneAPI + continue - header_file = api_tuple[0].replace('src/','') - fout.write(hfile_api_header.replace("API_NAME", header_file)) + if inline_function: + function_end = re.match('.*}.*', line) + if function_end: + inline_function = 0 + continue - with open(api_filename, 'rb') as fin: - typedefFound = 0 - multiline_function_def = 0 - multiline = '' - multiline_comment = 0 - inline_function = 0 - state = State.SearchStartAPI - - for line in fin: - if state == State.DoneAPI: - continue - - if state == State.SearchStartAPI: - parts = re.match('.*API_START.*',line) - if parts: - state = State.SearchEndAPI - continue - - if state == State.SearchEndAPI: - parts = re.match('.*API_END.*',line) - if parts: - state = State.DoneAPI - continue - - if inline_function: - function_end = re.match('.*}.*', line) - if function_end: - inline_function = 0 - continue - - if multiline_function_def: - multiline += line - function_end = re.match('.*\)', line) - if function_end: - multiline_function_def = 0 - function = re.match('([\w\s\*]*)\(([\w\s,\*]*)\).*', multiline) - if function: - type_and_name = function.group(1) - arg_string = function.group(2) - create_wrapper(fout, type_and_name, arg_string, need_lock) - continue - - if multiline_comment: - comment_end = re.match('.*\*/.*', line) - if comment_end: - multiline_comment = 0 - fout.write(line) - continue - - # search typedef struct end - if typedefFound: - typedef = re.match('}\s*(.*);\n', line) - if typedef: - typedefFound = 0 - continue - - # search comment line - comment = re.match(".*/\*.*\*/.*", line) - if comment: - fout.write(line) - continue - - # search start of multi line comment - comment = re.match(".*/\*", line) - if comment: - fout.write(line) - multiline_comment = 1 - continue - - # ignore __attribute__ for hci_dump_log in src/hci_dump.h - param = re.match(".*__attribute__", line) - if param: - continue - - # search typedef struct begin - typedef = re.match('.*typedef\s+struct.*', line) - if typedef: - typedefFound = 1 - - # complete function declaration - function = re.match('([\w\s\*]*)\((.*)\).*', line) + if multiline_function_def: + multiline += line + function_end = re.match('.*\)', line) + if function_end: + multiline_function_def = 0 + function = re.match('([\w\s\*]*)\(([\w\s,\*]*)\).*', multiline) if function: - if "return" in line: - continue type_and_name = function.group(1) arg_string = function.group(2) create_wrapper(fout, type_and_name, arg_string, need_lock) - inline_function = 'inline' in line; - continue + continue - # multi-line function declaration - function = re.match('([\w\s\*]*)\((.*).*', line) - if function: - multiline = line - multiline_function_def = 1 - continue + if multiline_comment: + comment_end = re.match('.*\*/.*', line) + if comment_end: + multiline_comment = 0 + fout.write(line) + continue + + # search typedef struct end + if typedefFound: + typedef = re.match('}\s*(.*);\n', line) + if typedef: + typedefFound = 0 + continue + + # search comment line + comment = re.match(".*/\*.*\*/.*", line) + if comment: + fout.write(line) + continue + + # search start of multi line comment + comment = re.match(".*/\*", line) + if comment: + fout.write(line) + multiline_comment = 1 + continue + + # ignore __attribute__ for hci_dump_log in src/hci_dump.h + param = re.match(".*__attribute__", line) + if param: + continue + + # search typedef struct begin + typedef = re.match('.*typedef\s+struct.*', line) + if typedef: + typedefFound = 1 + + # complete function declaration + function = re.match('([\w\s\*]*)\((.*)\).*', line) + if function: + if "return" in line: + continue + type_and_name = function.group(1) + arg_string = function.group(2) + create_wrapper(fout, type_and_name, arg_string, need_lock) + inline_function = 'inline' in line; + continue + + # multi-line function declaration + function = re.match('([\w\s\*]*)\((.*).*', line) + if function: + multiline = line + multiline_function_def = 1 + continue + + # fout.write(single_hfile_header_begin) + + +def create_wrapper_file(btstack_root, apis, wrapper_file): + with open(wrapper_file, 'w') as fout: + fout.write(copyright) + fout.write(single_hfile_header_begin) + + for api_tuple in apis: + api_filename = btstack_root + "/" + api_tuple[0] + need_lock = api_tuple[3] + header_file = api_tuple[0].replace('src/','') + fout.write(single_hfile_api_header.replace("API_NAME", header_file)) + write_wrappers_for_file(fout, api_filename, header_file, need_lock) + # fout.write(single_hfile_header_begin) + fout.write(single_hfile_header_end) + +def create_wrapper_files(btstack_root, rtos_folder, apis): + for api_tuple in apis: + api_filename = btstack_root + "/" + api_tuple[0] + need_lock = api_tuple[3] + header_file = api_tuple[0].replace('src/','') + path_parts = header_file.split('/') + path_parts[-1] = 'rtos_' + path_parts[-1] + rtos_file = '/'.join(path_parts) + wrapper_file = rtos_folder + '/' + rtos_file + # print('- %s' % wrapper_file) + with open(wrapper_file, 'w') as fout: + guard = '__' + rtos_file.replace('.','_').upper() + fout.write(copyright) + fout.write(multiple_header_begin.replace('FILENAME',rtos_file).replace('GUARD',guard).replace('HEADER',header_file)) + write_wrappers_for_file(fout, api_filename, header_file, need_lock) + fout.write(multiple_header_end.replace('GUARD',guard)) + +def assert_dir_exists(path): + if not os.path.exists(path): + os.makedirs(path) - # fout.write(hfile_header_begin) - fout.write(hfile_header_end) - def main(argv): btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') - gen_path = btstack_root + '/src/btstack_rtos.h' print ('BTstack folder is: %s' % btstack_root) - print ('Generating RTOS wrapper %s' % gen_path) - create_wrapper_file(btstack_root, apis, gen_path) + + # single file + # gen_path = btstack_root + '/src/btstack_rtos.h' + # print ('Generating RTOS wrapper %s' % gen_path) + # create_wrapper_file(btstack_root, apis, gen_path) + + # individual files in platform/rtos + print ('Generating RTOS wrappers...') + rtos_folder = btstack_root + '/platform/rtos' + assert_dir_exists(rtos_folder) + assert_dir_exists(rtos_folder+'/ble') + assert_dir_exists(rtos_folder+'/classic') + create_wrapper_files(btstack_root, rtos_folder, apis) + + # summary print ('Number wrapped headers: %u' % len(apis)) print ('Number wrapped functions: %u' % num_functions) + if __name__ == "__main__": main(sys.argv[1:])