1*3338b9aeSMilanka Ringwald#!/usr/bin/env python 2*3338b9aeSMilanka Ringwald# BlueKitchen GmbH (c) 2014 3*3338b9aeSMilanka Ringwald 4*3338b9aeSMilanka Ringwaldimport re 5*3338b9aeSMilanka Ringwaldimport os 6*3338b9aeSMilanka Ringwaldimport sys 7*3338b9aeSMilanka Ringwald 8*3338b9aeSMilanka Ringwald# paths 9*3338b9aeSMilanka Ringwaldbluetooth_h_path = 'src/bluetooth.h' 10*3338b9aeSMilanka Ringwaldbtstack_defines_h_path = 'src/btstack_defines.h' 11*3338b9aeSMilanka Ringwalddaemon_cmds_c_path = 'platform/daemon/src/daemon_cmds.c' 12*3338b9aeSMilanka Ringwaldhci_cmds_c_path = 'src/hci_cmd.c' 13*3338b9aeSMilanka Ringwaldhci_cmds_h_path = 'src/hci_cmd.h' 14*3338b9aeSMilanka Ringwaldhci_h_path = 'src/hci.h' 15*3338b9aeSMilanka Ringwald 16*3338b9aeSMilanka Ringwaldbtstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 17*3338b9aeSMilanka Ringwaldprint ("BTstack root %s" % btstack_root) 18*3338b9aeSMilanka Ringwald 19*3338b9aeSMilanka Ringwalddef set_btstack_root(path): 20*3338b9aeSMilanka Ringwald global btstack_root 21*3338b9aeSMilanka Ringwald btstack_root = path 22*3338b9aeSMilanka Ringwald 23*3338b9aeSMilanka Ringwalddef assert_dir(path): 24*3338b9aeSMilanka Ringwald if not os.access(path, os.R_OK): 25*3338b9aeSMilanka Ringwald os.makedirs(path) 26*3338b9aeSMilanka Ringwald 27*3338b9aeSMilanka Ringwalddef cap(x): 28*3338b9aeSMilanka Ringwald if x.lower() == 'btstack': 29*3338b9aeSMilanka Ringwald return 'BTstack' 30*3338b9aeSMilanka Ringwald acronyms = ['ATT', 'GAP', 'GATT', 'HCI', 'L2CAP', 'LE', 'RFCOMM', 'SM', 'SDP', 'UUID16', 'UUID128', 'HSP', 'HFP', 'ANCS'] 31*3338b9aeSMilanka Ringwald if x.upper() in acronyms: 32*3338b9aeSMilanka Ringwald return x.upper() 33*3338b9aeSMilanka Ringwald return x.capitalize() 34*3338b9aeSMilanka Ringwald 35*3338b9aeSMilanka Ringwalddef camel_case(name): 36*3338b9aeSMilanka Ringwald return ''.join(map(cap, name.split('_'))) 37*3338b9aeSMilanka Ringwald 38*3338b9aeSMilanka Ringwalddef camel_case_var(name): 39*3338b9aeSMilanka Ringwald if name in ['uuid128', 'uuid16']: 40*3338b9aeSMilanka Ringwald return name 41*3338b9aeSMilanka Ringwald camel = camel_case(name) 42*3338b9aeSMilanka Ringwald return camel[0].lower() + camel[1:] 43*3338b9aeSMilanka Ringwald 44*3338b9aeSMilanka Ringwalddef read_defines(infile): 45*3338b9aeSMilanka Ringwald defines = dict() 46*3338b9aeSMilanka Ringwald with open (infile, 'rt') as fin: 47*3338b9aeSMilanka Ringwald for line in fin: 48*3338b9aeSMilanka Ringwald parts = re.match('#define\s+(\w+)\s+(\w*)',line) 49*3338b9aeSMilanka Ringwald if parts and len(parts.groups()) == 2: 50*3338b9aeSMilanka Ringwald (key, value) = parts.groups() 51*3338b9aeSMilanka Ringwald defines[key] = value 52*3338b9aeSMilanka Ringwald return defines 53*3338b9aeSMilanka Ringwald 54*3338b9aeSMilanka Ringwalddef parse_defines(): 55*3338b9aeSMilanka Ringwald global btstack_root 56*3338b9aeSMilanka Ringwald defines = dict() 57*3338b9aeSMilanka Ringwald defines.update(read_defines(btstack_root + '/' + hci_cmds_h_path)) 58*3338b9aeSMilanka Ringwald defines.update(read_defines(btstack_root + '/' + hci_h_path)) 59*3338b9aeSMilanka Ringwald defines.update(read_defines(btstack_root + '/' + bluetooth_h_path)) 60*3338b9aeSMilanka Ringwald defines.update(read_defines(btstack_root + '/' + btstack_defines_h_path)) 61*3338b9aeSMilanka Ringwald return defines 62*3338b9aeSMilanka Ringwald 63*3338b9aeSMilanka Ringwalddef my_parse_events(path): 64*3338b9aeSMilanka Ringwald events = [] 65*3338b9aeSMilanka Ringwald subevents = [] 66*3338b9aeSMilanka Ringwald params = [] 67*3338b9aeSMilanka Ringwald event_types = set() 68*3338b9aeSMilanka Ringwald format = None 69*3338b9aeSMilanka Ringwald with open (path, 'rt') as fin: 70*3338b9aeSMilanka Ringwald for line in fin: 71*3338b9aeSMilanka Ringwald parts = re.match('.*@format\s*(\w*)\s*', line) 72*3338b9aeSMilanka Ringwald if parts and len(parts.groups()) == 1: 73*3338b9aeSMilanka Ringwald format = parts.groups()[0] 74*3338b9aeSMilanka Ringwald parts = re.match('.*@param\s*(\w*)\s*', line) 75*3338b9aeSMilanka Ringwald if parts and len(parts.groups()) == 1: 76*3338b9aeSMilanka Ringwald param = parts.groups()[0] 77*3338b9aeSMilanka Ringwald params.append(param) 78*3338b9aeSMilanka Ringwald parts = re.match('\s*#define\s+(\w+)\s+(\w*)',line) 79*3338b9aeSMilanka Ringwald if parts and len(parts.groups()) == 2: 80*3338b9aeSMilanka Ringwald (key, value) = parts.groups() 81*3338b9aeSMilanka Ringwald if format != None: 82*3338b9aeSMilanka Ringwald # renaming needed by Java Binding (... subevents are just enumerated with others due to event factory) 83*3338b9aeSMilanka Ringwald if "_subevent_" in key.lower(): 84*3338b9aeSMilanka Ringwald subevents.append((value, key, format, params)) 85*3338b9aeSMilanka Ringwald else: 86*3338b9aeSMilanka Ringwald events.append((value, key, format, params)) 87*3338b9aeSMilanka Ringwald event_types.add(key) 88*3338b9aeSMilanka Ringwald params = [] 89*3338b9aeSMilanka Ringwald format = None 90*3338b9aeSMilanka Ringwald return (events, subevents, event_types) 91*3338b9aeSMilanka Ringwald 92*3338b9aeSMilanka Ringwalddef parse_events(): 93*3338b9aeSMilanka Ringwald global btstack_root 94*3338b9aeSMilanka Ringwald 95*3338b9aeSMilanka Ringwald # parse bluetooth.h to get used events 96*3338b9aeSMilanka Ringwald (bluetooth_events, bluetooth_subevents, bluetooth_event_types) = my_parse_events(btstack_root + '/' + bluetooth_h_path) 97*3338b9aeSMilanka Ringwald 98*3338b9aeSMilanka Ringwald # parse btstack_defines to get events 99*3338b9aeSMilanka Ringwald (btstack_events, btstack_subevents, btstack_event_types) = my_parse_events(btstack_root + '/' + btstack_defines_h_path) 100*3338b9aeSMilanka Ringwald 101*3338b9aeSMilanka Ringwald # concat lists 102*3338b9aeSMilanka Ringwald (events, subvents, event_types) = (bluetooth_events + btstack_events, bluetooth_subevents + btstack_subevents, bluetooth_event_types | btstack_event_types) 103*3338b9aeSMilanka Ringwald 104*3338b9aeSMilanka Ringwald return (events, subvents, event_types) 105*3338b9aeSMilanka Ringwald 106*3338b9aeSMilanka Ringwalddef my_parse_commands(infile): 107*3338b9aeSMilanka Ringwald commands = [] 108*3338b9aeSMilanka Ringwald with open (infile, 'rt') as fin: 109*3338b9aeSMilanka Ringwald 110*3338b9aeSMilanka Ringwald params = [] 111*3338b9aeSMilanka Ringwald for line in fin: 112*3338b9aeSMilanka Ringwald 113*3338b9aeSMilanka Ringwald parts = re.match('.*@param\s*(\w*)\s*', line) 114*3338b9aeSMilanka Ringwald if parts and len(parts.groups()) == 1: 115*3338b9aeSMilanka Ringwald param = parts.groups()[0] 116*3338b9aeSMilanka Ringwald params.append(camel_case_var(param)) 117*3338b9aeSMilanka Ringwald continue 118*3338b9aeSMilanka Ringwald 119*3338b9aeSMilanka Ringwald declaration = re.match('const\s+hci_cmd_t\s+(\w+)[\s=]+', line) 120*3338b9aeSMilanka Ringwald if declaration: 121*3338b9aeSMilanka Ringwald command_name = camel_case(declaration.groups()[0]) 122*3338b9aeSMilanka Ringwald if command_name.endswith('Cmd'): 123*3338b9aeSMilanka Ringwald command_name = command_name[:-len('Cmd')] 124*3338b9aeSMilanka Ringwald continue 125*3338b9aeSMilanka Ringwald 126*3338b9aeSMilanka Ringwald definition = re.match('\s*OPCODE\\(\s*(\w+)\s*,\s+(\w+)\s*\\)\s*,\s\\"(\w*)\\".*', line) 127*3338b9aeSMilanka Ringwald if definition: 128*3338b9aeSMilanka Ringwald (ogf, ocf, format) = definition.groups() 129*3338b9aeSMilanka Ringwald if len(params) != len(format): 130*3338b9aeSMilanka Ringwald params = [] 131*3338b9aeSMilanka Ringwald arg_counter = 1 132*3338b9aeSMilanka Ringwald for f in format: 133*3338b9aeSMilanka Ringwald arg_name = 'arg%u' % arg_counter 134*3338b9aeSMilanka Ringwald params.append(arg_name) 135*3338b9aeSMilanka Ringwald arg_counter += 1 136*3338b9aeSMilanka Ringwald commands.append((command_name, ogf, ocf, format, params)) 137*3338b9aeSMilanka Ringwald params = [] 138*3338b9aeSMilanka Ringwald continue 139*3338b9aeSMilanka Ringwald return commands 140*3338b9aeSMilanka Ringwald 141*3338b9aeSMilanka Ringwalddef parse_commands(): 142*3338b9aeSMilanka Ringwald global btstack_root 143*3338b9aeSMilanka Ringwald commands = [] 144*3338b9aeSMilanka Ringwald commands = commands = my_parse_commands(btstack_root + '/' + hci_cmds_c_path) 145*3338b9aeSMilanka Ringwald commands = commands = my_parse_commands(btstack_root + '/' + daemon_cmds_c_path) 146*3338b9aeSMilanka Ringwald return commands