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 16*60b51a4cSMatthias Ringwaldimport sys 17b3fcedb9SMatthias Ringwald 18b3fcedb9SMatthias Ringwaldheader = ''' 19b3fcedb9SMatthias Ringwald// {0} generated from {1} for BTstack 20b3fcedb9SMatthias Ringwald 21b3fcedb9SMatthias Ringwald// binary representation 22b3fcedb9SMatthias Ringwald// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) 23b3fcedb9SMatthias Ringwald 24b3fcedb9SMatthias Ringwald#include <stdint.h> 25b3fcedb9SMatthias Ringwald 26b3fcedb9SMatthias Ringwaldconst uint8_t profile_data[] = 27b3fcedb9SMatthias Ringwald''' 28b3fcedb9SMatthias Ringwald 29b3fcedb9SMatthias Ringwaldusage = ''' 30b3fcedb9SMatthias RingwaldUsage: ./compile_gatt.py profile.gatt profile.h 31b3fcedb9SMatthias Ringwald''' 32b3fcedb9SMatthias Ringwald 33b3fcedb9SMatthias Ringwald 34b3fcedb9SMatthias Ringwaldprint(''' 35b3fcedb9SMatthias RingwaldBLE configuration generator for use with BTstack, v0.1 36b3fcedb9SMatthias RingwaldCopyright 2011 Matthias Ringwald 37b3fcedb9SMatthias Ringwald''') 38b3fcedb9SMatthias Ringwald 39b3fcedb9SMatthias Ringwaldassigned_uuids = { 40b3fcedb9SMatthias Ringwald 'GAP_SERVICE' : 0x1800, 41b3fcedb9SMatthias Ringwald 'GATT_SERVICE' : 0x1801, 42b3fcedb9SMatthias Ringwald 'GAP_DEVICE_NAME' : 0x2a00, 43b3fcedb9SMatthias Ringwald 'GAP_APPEARANCE' : 0x2a01, 44b3fcedb9SMatthias Ringwald 'GAP_PERIPHERAL_PRIVACY_FLAG' : 0x2A02, 45b3fcedb9SMatthias Ringwald 'GAP_RECONNECTION_ADDRESS' : 0x2A03, 46b3fcedb9SMatthias Ringwald 'GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS' : 0x2A04, 47b3fcedb9SMatthias Ringwald 'GATT_SERVICE_CHANGED' : 0x2a05, 48b3fcedb9SMatthias Ringwald} 49b3fcedb9SMatthias Ringwald 50b3fcedb9SMatthias Ringwaldproperty_flags = { 51b3fcedb9SMatthias Ringwald 'BROADCAST' : 0x01, 52b3fcedb9SMatthias Ringwald 'READ' : 0x02, 53b3fcedb9SMatthias Ringwald 'WRITE_WITHOUT_RESPONSE' : 0x04, 54b3fcedb9SMatthias Ringwald 'WRITE' : 0x08, 55b3fcedb9SMatthias Ringwald 'NOTIFY': 0x10, 56b3fcedb9SMatthias Ringwald 'INDICATE' : 0x20, 57b3fcedb9SMatthias Ringwald 'AUTHENTICATED_SIGNED_WRITE' : 0x40, 58b3fcedb9SMatthias Ringwald 'EXTENDED_PROPERTIES' : 0x80, 59b3fcedb9SMatthias Ringwald # custom BTstack extension 60b3fcedb9SMatthias Ringwald 'DYNAMIC': 0x100, 61b3fcedb9SMatthias Ringwald 'LONG_UUID': 0x200, 62b3fcedb9SMatthias Ringwald 'AUTHENTICATION_REQUIRED': 0x400, 63b3fcedb9SMatthias Ringwald 'AUTHORIZATION_REQUIRED': 0x800, 64b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_7': 0x6000, 65b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_8': 0x7000, 66b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_9': 0x8000, 67b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_10': 0x9000, 68b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_11': 0xa000, 69b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_12': 0xb000, 70b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_13': 0xc000, 71b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_14': 0xd000, 72b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_15': 0xe000, 73b3fcedb9SMatthias Ringwald 'ENCRYPTION_KEY_SIZE_16': 0xf000, 74b3fcedb9SMatthias Ringwald # only used by gatt compiler >= 0xffff 75b3fcedb9SMatthias Ringwald # Extended Properties 76b3fcedb9SMatthias Ringwald 'RELIABLE_WRITE': 0x10000, 77b3fcedb9SMatthias Ringwald} 78b3fcedb9SMatthias Ringwald 79*60b51a4cSMatthias Ringwaldbtstack_root = '' 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 = "" 86729074c4SMatthias Ringwalddefines_for_characteristics = [] 87729074c4SMatthias 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 179729074c4SMatthias Ringwalddef serviceDefinitionComplete(fout): 180729074c4SMatthias Ringwald global services 181729074c4SMatthias Ringwald if current_service_uuid_string: 182729074c4SMatthias Ringwald fout.write("\n") 183729074c4SMatthias Ringwald # print("append service %s = [%d, %d]" % (current_characteristic_uuid_string, current_service_start_handle, handle-1)) 184729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_START_HANDLE 0x%04x' % (current_service_uuid_string, current_service_start_handle)) 185729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_END_HANDLE 0x%04x' % (current_service_uuid_string, handle-1)) 186729074c4SMatthias Ringwald services[current_service_uuid_string] = [current_service_start_handle, handle-1] 187729074c4SMatthias 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 194729074c4SMatthias 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 217729074c4SMatthias 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 241729074c4SMatthias Ringwald # print("Include Service ", c_string_for_uuid(uuid)) 242b3fcedb9SMatthias Ringwald 243b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 4 + uuid_size 244b3fcedb9SMatthias Ringwald 245729074c4SMatthias 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") 328729074c4SMatthias 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") 342729074c4SMatthias 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") 384729074c4SMatthias 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") 404729074c4SMatthias 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 507*60b51a4cSMatthias Ringwalddef parseLines(fname_in, fin, fout): 508b3fcedb9SMatthias Ringwald global handle 509b3fcedb9SMatthias Ringwald global total_size 510b3fcedb9SMatthias Ringwald 511b165f97bSMatthias Ringwald line_count = 0; 512b3fcedb9SMatthias Ringwald for line in fin: 513b3fcedb9SMatthias Ringwald line = line.strip("\n\r ") 514b165f97bSMatthias Ringwald line_count += 1 515b3fcedb9SMatthias Ringwald 516b165f97bSMatthias Ringwald if line.startswith("//"): 517b165f97bSMatthias Ringwald fout.write(" //" + line.lstrip('/') + '\n') 518b165f97bSMatthias Ringwald continue 519b165f97bSMatthias Ringwald 520*60b51a4cSMatthias Ringwald if line.startswith("#import"): 521*60b51a4cSMatthias Ringwald imported_file = '' 522*60b51a4cSMatthias Ringwald parts = re.match('#import\s+<(.*)>\w*',line) 523*60b51a4cSMatthias Ringwald if parts and len(parts.groups()) == 1: 524*60b51a4cSMatthias Ringwald imported_file = btstack_root+'/src/ble/' + parts.groups()[0] 525*60b51a4cSMatthias Ringwald parts = re.match('#import\s+"(.*)"\w*',line) 526*60b51a4cSMatthias Ringwald if parts and len(parts.groups()) == 1: 527*60b51a4cSMatthias Ringwald imported_file = os.path.abspath(os.path.dirname(fname_in) + '/'+parts.groups()[0]) 528*60b51a4cSMatthias Ringwald if len(imported_file) == 0: 529*60b51a4cSMatthias Ringwald print('ERROR: #import in file %s - line %u neither <name.gatt> nor "name.gatt" form', (fname_in, line_count)) 530*60b51a4cSMatthias Ringwald continue 531*60b51a4cSMatthias Ringwald 532*60b51a4cSMatthias Ringwald print("Importing %s" % imported_file) 533*60b51a4cSMatthias Ringwald try: 534*60b51a4cSMatthias Ringwald imported_fin = codecs.open (imported_file, encoding='utf-8') 535*60b51a4cSMatthias Ringwald fout.write(' // ' + line + ' -- BEGIN\n') 536*60b51a4cSMatthias Ringwald parseLines(imported_file, imported_fin, fout) 537*60b51a4cSMatthias Ringwald fout.write(' // ' + line + ' -- END\n') 538*60b51a4cSMatthias Ringwald except IOError as e: 539*60b51a4cSMatthias Ringwald print('ERROR: Import failed. Please check path.') 540*60b51a4cSMatthias Ringwald 541*60b51a4cSMatthias Ringwald continue 542*60b51a4cSMatthias Ringwald 543*60b51a4cSMatthias Ringwald if line.startswith("#TODO"): 544*60b51a4cSMatthias Ringwald print ("WARNING: #TODO in file %s - line %u not handled, skipping declaration:" % (fname_in, line_count)) 545b165f97bSMatthias Ringwald print ("'%s'" % line) 546b165f97bSMatthias Ringwald fout.write("// " + line + '\n') 547b3fcedb9SMatthias Ringwald continue 548b3fcedb9SMatthias Ringwald 549b3fcedb9SMatthias Ringwald if len(line) == 0: 550b3fcedb9SMatthias Ringwald continue 551b3fcedb9SMatthias Ringwald 552b3fcedb9SMatthias Ringwald f = io.StringIO(line) 553b3fcedb9SMatthias Ringwald parts_list = csv.reader(f, delimiter=',', quotechar='"') 554b3fcedb9SMatthias Ringwald 555b3fcedb9SMatthias Ringwald for parts in parts_list: 556b3fcedb9SMatthias Ringwald for index, object in enumerate(parts): 557b3fcedb9SMatthias Ringwald parts[index] = object.strip().lstrip('"').rstrip('"') 558b3fcedb9SMatthias Ringwald 559b3fcedb9SMatthias Ringwald if parts[0] == 'PRIMARY_SERVICE': 560b3fcedb9SMatthias Ringwald parsePrimaryService(fout, parts) 561b3fcedb9SMatthias Ringwald continue 562b3fcedb9SMatthias Ringwald 563b3fcedb9SMatthias Ringwald if parts[0] == 'SECONDARY_SERVICE': 564b3fcedb9SMatthias Ringwald parseSecondaryService(fout, parts) 565b3fcedb9SMatthias Ringwald continue 566b3fcedb9SMatthias Ringwald 567b3fcedb9SMatthias Ringwald if parts[0] == 'INCLUDE_SERVICE': 568b3fcedb9SMatthias Ringwald parseIncludeService(fout, parts) 569b3fcedb9SMatthias Ringwald continue 570b3fcedb9SMatthias Ringwald 571b3fcedb9SMatthias Ringwald # 2803 572b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC': 573b3fcedb9SMatthias Ringwald parseCharacteristic(fout, parts) 574b3fcedb9SMatthias Ringwald continue 575b3fcedb9SMatthias Ringwald 576b3fcedb9SMatthias Ringwald # 2900 Characteristic Extended Properties 577b3fcedb9SMatthias Ringwald 578b3fcedb9SMatthias Ringwald # 2901 579b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_USER_DESCRIPTION': 580b3fcedb9SMatthias Ringwald parseCharacteristicUserDescription(fout, parts) 581b3fcedb9SMatthias Ringwald continue 582b3fcedb9SMatthias Ringwald 583b165f97bSMatthias Ringwald 584b165f97bSMatthias Ringwald # 2902 Client Characteristic Configuration - automatically included in Characteristic if 585b3fcedb9SMatthias Ringwald # notification / indication is supported 586b165f97bSMatthias Ringwald if parts[0] == 'CHARACTERISTIC_USER_DESCRIPTION': 587b165f97bSMatthias Ringwald continue 588b3fcedb9SMatthias Ringwald 589b3fcedb9SMatthias Ringwald # 2903 590b3fcedb9SMatthias Ringwald if parts[0] == 'SERVER_CHARACTERISTIC_CONFIGURATION': 591b3fcedb9SMatthias Ringwald parseServerCharacteristicConfiguration(fout, parts) 592b3fcedb9SMatthias Ringwald continue 593b3fcedb9SMatthias Ringwald 594b3fcedb9SMatthias Ringwald # 2904 595b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_FORMAT': 596b3fcedb9SMatthias Ringwald parseCharacteristicFormat(fout, parts) 597b3fcedb9SMatthias Ringwald continue 598b3fcedb9SMatthias Ringwald 599b3fcedb9SMatthias Ringwald # 2905 600b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_AGGREGATE_FORMAT': 601b3fcedb9SMatthias Ringwald parseCharacteristicAggregateFormat(fout, parts) 602b3fcedb9SMatthias Ringwald continue 603b3fcedb9SMatthias Ringwald 604b3fcedb9SMatthias Ringwald # 2906 605b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 606b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 607b3fcedb9SMatthias Ringwald continue 608b3fcedb9SMatthias Ringwald 609b3fcedb9SMatthias Ringwald # 2907 610b3fcedb9SMatthias Ringwald if parts[0] == 'EXTERNAL_REPORT_REFERENCE': 611b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 612b3fcedb9SMatthias Ringwald continue 613b3fcedb9SMatthias Ringwald 614b3fcedb9SMatthias Ringwald # 2908 615b3fcedb9SMatthias Ringwald if parts[0] == 'REPORT_REFERENCE': 616b3fcedb9SMatthias Ringwald parseReportReference(fout, parts) 617b3fcedb9SMatthias Ringwald continue 618b3fcedb9SMatthias Ringwald 619b3fcedb9SMatthias Ringwald # 2909 620b3fcedb9SMatthias Ringwald if parts[0] == 'NUMBER_OF_DIGITALS': 621b3fcedb9SMatthias Ringwald parseNumberOfDigitals(fout, parts) 622b3fcedb9SMatthias Ringwald continue 623b3fcedb9SMatthias Ringwald 624b3fcedb9SMatthias Ringwald # 290A 625b3fcedb9SMatthias Ringwald if parts[0] == 'VALUE_TRIGGER_SETTING': 626b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 627b3fcedb9SMatthias Ringwald continue 628b3fcedb9SMatthias Ringwald 629b3fcedb9SMatthias Ringwald # 290B 630b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_CONFIGURATION': 631b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 632b3fcedb9SMatthias Ringwald continue 633b3fcedb9SMatthias Ringwald 634b3fcedb9SMatthias Ringwald # 290C 635b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_MEASUREMENT': 636b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 637b3fcedb9SMatthias Ringwald continue 638b3fcedb9SMatthias Ringwald 639b3fcedb9SMatthias Ringwald # 290D 640b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_TRIGGER_SETTING': 641b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 642b3fcedb9SMatthias Ringwald continue 643b3fcedb9SMatthias Ringwald 644b3fcedb9SMatthias Ringwald # 2906 645b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 646b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 647b3fcedb9SMatthias Ringwald continue 648b3fcedb9SMatthias Ringwald 649b3fcedb9SMatthias Ringwald print("WARNING: unknown token: %s\n" % (parts[0])) 650b3fcedb9SMatthias Ringwald 651*60b51a4cSMatthias Ringwalddef parse(fname_in, fin, fname_out, fout): 652*60b51a4cSMatthias Ringwald global handle 653*60b51a4cSMatthias Ringwald global total_size 654*60b51a4cSMatthias Ringwald 655*60b51a4cSMatthias Ringwald fout.write(header.format(fname_out, fname_in)) 656*60b51a4cSMatthias Ringwald fout.write('{\n') 657*60b51a4cSMatthias Ringwald 658*60b51a4cSMatthias Ringwald parseLines(fname_in, fin, fout) 659*60b51a4cSMatthias Ringwald 660729074c4SMatthias Ringwald serviceDefinitionComplete(fout) 661b3fcedb9SMatthias Ringwald write_indent(fout) 662b3fcedb9SMatthias Ringwald fout.write("// END\n"); 663b3fcedb9SMatthias Ringwald write_indent(fout) 664b3fcedb9SMatthias Ringwald write_16(fout,0) 665b3fcedb9SMatthias Ringwald fout.write("\n") 666b3fcedb9SMatthias Ringwald total_size = total_size + 2 667b3fcedb9SMatthias Ringwald 668b3fcedb9SMatthias Ringwald fout.write("}; // total size %u bytes \n" % total_size); 669b3fcedb9SMatthias Ringwald 670b3fcedb9SMatthias Ringwalddef listHandles(fout): 671b3fcedb9SMatthias Ringwald fout.write('\n\n') 672b3fcedb9SMatthias Ringwald fout.write('//\n') 673729074c4SMatthias Ringwald fout.write('// list service handle ranges\n') 674729074c4SMatthias Ringwald fout.write('//\n') 675729074c4SMatthias Ringwald for define in defines_for_services: 676729074c4SMatthias Ringwald fout.write(define) 677729074c4SMatthias Ringwald fout.write('\n') 678729074c4SMatthias Ringwald fout.write('\n') 679729074c4SMatthias Ringwald fout.write('//\n') 680b3fcedb9SMatthias Ringwald fout.write('// list mapping between characteristics and handles\n') 681b3fcedb9SMatthias Ringwald fout.write('//\n') 682729074c4SMatthias Ringwald for define in defines_for_characteristics: 683b3fcedb9SMatthias Ringwald fout.write(define) 684b3fcedb9SMatthias Ringwald fout.write('\n') 685b3fcedb9SMatthias Ringwald 686b3fcedb9SMatthias Ringwaldif (len(sys.argv) < 3): 687b3fcedb9SMatthias Ringwald print(usage) 688b3fcedb9SMatthias Ringwald sys.exit(1) 689b3fcedb9SMatthias Ringwaldtry: 690b165f97bSMatthias Ringwald # read defines from bluetooth_gatt.h 691b165f97bSMatthias Ringwald btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 692b165f97bSMatthias Ringwald gen_path = btstack_root + '/src/bluetooth_gatt.h' 693b165f97bSMatthias Ringwald bluetooth_gatt = read_defines(gen_path) 694b165f97bSMatthias Ringwald 695b3fcedb9SMatthias Ringwald filename = sys.argv[2] 696b3fcedb9SMatthias Ringwald fin = codecs.open (sys.argv[1], encoding='utf-8') 697b3fcedb9SMatthias Ringwald fout = open (filename, 'w') 698b3fcedb9SMatthias Ringwald parse(sys.argv[1], fin, filename, fout) 699b3fcedb9SMatthias Ringwald listHandles(fout) 700b3fcedb9SMatthias Ringwald fout.close() 701b165f97bSMatthias Ringwald print('Created %s' % filename) 702b3fcedb9SMatthias Ringwald 703b3fcedb9SMatthias Ringwaldexcept IOError as e: 704b3fcedb9SMatthias Ringwald print(usage) 705b3fcedb9SMatthias Ringwald sys.exit(1) 706b3fcedb9SMatthias Ringwald 707b3fcedb9SMatthias Ringwaldprint('Compilation successful!\n') 708