1b3fcedb9SMatthias Ringwald#!/usr/bin/env python 2b3fcedb9SMatthias Ringwald# 3b3fcedb9SMatthias Ringwald# BLE GATT configuration generator for use with BTstack, v0.1 4b3fcedb9SMatthias Ringwald# Copyright 2011 Matthias Ringwald 5b3fcedb9SMatthias Ringwald# 6b3fcedb9SMatthias Ringwald# Format of input file: 7b3fcedb9SMatthias Ringwald# PRIMARY_SERVICE, SERVICE_UUID 8b3fcedb9SMatthias Ringwald# CHARACTERISTIC, ATTRIBUTE_TYPE_UUID, [READ | WRITE | DYNAMIC], VALUE 9b3fcedb9SMatthias Ringwald 10b3fcedb9SMatthias Ringwaldimport codecs 11b165f97bSMatthias Ringwaldimport csv 12b165f97bSMatthias Ringwaldimport io 13b165f97bSMatthias Ringwaldimport os 14b165f97bSMatthias Ringwaldimport re 15b165f97bSMatthias Ringwaldimport string 16b3fcedb9SMatthias Ringwald 17b3fcedb9SMatthias Ringwaldheader = ''' 18b3fcedb9SMatthias Ringwald// {0} generated from {1} for BTstack 19b3fcedb9SMatthias Ringwald 20b3fcedb9SMatthias Ringwald// binary representation 21b3fcedb9SMatthias Ringwald// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) 22b3fcedb9SMatthias Ringwald 23b3fcedb9SMatthias Ringwald#include <stdint.h> 24b3fcedb9SMatthias Ringwald 25b3fcedb9SMatthias Ringwaldconst uint8_t profile_data[] = 26b3fcedb9SMatthias Ringwald''' 27b3fcedb9SMatthias Ringwald 28b3fcedb9SMatthias Ringwaldusage = ''' 29b3fcedb9SMatthias RingwaldUsage: ./compile_gatt.py profile.gatt profile.h 30b3fcedb9SMatthias Ringwald''' 31b3fcedb9SMatthias Ringwald 32b3fcedb9SMatthias Ringwaldimport re 33b3fcedb9SMatthias Ringwaldimport sys 34b3fcedb9SMatthias Ringwald 35b3fcedb9SMatthias Ringwaldprint(''' 36b3fcedb9SMatthias RingwaldBLE configuration generator for use with BTstack, v0.1 37b3fcedb9SMatthias RingwaldCopyright 2011 Matthias Ringwald 38b3fcedb9SMatthias Ringwald''') 39b3fcedb9SMatthias Ringwald 40b3fcedb9SMatthias Ringwaldassigned_uuids = { 41b3fcedb9SMatthias Ringwald 'GAP_SERVICE' : 0x1800, 42b3fcedb9SMatthias Ringwald 'GATT_SERVICE' : 0x1801, 43b3fcedb9SMatthias Ringwald 'GAP_DEVICE_NAME' : 0x2a00, 44b3fcedb9SMatthias Ringwald 'GAP_APPEARANCE' : 0x2a01, 45b3fcedb9SMatthias Ringwald 'GAP_PERIPHERAL_PRIVACY_FLAG' : 0x2A02, 46b3fcedb9SMatthias Ringwald 'GAP_RECONNECTION_ADDRESS' : 0x2A03, 47b3fcedb9SMatthias Ringwald 'GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS' : 0x2A04, 48b3fcedb9SMatthias Ringwald 'GATT_SERVICE_CHANGED' : 0x2a05, 49b3fcedb9SMatthias Ringwald} 50b3fcedb9SMatthias Ringwald 51b3fcedb9SMatthias Ringwaldproperty_flags = { 52b3fcedb9SMatthias Ringwald 'BROADCAST' : 0x01, 53b3fcedb9SMatthias Ringwald 'READ' : 0x02, 54b3fcedb9SMatthias Ringwald 'WRITE_WITHOUT_RESPONSE' : 0x04, 55b3fcedb9SMatthias Ringwald 'WRITE' : 0x08, 56b3fcedb9SMatthias Ringwald 'NOTIFY': 0x10, 57b3fcedb9SMatthias Ringwald 'INDICATE' : 0x20, 58b3fcedb9SMatthias Ringwald 'AUTHENTICATED_SIGNED_WRITE' : 0x40, 59b3fcedb9SMatthias Ringwald 'EXTENDED_PROPERTIES' : 0x80, 60b3fcedb9SMatthias Ringwald # custom BTstack extension 61b3fcedb9SMatthias Ringwald 'DYNAMIC': 0x100, 62b3fcedb9SMatthias Ringwald 'LONG_UUID': 0x200, 63b3fcedb9SMatthias Ringwald 'AUTHENTICATION_REQUIRED': 0x400, 64b3fcedb9SMatthias Ringwald 'AUTHORIZATION_REQUIRED': 0x800, 65b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_7': 0x6000, 66b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_8': 0x7000, 67b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_9': 0x8000, 68b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_10': 0x9000, 69b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_11': 0xa000, 70b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_12': 0xb000, 71b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_13': 0xc000, 72b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_14': 0xd000, 73b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_15': 0xe000, 74b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_16': 0xf000, 75b3fcedb9SMatthias Ringwald # only used by gatt compiler >= 0xffff 76b3fcedb9SMatthias Ringwald # Extended Properties 77b3fcedb9SMatthias Ringwald 'RELIABLE_WRITE': 0x10000, 78b3fcedb9SMatthias Ringwald} 79b3fcedb9SMatthias Ringwald 80b3fcedb9SMatthias Ringwaldservices = dict() 81b3fcedb9SMatthias Ringwaldcharacteristic_indices = dict() 82b3fcedb9SMatthias Ringwaldpresentation_formats = dict() 83b3fcedb9SMatthias Ringwaldcurrent_service_uuid_string = "" 84b3fcedb9SMatthias Ringwaldcurrent_service_start_handle = 0 85b3fcedb9SMatthias Ringwaldcurrent_characteristic_uuid_string = "" 86*729074c4SMatthias Ringwalddefines_for_characteristics = [] 87*729074c4SMatthias Ringwalddefines_for_services = [] 88b3fcedb9SMatthias Ringwald 89b3fcedb9SMatthias Ringwaldhandle = 1 90b3fcedb9SMatthias Ringwaldtotal_size = 0 91b3fcedb9SMatthias Ringwald 92b165f97bSMatthias Ringwalddef read_defines(infile): 93b165f97bSMatthias Ringwald defines = dict() 94b165f97bSMatthias Ringwald with open (infile, 'rt') as fin: 95b165f97bSMatthias Ringwald for line in fin: 96b165f97bSMatthias Ringwald parts = re.match('#define\s+(\w+)\s+(\w+)',line) 97b165f97bSMatthias Ringwald if parts and len(parts.groups()) == 2: 98b165f97bSMatthias Ringwald (key, value) = parts.groups() 99b165f97bSMatthias Ringwald defines[key] = int(value, 16) 100b165f97bSMatthias Ringwald return defines 101b165f97bSMatthias Ringwald 102b3fcedb9SMatthias Ringwalddef keyForUUID(uuid): 103b3fcedb9SMatthias Ringwald keyUUID = "" 104b3fcedb9SMatthias Ringwald for i in uuid: 105b3fcedb9SMatthias Ringwald keyUUID += "%02x" % i 106b3fcedb9SMatthias Ringwald return keyUUID 107b3fcedb9SMatthias Ringwald 108b3fcedb9SMatthias Ringwalddef c_string_for_uuid(uuid): 109b3fcedb9SMatthias Ringwald return uuid.replace('-', '_') 110b3fcedb9SMatthias Ringwald 111b3fcedb9SMatthias Ringwalddef twoByteLEFor(value): 112b3fcedb9SMatthias Ringwald return [ (value & 0xff), (value >> 8)] 113b3fcedb9SMatthias Ringwald 114b3fcedb9SMatthias Ringwalddef is_128bit_uuid(text): 115b3fcedb9SMatthias Ringwald if re.match("[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}", text): 116b3fcedb9SMatthias Ringwald return True 117b3fcedb9SMatthias Ringwald return False 118b3fcedb9SMatthias Ringwald 119b3fcedb9SMatthias Ringwalddef parseUUID128(uuid): 120b3fcedb9SMatthias Ringwald parts = re.match("([0-9A-Fa-f]{4})([0-9A-Fa-f]{4})-([0-9A-Fa-f]{4})-([0-9A-Fa-f]{4})-([0-9A-Fa-f]{4})-([0-9A-Fa-f]{4})([0-9A-Fa-f]{4})([0-9A-Fa-f]{4})", uuid) 121b3fcedb9SMatthias Ringwald uuid_bytes = [] 122b3fcedb9SMatthias Ringwald for i in range(8, 0, -1): 123b3fcedb9SMatthias Ringwald uuid_bytes = uuid_bytes + twoByteLEFor(int(parts.group(i),16)) 124b3fcedb9SMatthias Ringwald return uuid_bytes 125b3fcedb9SMatthias Ringwald 126b3fcedb9SMatthias Ringwalddef parseUUID(uuid): 127b3fcedb9SMatthias Ringwald if uuid in assigned_uuids: 128b3fcedb9SMatthias Ringwald return twoByteLEFor(assigned_uuids[uuid]) 129b165f97bSMatthias Ringwald uuid_upper = uuid.upper().replace('.','_') 130b165f97bSMatthias Ringwald if uuid_upper in bluetooth_gatt: 131b165f97bSMatthias Ringwald return twoByteLEFor(bluetooth_gatt[uuid_upper]) 132b3fcedb9SMatthias Ringwald if is_128bit_uuid(uuid): 133b3fcedb9SMatthias Ringwald return parseUUID128(uuid) 134b3fcedb9SMatthias Ringwald uuidInt = int(uuid, 16) 135b3fcedb9SMatthias Ringwald return twoByteLEFor(uuidInt) 136b3fcedb9SMatthias Ringwald 137b3fcedb9SMatthias Ringwalddef parseProperties(properties): 138b3fcedb9SMatthias Ringwald value = 0 139b3fcedb9SMatthias Ringwald parts = properties.split("|") 140b3fcedb9SMatthias Ringwald for property in parts: 141b3fcedb9SMatthias Ringwald property = property.strip() 142b3fcedb9SMatthias Ringwald if property in property_flags: 143b3fcedb9SMatthias Ringwald value |= property_flags[property] 144b3fcedb9SMatthias Ringwald else: 145b3fcedb9SMatthias Ringwald print("WARNING: property %s undefined" % (property)) 146b3fcedb9SMatthias Ringwald return value 147b3fcedb9SMatthias Ringwald 148b3fcedb9SMatthias Ringwalddef write_8(fout, value): 149b3fcedb9SMatthias Ringwald fout.write( "0x%02x, " % (value & 0xff)) 150b3fcedb9SMatthias Ringwald 151b3fcedb9SMatthias Ringwalddef write_16(fout, value): 152b3fcedb9SMatthias Ringwald fout.write('0x%02x, 0x%02x, ' % (value & 0xff, (value >> 8) & 0xff)) 153b3fcedb9SMatthias Ringwald 154b3fcedb9SMatthias Ringwalddef write_uuid(uuid): 155b3fcedb9SMatthias Ringwald for byte in uuid: 156b3fcedb9SMatthias Ringwald fout.write( "0x%02x, " % byte) 157b3fcedb9SMatthias Ringwald 158b3fcedb9SMatthias Ringwalddef write_string(fout, text): 159b3fcedb9SMatthias Ringwald for l in text.lstrip('"').rstrip('"'): 160b3fcedb9SMatthias Ringwald write_8(fout, ord(l)) 161b3fcedb9SMatthias Ringwald 162b3fcedb9SMatthias Ringwalddef write_sequence(fout, text): 163b3fcedb9SMatthias Ringwald parts = text.split() 164b3fcedb9SMatthias Ringwald for part in parts: 165b3fcedb9SMatthias Ringwald fout.write("0x%s, " % (part.strip())) 166b3fcedb9SMatthias Ringwald 167b3fcedb9SMatthias Ringwalddef write_indent(fout): 168b3fcedb9SMatthias Ringwald fout.write(" ") 169b3fcedb9SMatthias Ringwald 170b3fcedb9SMatthias Ringwalddef is_string(text): 171b3fcedb9SMatthias Ringwald for item in text.split(" "): 172b3fcedb9SMatthias Ringwald if not all(c in string.hexdigits for c in item): 173b3fcedb9SMatthias Ringwald return True 174b3fcedb9SMatthias Ringwald return False 175b3fcedb9SMatthias Ringwald 176b3fcedb9SMatthias Ringwalddef add_client_characteristic_configuration(properties): 177b3fcedb9SMatthias Ringwald return properties & (property_flags['NOTIFY'] | property_flags['INDICATE']) 178b3fcedb9SMatthias Ringwald 179*729074c4SMatthias Ringwalddef serviceDefinitionComplete(fout): 180*729074c4SMatthias Ringwald global services 181*729074c4SMatthias Ringwald if current_service_uuid_string: 182*729074c4SMatthias Ringwald fout.write("\n") 183*729074c4SMatthias Ringwald # print("append service %s = [%d, %d]" % (current_characteristic_uuid_string, current_service_start_handle, handle-1)) 184*729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_START_HANDLE 0x%04x' % (current_service_uuid_string, current_service_start_handle)) 185*729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_END_HANDLE 0x%04x' % (current_service_uuid_string, handle-1)) 186*729074c4SMatthias Ringwald services[current_service_uuid_string] = [current_service_start_handle, handle-1] 187*729074c4SMatthias Ringwald 188b3fcedb9SMatthias Ringwalddef parseService(fout, parts, service_type): 189b3fcedb9SMatthias Ringwald global handle 190b3fcedb9SMatthias Ringwald global total_size 191b3fcedb9SMatthias Ringwald global current_service_uuid_string 192b3fcedb9SMatthias Ringwald global current_service_start_handle 193b3fcedb9SMatthias Ringwald 194*729074c4SMatthias Ringwald serviceDefinitionComplete(fout) 195b3fcedb9SMatthias Ringwald 196b3fcedb9SMatthias Ringwald property = property_flags['READ']; 197b3fcedb9SMatthias Ringwald 198b3fcedb9SMatthias Ringwald write_indent(fout) 199b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts))) 200b3fcedb9SMatthias Ringwald 201b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 202b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 203b3fcedb9SMatthias Ringwald 204b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + uuid_size + 2 205b3fcedb9SMatthias Ringwald 206b3fcedb9SMatthias Ringwald if service_type == 0x2802: 207b3fcedb9SMatthias Ringwald size += 4 208b3fcedb9SMatthias Ringwald 209b3fcedb9SMatthias Ringwald write_indent(fout) 210b3fcedb9SMatthias Ringwald write_16(fout, size) 211b3fcedb9SMatthias Ringwald write_16(fout, property) 212b3fcedb9SMatthias Ringwald write_16(fout, handle) 213b3fcedb9SMatthias Ringwald write_16(fout, service_type) 214b3fcedb9SMatthias Ringwald write_uuid(uuid) 215b3fcedb9SMatthias Ringwald fout.write("\n") 216b3fcedb9SMatthias Ringwald 217*729074c4SMatthias Ringwald current_service_uuid_string = c_string_for_uuid(parts[1]) 218b3fcedb9SMatthias Ringwald current_service_start_handle = handle 219b3fcedb9SMatthias Ringwald handle = handle + 1 220b3fcedb9SMatthias Ringwald total_size = total_size + size 221b3fcedb9SMatthias Ringwald 222b3fcedb9SMatthias Ringwalddef parsePrimaryService(fout, parts): 223b3fcedb9SMatthias Ringwald parseService(fout, parts, 0x2800) 224b3fcedb9SMatthias Ringwald 225b3fcedb9SMatthias Ringwalddef parseSecondaryService(fout, parts): 226b3fcedb9SMatthias Ringwald parseService(fout, parts, 0x2801) 227b3fcedb9SMatthias Ringwald 228b3fcedb9SMatthias Ringwalddef parseIncludeService(fout, parts): 229b3fcedb9SMatthias Ringwald global handle 230b3fcedb9SMatthias Ringwald global total_size 231b3fcedb9SMatthias Ringwald 232b3fcedb9SMatthias Ringwald property = property_flags['READ']; 233b3fcedb9SMatthias Ringwald 234b3fcedb9SMatthias Ringwald write_indent(fout) 235b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts))) 236b3fcedb9SMatthias Ringwald 237b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 238b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 239b3fcedb9SMatthias Ringwald if uuid_size > 2: 240b3fcedb9SMatthias Ringwald uuid_size = 0 241*729074c4SMatthias Ringwald # print("Include Service ", c_string_for_uuid(uuid)) 242b3fcedb9SMatthias Ringwald 243b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 4 + uuid_size 244b3fcedb9SMatthias Ringwald 245*729074c4SMatthias Ringwald keyUUID = c_string_for_uuid(parts[1]) 246b3fcedb9SMatthias Ringwald 247b3fcedb9SMatthias Ringwald write_indent(fout) 248b3fcedb9SMatthias Ringwald write_16(fout, size) 249b3fcedb9SMatthias Ringwald write_16(fout, property) 250b3fcedb9SMatthias Ringwald write_16(fout, handle) 251b3fcedb9SMatthias Ringwald write_16(fout, 0x2802) 252b3fcedb9SMatthias Ringwald write_16(fout, services[keyUUID][0]) 253b3fcedb9SMatthias Ringwald write_16(fout, services[keyUUID][1]) 254b3fcedb9SMatthias Ringwald if uuid_size > 0: 255b3fcedb9SMatthias Ringwald write_uuid(uuid) 256b3fcedb9SMatthias Ringwald fout.write("\n") 257b3fcedb9SMatthias Ringwald 258b3fcedb9SMatthias Ringwald handle = handle + 1 259b3fcedb9SMatthias Ringwald total_size = total_size + size 260b3fcedb9SMatthias Ringwald 261b3fcedb9SMatthias Ringwald 262b3fcedb9SMatthias Ringwalddef parseCharacteristic(fout, parts): 263b3fcedb9SMatthias Ringwald global handle 264b3fcedb9SMatthias Ringwald global total_size 265b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 266b3fcedb9SMatthias Ringwald global characteristic_indices 267b3fcedb9SMatthias Ringwald 268b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 269b3fcedb9SMatthias Ringwald 270b3fcedb9SMatthias Ringwald # enumerate characteristics with same UUID, using optional name tag if available 271b3fcedb9SMatthias Ringwald current_characteristic_uuid_string = c_string_for_uuid(parts[1]); 272b3fcedb9SMatthias Ringwald index = 1 273b3fcedb9SMatthias Ringwald if current_characteristic_uuid_string in characteristic_indices: 274b3fcedb9SMatthias Ringwald index = characteristic_indices[current_characteristic_uuid_string] + 1 275b3fcedb9SMatthias Ringwald characteristic_indices[current_characteristic_uuid_string] = index 276b3fcedb9SMatthias Ringwald if len(parts) > 4: 277b3fcedb9SMatthias Ringwald current_characteristic_uuid_string += '_' + parts[4].upper().replace(' ','_') 278b3fcedb9SMatthias Ringwald else: 279b3fcedb9SMatthias Ringwald current_characteristic_uuid_string += ('_%02x' % index) 280b3fcedb9SMatthias Ringwald 281b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 282b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 283b3fcedb9SMatthias Ringwald properties = parseProperties(parts[2]) 284b3fcedb9SMatthias Ringwald value = ', '.join([str(x) for x in parts[3:]]) 285b3fcedb9SMatthias Ringwald 286b3fcedb9SMatthias Ringwald # reliable writes is defined in an extended properties 287b3fcedb9SMatthias Ringwald if (properties & property_flags['RELIABLE_WRITE']): 288b3fcedb9SMatthias Ringwald properties = properties | property_flags['EXTENDED_PROPERTIES'] 289b3fcedb9SMatthias Ringwald 290b3fcedb9SMatthias Ringwald write_indent(fout) 291b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts[0:3]))) 292b3fcedb9SMatthias Ringwald 293b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + (1+2+uuid_size) 294b3fcedb9SMatthias Ringwald write_indent(fout) 295b3fcedb9SMatthias Ringwald write_16(fout, size) 296b3fcedb9SMatthias Ringwald write_16(fout, property_read) 297b3fcedb9SMatthias Ringwald write_16(fout, handle) 298b3fcedb9SMatthias Ringwald write_16(fout, 0x2803) 299b3fcedb9SMatthias Ringwald write_8(fout, properties) 300b3fcedb9SMatthias Ringwald write_16(fout, handle+1) 301b3fcedb9SMatthias Ringwald write_uuid(uuid) 302b3fcedb9SMatthias Ringwald fout.write("\n") 303b3fcedb9SMatthias Ringwald handle = handle + 1 304b3fcedb9SMatthias Ringwald total_size = total_size + size 305b3fcedb9SMatthias Ringwald 306b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + uuid_size 307b3fcedb9SMatthias Ringwald if is_string(value): 308b3fcedb9SMatthias Ringwald size = size + len(value) 309b3fcedb9SMatthias Ringwald else: 310b3fcedb9SMatthias Ringwald size = size + len(value.split()) 311b3fcedb9SMatthias Ringwald 312b3fcedb9SMatthias Ringwald if uuid_size == 16: 313b3fcedb9SMatthias Ringwald properties = properties | property_flags['LONG_UUID']; 314b3fcedb9SMatthias Ringwald 315b3fcedb9SMatthias Ringwald write_indent(fout) 316b3fcedb9SMatthias Ringwald fout.write('// 0x%04x VALUE-%s-'"'%s'"'\n' % (handle, '-'.join(parts[1:3]),value)) 317b3fcedb9SMatthias Ringwald write_indent(fout) 318b3fcedb9SMatthias Ringwald write_16(fout, size) 319b3fcedb9SMatthias Ringwald write_16(fout, properties) 320b3fcedb9SMatthias Ringwald write_16(fout, handle) 321b3fcedb9SMatthias Ringwald write_uuid(uuid) 322b3fcedb9SMatthias Ringwald if is_string(value): 323b3fcedb9SMatthias Ringwald write_string(fout, value) 324b3fcedb9SMatthias Ringwald else: 325b3fcedb9SMatthias Ringwald write_sequence(fout,value) 326b3fcedb9SMatthias Ringwald 327b3fcedb9SMatthias Ringwald fout.write("\n") 328*729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_VALUE_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 329b3fcedb9SMatthias Ringwald handle = handle + 1 330b3fcedb9SMatthias Ringwald 331b3fcedb9SMatthias Ringwald if add_client_characteristic_configuration(properties): 332b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 2 333b3fcedb9SMatthias Ringwald write_indent(fout) 334b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CLIENT_CHARACTERISTIC_CONFIGURATION\n' % (handle)) 335b3fcedb9SMatthias Ringwald write_indent(fout) 336b3fcedb9SMatthias Ringwald write_16(fout, size) 337b3fcedb9SMatthias Ringwald write_16(fout, property_flags['READ'] | property_flags['WRITE'] | property_flags['DYNAMIC']) 338b3fcedb9SMatthias Ringwald write_16(fout, handle) 339b3fcedb9SMatthias Ringwald write_16(fout, 0x2902) 340b3fcedb9SMatthias Ringwald write_16(fout, 0) 341b3fcedb9SMatthias Ringwald fout.write("\n") 342*729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_CLIENT_CONFIGURATION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 343b3fcedb9SMatthias Ringwald handle = handle + 1 344b3fcedb9SMatthias Ringwald 345b3fcedb9SMatthias Ringwald if properties & property_flags['RELIABLE_WRITE']: 346b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 2 347b3fcedb9SMatthias Ringwald write_indent(fout) 348b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_EXTENDED_PROPERTIES\n' % (handle)) 349b3fcedb9SMatthias Ringwald write_indent(fout) 350b3fcedb9SMatthias Ringwald write_16(fout, size) 351b3fcedb9SMatthias Ringwald write_16(fout, property_flags['READ']) 352b3fcedb9SMatthias Ringwald write_16(fout, handle) 353b3fcedb9SMatthias Ringwald write_16(fout, 0x2900) 354b3fcedb9SMatthias Ringwald write_16(fout, 1) # Reliable Write 355b3fcedb9SMatthias Ringwald fout.write("\n") 356b3fcedb9SMatthias Ringwald handle = handle + 1 357b3fcedb9SMatthias Ringwald 358b3fcedb9SMatthias Ringwalddef parseCharacteristicUserDescription(fout, parts): 359b3fcedb9SMatthias Ringwald global handle 360b3fcedb9SMatthias Ringwald global total_size 361b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 362b3fcedb9SMatthias Ringwald 363b3fcedb9SMatthias Ringwald properties = parseProperties(parts[1]) 364b3fcedb9SMatthias Ringwald value = parts[2] 365b3fcedb9SMatthias Ringwald 366b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 367b3fcedb9SMatthias Ringwald if is_string(value): 368b3fcedb9SMatthias Ringwald size = size + len(value) - 2 369b3fcedb9SMatthias Ringwald else: 370b3fcedb9SMatthias Ringwald size = size + len(value.split()) 371b3fcedb9SMatthias Ringwald 372b3fcedb9SMatthias Ringwald write_indent(fout) 373b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_USER_DESCRIPTION-%s\n' % (handle, '-'.join(parts[1:]))) 374b3fcedb9SMatthias Ringwald write_indent(fout) 375b3fcedb9SMatthias Ringwald write_16(fout, size) 376b3fcedb9SMatthias Ringwald write_16(fout, properties) 377b3fcedb9SMatthias Ringwald write_16(fout, handle) 378b3fcedb9SMatthias Ringwald write_16(fout, 0x2901) 379b3fcedb9SMatthias Ringwald if is_string(value): 380b3fcedb9SMatthias Ringwald write_string(fout, value) 381b3fcedb9SMatthias Ringwald else: 382b3fcedb9SMatthias Ringwald write_sequence(fout,value) 383b3fcedb9SMatthias Ringwald fout.write("\n") 384*729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_USER_DESCRIPTION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 385b3fcedb9SMatthias Ringwald handle = handle + 1 386b3fcedb9SMatthias Ringwald 387b3fcedb9SMatthias Ringwalddef parseServerCharacteristicConfiguration(fout, parts): 388b3fcedb9SMatthias Ringwald global handle 389b3fcedb9SMatthias Ringwald global total_size 390b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 391b3fcedb9SMatthias Ringwald 392b3fcedb9SMatthias Ringwald properties = parseProperties(parts[1]) 393b3fcedb9SMatthias Ringwald properties = properties | property_flags['DYNAMIC'] 394b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 395b3fcedb9SMatthias Ringwald 396b3fcedb9SMatthias Ringwald write_indent(fout) 397b3fcedb9SMatthias Ringwald fout.write('// 0x%04x SERVER_CHARACTERISTIC_CONFIGURATION-%s\n' % (handle, '-'.join(parts[1:]))) 398b3fcedb9SMatthias Ringwald write_indent(fout) 399b3fcedb9SMatthias Ringwald write_16(fout, size) 400b3fcedb9SMatthias Ringwald write_16(fout, properties) 401b3fcedb9SMatthias Ringwald write_16(fout, handle) 402b3fcedb9SMatthias Ringwald write_16(fout, 0x2903) 403b3fcedb9SMatthias Ringwald fout.write("\n") 404*729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_SERVER_CONFIGURATION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 405b3fcedb9SMatthias Ringwald handle = handle + 1 406b3fcedb9SMatthias Ringwald 407b3fcedb9SMatthias Ringwalddef parseCharacteristicFormat(fout, parts): 408b3fcedb9SMatthias Ringwald global handle 409b3fcedb9SMatthias Ringwald global total_size 410b3fcedb9SMatthias Ringwald 411b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 412b3fcedb9SMatthias Ringwald 413b3fcedb9SMatthias Ringwald identifier = parts[1] 414b3fcedb9SMatthias Ringwald presentation_formats[identifier] = handle 415b3fcedb9SMatthias Ringwald # print("format '%s' with handle %d\n" % (identifier, handle)) 416b3fcedb9SMatthias Ringwald 417b3fcedb9SMatthias Ringwald format = parts[2] 418b3fcedb9SMatthias Ringwald exponent = parts[3] 419b3fcedb9SMatthias Ringwald unit = parseUUID(parts[4]) 420b3fcedb9SMatthias Ringwald name_space = parts[5] 421b3fcedb9SMatthias Ringwald description = parseUUID(parts[6]) 422b3fcedb9SMatthias Ringwald 423b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 7 424b3fcedb9SMatthias Ringwald 425b3fcedb9SMatthias Ringwald write_indent(fout) 426b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_FORMAT-%s\n' % (handle, '-'.join(parts[1:]))) 427b3fcedb9SMatthias Ringwald write_indent(fout) 428b3fcedb9SMatthias Ringwald write_16(fout, size) 429b3fcedb9SMatthias Ringwald write_16(fout, property_read) 430b3fcedb9SMatthias Ringwald write_16(fout, handle) 431b3fcedb9SMatthias Ringwald write_16(fout, 0x2904) 432b3fcedb9SMatthias Ringwald write_sequence(fout, format) 433b3fcedb9SMatthias Ringwald write_sequence(fout, exponent) 434b3fcedb9SMatthias Ringwald write_uuid(unit) 435b3fcedb9SMatthias Ringwald write_sequence(fout, name_space) 436b3fcedb9SMatthias Ringwald write_uuid(description) 437b3fcedb9SMatthias Ringwald fout.write("\n") 438b3fcedb9SMatthias Ringwald handle = handle + 1 439b3fcedb9SMatthias Ringwald 440b3fcedb9SMatthias Ringwald 441b3fcedb9SMatthias Ringwalddef parseCharacteristicAggregateFormat(fout, parts): 442b3fcedb9SMatthias Ringwald global handle 443b3fcedb9SMatthias Ringwald global total_size 444b3fcedb9SMatthias Ringwald 445b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 446b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + (len(parts)-1) * 2 447b3fcedb9SMatthias Ringwald 448b3fcedb9SMatthias Ringwald write_indent(fout) 449b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_AGGREGATE_FORMAT-%s\n' % (handle, '-'.join(parts[1:]))) 450b3fcedb9SMatthias Ringwald write_indent(fout) 451b3fcedb9SMatthias Ringwald write_16(fout, size) 452b3fcedb9SMatthias Ringwald write_16(fout, property_read) 453b3fcedb9SMatthias Ringwald write_16(fout, handle) 454b3fcedb9SMatthias Ringwald write_16(fout, 0x2905) 455b3fcedb9SMatthias Ringwald for identifier in parts[1:]: 456b3fcedb9SMatthias Ringwald format_handle = presentation_formats[identifier] 457b3fcedb9SMatthias Ringwald if format == 0: 458b3fcedb9SMatthias Ringwald print("ERROR: identifier '%s' in CHARACTERISTIC_AGGREGATE_FORMAT undefined" % identifier) 459b3fcedb9SMatthias Ringwald sys.exit(1) 460b3fcedb9SMatthias Ringwald write_16(fout, format_handle) 461b3fcedb9SMatthias Ringwald fout.write("\n") 462b3fcedb9SMatthias Ringwald handle = handle + 1 463b3fcedb9SMatthias Ringwald 464b3fcedb9SMatthias Ringwalddef parseReportReference(fout, parts): 465b3fcedb9SMatthias Ringwald global handle 466b3fcedb9SMatthias Ringwald global total_size 467b3fcedb9SMatthias Ringwald 468b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 469b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 1 + 1 470b3fcedb9SMatthias Ringwald 471b3fcedb9SMatthias Ringwald report_id = parts[1] 472b3fcedb9SMatthias Ringwald report_type = parts[2] 473b3fcedb9SMatthias Ringwald 474b3fcedb9SMatthias Ringwald write_indent(fout) 475b3fcedb9SMatthias Ringwald fout.write('// 0x%04x REPORT_REFERENCE-%s\n' % (handle, '-'.join(parts[1:]))) 476b3fcedb9SMatthias Ringwald write_indent(fout) 477b3fcedb9SMatthias Ringwald write_16(fout, size) 478b3fcedb9SMatthias Ringwald write_16(fout, property_read) 479b3fcedb9SMatthias Ringwald write_16(fout, handle) 480b3fcedb9SMatthias Ringwald write_16(fout, 0x2908) 481b3fcedb9SMatthias Ringwald write_sequence(fout, report_id) 482b3fcedb9SMatthias Ringwald write_sequence(fout, report_type) 483b3fcedb9SMatthias Ringwald fout.write("\n") 484b3fcedb9SMatthias Ringwald handle = handle + 1 485b3fcedb9SMatthias Ringwald 486b3fcedb9SMatthias Ringwald 487b3fcedb9SMatthias Ringwalddef parseNumberOfDigitals(fout, parts): 488b3fcedb9SMatthias Ringwald global handle 489b3fcedb9SMatthias Ringwald global total_size 490b3fcedb9SMatthias Ringwald 491b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 492b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 1 493b3fcedb9SMatthias Ringwald 494b3fcedb9SMatthias Ringwald no_of_digitals = parts[1] 495b3fcedb9SMatthias Ringwald 496b3fcedb9SMatthias Ringwald write_indent(fout) 497b3fcedb9SMatthias Ringwald fout.write('// 0x%04x NUMBER_OF_DIGITALS-%s\n' % (handle, '-'.join(parts[1:]))) 498b3fcedb9SMatthias Ringwald write_indent(fout) 499b3fcedb9SMatthias Ringwald write_16(fout, size) 500b3fcedb9SMatthias Ringwald write_16(fout, property_read) 501b3fcedb9SMatthias Ringwald write_16(fout, handle) 502b3fcedb9SMatthias Ringwald write_16(fout, 0x2909) 503b3fcedb9SMatthias Ringwald write_sequence(fout, no_of_digitals) 504b3fcedb9SMatthias Ringwald fout.write("\n") 505b3fcedb9SMatthias Ringwald handle = handle + 1 506b3fcedb9SMatthias Ringwald 507b3fcedb9SMatthias Ringwald 508b3fcedb9SMatthias Ringwalddef parse(fname_in, fin, fname_out, fout): 509b3fcedb9SMatthias Ringwald global handle 510b3fcedb9SMatthias Ringwald global total_size 511b3fcedb9SMatthias Ringwald 512b3fcedb9SMatthias Ringwald fout.write(header.format(fname_out, fname_in)) 513b3fcedb9SMatthias Ringwald fout.write('{\n') 514b3fcedb9SMatthias Ringwald 515b165f97bSMatthias Ringwald line_count = 0; 516b3fcedb9SMatthias Ringwald for line in fin: 517b3fcedb9SMatthias Ringwald line = line.strip("\n\r ") 518b165f97bSMatthias Ringwald line_count += 1 519b3fcedb9SMatthias Ringwald 520b165f97bSMatthias Ringwald if line.startswith("//"): 521b165f97bSMatthias Ringwald fout.write("//" + line.lstrip('/') + '\n') 522b165f97bSMatthias Ringwald continue 523b165f97bSMatthias Ringwald 524b165f97bSMatthias Ringwald if line.startswith("#"): 525b165f97bSMatthias Ringwald print ("WARNING: #TODO in line %u not handled, skipping declaration:" % line_count) 526b165f97bSMatthias Ringwald print ("'%s'" % line) 527b165f97bSMatthias Ringwald fout.write("// " + line + '\n') 528b3fcedb9SMatthias Ringwald continue 529b3fcedb9SMatthias Ringwald 530b3fcedb9SMatthias Ringwald if len(line) == 0: 531b3fcedb9SMatthias Ringwald continue 532b3fcedb9SMatthias Ringwald 533b3fcedb9SMatthias Ringwald f = io.StringIO(line) 534b3fcedb9SMatthias Ringwald parts_list = csv.reader(f, delimiter=',', quotechar='"') 535b3fcedb9SMatthias Ringwald 536b3fcedb9SMatthias Ringwald for parts in parts_list: 537b3fcedb9SMatthias Ringwald for index, object in enumerate(parts): 538b3fcedb9SMatthias Ringwald parts[index] = object.strip().lstrip('"').rstrip('"') 539b3fcedb9SMatthias Ringwald 540b3fcedb9SMatthias Ringwald if parts[0] == 'PRIMARY_SERVICE': 541b3fcedb9SMatthias Ringwald parsePrimaryService(fout, parts) 542b3fcedb9SMatthias Ringwald continue 543b3fcedb9SMatthias Ringwald 544b3fcedb9SMatthias Ringwald if parts[0] == 'SECONDARY_SERVICE': 545b3fcedb9SMatthias Ringwald parseSecondaryService(fout, parts) 546b3fcedb9SMatthias Ringwald continue 547b3fcedb9SMatthias Ringwald 548b3fcedb9SMatthias Ringwald if parts[0] == 'INCLUDE_SERVICE': 549b3fcedb9SMatthias Ringwald parseIncludeService(fout, parts) 550b3fcedb9SMatthias Ringwald continue 551b3fcedb9SMatthias Ringwald 552b3fcedb9SMatthias Ringwald # 2803 553b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC': 554b3fcedb9SMatthias Ringwald parseCharacteristic(fout, parts) 555b3fcedb9SMatthias Ringwald continue 556b3fcedb9SMatthias Ringwald 557b3fcedb9SMatthias Ringwald # 2900 Characteristic Extended Properties 558b3fcedb9SMatthias Ringwald 559b3fcedb9SMatthias Ringwald # 2901 560b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_USER_DESCRIPTION': 561b3fcedb9SMatthias Ringwald parseCharacteristicUserDescription(fout, parts) 562b3fcedb9SMatthias Ringwald continue 563b3fcedb9SMatthias Ringwald 564b165f97bSMatthias Ringwald 565b165f97bSMatthias Ringwald # 2902 Client Characteristic Configuration - automatically included in Characteristic if 566b3fcedb9SMatthias Ringwald # notification / indication is supported 567b165f97bSMatthias Ringwald if parts[0] == 'CHARACTERISTIC_USER_DESCRIPTION': 568b165f97bSMatthias Ringwald continue 569b3fcedb9SMatthias Ringwald 570b3fcedb9SMatthias Ringwald # 2903 571b3fcedb9SMatthias Ringwald if parts[0] == 'SERVER_CHARACTERISTIC_CONFIGURATION': 572b3fcedb9SMatthias Ringwald parseServerCharacteristicConfiguration(fout, parts) 573b3fcedb9SMatthias Ringwald continue 574b3fcedb9SMatthias Ringwald 575b3fcedb9SMatthias Ringwald # 2904 576b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_FORMAT': 577b3fcedb9SMatthias Ringwald parseCharacteristicFormat(fout, parts) 578b3fcedb9SMatthias Ringwald continue 579b3fcedb9SMatthias Ringwald 580b3fcedb9SMatthias Ringwald # 2905 581b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_AGGREGATE_FORMAT': 582b3fcedb9SMatthias Ringwald parseCharacteristicAggregateFormat(fout, parts) 583b3fcedb9SMatthias Ringwald continue 584b3fcedb9SMatthias Ringwald 585b3fcedb9SMatthias Ringwald # 2906 586b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 587b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 588b3fcedb9SMatthias Ringwald continue 589b3fcedb9SMatthias Ringwald 590b3fcedb9SMatthias Ringwald # 2907 591b3fcedb9SMatthias Ringwald if parts[0] == 'EXTERNAL_REPORT_REFERENCE': 592b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 593b3fcedb9SMatthias Ringwald continue 594b3fcedb9SMatthias Ringwald 595b3fcedb9SMatthias Ringwald # 2908 596b3fcedb9SMatthias Ringwald if parts[0] == 'REPORT_REFERENCE': 597b3fcedb9SMatthias Ringwald parseReportReference(fout, parts) 598b3fcedb9SMatthias Ringwald continue 599b3fcedb9SMatthias Ringwald 600b3fcedb9SMatthias Ringwald # 2909 601b3fcedb9SMatthias Ringwald if parts[0] == 'NUMBER_OF_DIGITALS': 602b3fcedb9SMatthias Ringwald parseNumberOfDigitals(fout, parts) 603b3fcedb9SMatthias Ringwald continue 604b3fcedb9SMatthias Ringwald 605b3fcedb9SMatthias Ringwald # 290A 606b3fcedb9SMatthias Ringwald if parts[0] == 'VALUE_TRIGGER_SETTING': 607b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 608b3fcedb9SMatthias Ringwald continue 609b3fcedb9SMatthias Ringwald 610b3fcedb9SMatthias Ringwald # 290B 611b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_CONFIGURATION': 612b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 613b3fcedb9SMatthias Ringwald continue 614b3fcedb9SMatthias Ringwald 615b3fcedb9SMatthias Ringwald # 290C 616b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_MEASUREMENT': 617b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 618b3fcedb9SMatthias Ringwald continue 619b3fcedb9SMatthias Ringwald 620b3fcedb9SMatthias Ringwald # 290D 621b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_TRIGGER_SETTING': 622b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 623b3fcedb9SMatthias Ringwald continue 624b3fcedb9SMatthias Ringwald 625b3fcedb9SMatthias Ringwald # 2906 626b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 627b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 628b3fcedb9SMatthias Ringwald continue 629b3fcedb9SMatthias Ringwald 630b3fcedb9SMatthias Ringwald print("WARNING: unknown token: %s\n" % (parts[0])) 631b3fcedb9SMatthias Ringwald 632*729074c4SMatthias Ringwald serviceDefinitionComplete(fout) 633b3fcedb9SMatthias Ringwald write_indent(fout) 634b3fcedb9SMatthias Ringwald fout.write("// END\n"); 635b3fcedb9SMatthias Ringwald write_indent(fout) 636b3fcedb9SMatthias Ringwald write_16(fout,0) 637b3fcedb9SMatthias Ringwald fout.write("\n") 638b3fcedb9SMatthias Ringwald total_size = total_size + 2 639b3fcedb9SMatthias Ringwald 640b3fcedb9SMatthias Ringwald fout.write("}; // total size %u bytes \n" % total_size); 641b3fcedb9SMatthias Ringwald 642b3fcedb9SMatthias Ringwalddef listHandles(fout): 643b3fcedb9SMatthias Ringwald fout.write('\n\n') 644b3fcedb9SMatthias Ringwald fout.write('//\n') 645*729074c4SMatthias Ringwald fout.write('// list service handle ranges\n') 646*729074c4SMatthias Ringwald fout.write('//\n') 647*729074c4SMatthias Ringwald for define in defines_for_services: 648*729074c4SMatthias Ringwald fout.write(define) 649*729074c4SMatthias Ringwald fout.write('\n') 650*729074c4SMatthias Ringwald fout.write('\n') 651*729074c4SMatthias Ringwald fout.write('//\n') 652b3fcedb9SMatthias Ringwald fout.write('// list mapping between characteristics and handles\n') 653b3fcedb9SMatthias Ringwald fout.write('//\n') 654*729074c4SMatthias Ringwald for define in defines_for_characteristics: 655b3fcedb9SMatthias Ringwald fout.write(define) 656b3fcedb9SMatthias Ringwald fout.write('\n') 657b3fcedb9SMatthias Ringwald 658b3fcedb9SMatthias Ringwaldif (len(sys.argv) < 3): 659b3fcedb9SMatthias Ringwald print(usage) 660b3fcedb9SMatthias Ringwald sys.exit(1) 661b3fcedb9SMatthias Ringwaldtry: 662b165f97bSMatthias Ringwald # read defines from bluetooth_gatt.h 663b165f97bSMatthias Ringwald btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 664b165f97bSMatthias Ringwald gen_path = btstack_root + '/src/bluetooth_gatt.h' 665b165f97bSMatthias Ringwald bluetooth_gatt = read_defines(gen_path) 666b165f97bSMatthias Ringwald 667b3fcedb9SMatthias Ringwald filename = sys.argv[2] 668b3fcedb9SMatthias Ringwald fin = codecs.open (sys.argv[1], encoding='utf-8') 669b3fcedb9SMatthias Ringwald fout = open (filename, 'w') 670b3fcedb9SMatthias Ringwald parse(sys.argv[1], fin, filename, fout) 671b3fcedb9SMatthias Ringwald listHandles(fout) 672b3fcedb9SMatthias Ringwald fout.close() 673b165f97bSMatthias Ringwald print('Created %s' % filename) 674b3fcedb9SMatthias Ringwald 675b3fcedb9SMatthias Ringwaldexcept IOError as e: 676b3fcedb9SMatthias Ringwald print(usage) 677b3fcedb9SMatthias Ringwald sys.exit(1) 678b3fcedb9SMatthias Ringwald 679b3fcedb9SMatthias Ringwaldprint('Compilation successful!\n') 680