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 1660b51a4cSMatthias 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 = { 51*eb6072adSMatthias Ringwald # GATT Characteristic Properties 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, 75*eb6072adSMatthias Ringwald 76b3fcedb9SMatthias Ringwald # only used by gatt compiler >= 0xffff 77b3fcedb9SMatthias Ringwald # Extended Properties 78b3fcedb9SMatthias Ringwald 'RELIABLE_WRITE': 0x10000, 79*eb6072adSMatthias Ringwald 80*eb6072adSMatthias Ringwald # Broadcast, Notify, Indicate, Extended Properties are only used to describe a GATT Characteristic, but are free to use with att_db 81*eb6072adSMatthias Ringwald 'READ_WITHOUT_AUTHENTICATION': 0x0001, 82*eb6072adSMatthias Ringwald # 0x10 83*eb6072adSMatthias Ringwald # 0x20 84*eb6072adSMatthias Ringwald # 0x80 85b3fcedb9SMatthias Ringwald} 86b3fcedb9SMatthias Ringwald 8760b51a4cSMatthias Ringwaldbtstack_root = '' 88b3fcedb9SMatthias Ringwaldservices = dict() 89b3fcedb9SMatthias Ringwaldcharacteristic_indices = dict() 90b3fcedb9SMatthias Ringwaldpresentation_formats = dict() 91b3fcedb9SMatthias Ringwaldcurrent_service_uuid_string = "" 92b3fcedb9SMatthias Ringwaldcurrent_service_start_handle = 0 93b3fcedb9SMatthias Ringwaldcurrent_characteristic_uuid_string = "" 94729074c4SMatthias Ringwalddefines_for_characteristics = [] 95729074c4SMatthias Ringwalddefines_for_services = [] 96b3fcedb9SMatthias Ringwald 97b3fcedb9SMatthias Ringwaldhandle = 1 98b3fcedb9SMatthias Ringwaldtotal_size = 0 99b3fcedb9SMatthias Ringwald 100b165f97bSMatthias Ringwalddef read_defines(infile): 101b165f97bSMatthias Ringwald defines = dict() 102b165f97bSMatthias Ringwald with open (infile, 'rt') as fin: 103b165f97bSMatthias Ringwald for line in fin: 104b165f97bSMatthias Ringwald parts = re.match('#define\s+(\w+)\s+(\w+)',line) 105b165f97bSMatthias Ringwald if parts and len(parts.groups()) == 2: 106b165f97bSMatthias Ringwald (key, value) = parts.groups() 107b165f97bSMatthias Ringwald defines[key] = int(value, 16) 108b165f97bSMatthias Ringwald return defines 109b165f97bSMatthias Ringwald 110b3fcedb9SMatthias Ringwalddef keyForUUID(uuid): 111b3fcedb9SMatthias Ringwald keyUUID = "" 112b3fcedb9SMatthias Ringwald for i in uuid: 113b3fcedb9SMatthias Ringwald keyUUID += "%02x" % i 114b3fcedb9SMatthias Ringwald return keyUUID 115b3fcedb9SMatthias Ringwald 116b3fcedb9SMatthias Ringwalddef c_string_for_uuid(uuid): 117b3fcedb9SMatthias Ringwald return uuid.replace('-', '_') 118b3fcedb9SMatthias Ringwald 119b3fcedb9SMatthias Ringwalddef twoByteLEFor(value): 120b3fcedb9SMatthias Ringwald return [ (value & 0xff), (value >> 8)] 121b3fcedb9SMatthias Ringwald 122b3fcedb9SMatthias Ringwalddef is_128bit_uuid(text): 123b3fcedb9SMatthias 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): 124b3fcedb9SMatthias Ringwald return True 125b3fcedb9SMatthias Ringwald return False 126b3fcedb9SMatthias Ringwald 127b3fcedb9SMatthias Ringwalddef parseUUID128(uuid): 128b3fcedb9SMatthias 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) 129b3fcedb9SMatthias Ringwald uuid_bytes = [] 130b3fcedb9SMatthias Ringwald for i in range(8, 0, -1): 131b3fcedb9SMatthias Ringwald uuid_bytes = uuid_bytes + twoByteLEFor(int(parts.group(i),16)) 132b3fcedb9SMatthias Ringwald return uuid_bytes 133b3fcedb9SMatthias Ringwald 134b3fcedb9SMatthias Ringwalddef parseUUID(uuid): 135b3fcedb9SMatthias Ringwald if uuid in assigned_uuids: 136b3fcedb9SMatthias Ringwald return twoByteLEFor(assigned_uuids[uuid]) 137b165f97bSMatthias Ringwald uuid_upper = uuid.upper().replace('.','_') 138b165f97bSMatthias Ringwald if uuid_upper in bluetooth_gatt: 139b165f97bSMatthias Ringwald return twoByteLEFor(bluetooth_gatt[uuid_upper]) 140b3fcedb9SMatthias Ringwald if is_128bit_uuid(uuid): 141b3fcedb9SMatthias Ringwald return parseUUID128(uuid) 142b3fcedb9SMatthias Ringwald uuidInt = int(uuid, 16) 143b3fcedb9SMatthias Ringwald return twoByteLEFor(uuidInt) 144b3fcedb9SMatthias Ringwald 145b3fcedb9SMatthias Ringwalddef parseProperties(properties): 146b3fcedb9SMatthias Ringwald value = 0 147b3fcedb9SMatthias Ringwald parts = properties.split("|") 148b3fcedb9SMatthias Ringwald for property in parts: 149b3fcedb9SMatthias Ringwald property = property.strip() 150b3fcedb9SMatthias Ringwald if property in property_flags: 151b3fcedb9SMatthias Ringwald value |= property_flags[property] 152b3fcedb9SMatthias Ringwald else: 153b3fcedb9SMatthias Ringwald print("WARNING: property %s undefined" % (property)) 154b3fcedb9SMatthias Ringwald return value 155b3fcedb9SMatthias Ringwald 156b3fcedb9SMatthias Ringwalddef write_8(fout, value): 157b3fcedb9SMatthias Ringwald fout.write( "0x%02x, " % (value & 0xff)) 158b3fcedb9SMatthias Ringwald 159b3fcedb9SMatthias Ringwalddef write_16(fout, value): 160b3fcedb9SMatthias Ringwald fout.write('0x%02x, 0x%02x, ' % (value & 0xff, (value >> 8) & 0xff)) 161b3fcedb9SMatthias Ringwald 162b3fcedb9SMatthias Ringwalddef write_uuid(uuid): 163b3fcedb9SMatthias Ringwald for byte in uuid: 164b3fcedb9SMatthias Ringwald fout.write( "0x%02x, " % byte) 165b3fcedb9SMatthias Ringwald 166b3fcedb9SMatthias Ringwalddef write_string(fout, text): 167b3fcedb9SMatthias Ringwald for l in text.lstrip('"').rstrip('"'): 168b3fcedb9SMatthias Ringwald write_8(fout, ord(l)) 169b3fcedb9SMatthias Ringwald 170b3fcedb9SMatthias Ringwalddef write_sequence(fout, text): 171b3fcedb9SMatthias Ringwald parts = text.split() 172b3fcedb9SMatthias Ringwald for part in parts: 173b3fcedb9SMatthias Ringwald fout.write("0x%s, " % (part.strip())) 174b3fcedb9SMatthias Ringwald 175b3fcedb9SMatthias Ringwalddef write_indent(fout): 176b3fcedb9SMatthias Ringwald fout.write(" ") 177b3fcedb9SMatthias Ringwald 178b3fcedb9SMatthias Ringwalddef is_string(text): 179b3fcedb9SMatthias Ringwald for item in text.split(" "): 180b3fcedb9SMatthias Ringwald if not all(c in string.hexdigits for c in item): 181b3fcedb9SMatthias Ringwald return True 182b3fcedb9SMatthias Ringwald return False 183b3fcedb9SMatthias Ringwald 184b3fcedb9SMatthias Ringwalddef add_client_characteristic_configuration(properties): 185b3fcedb9SMatthias Ringwald return properties & (property_flags['NOTIFY'] | property_flags['INDICATE']) 186b3fcedb9SMatthias Ringwald 187729074c4SMatthias Ringwalddef serviceDefinitionComplete(fout): 188729074c4SMatthias Ringwald global services 189729074c4SMatthias Ringwald if current_service_uuid_string: 190729074c4SMatthias Ringwald fout.write("\n") 191729074c4SMatthias Ringwald # print("append service %s = [%d, %d]" % (current_characteristic_uuid_string, current_service_start_handle, handle-1)) 192729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_START_HANDLE 0x%04x' % (current_service_uuid_string, current_service_start_handle)) 193729074c4SMatthias Ringwald defines_for_services.append('#define ATT_SERVICE_%s_END_HANDLE 0x%04x' % (current_service_uuid_string, handle-1)) 194729074c4SMatthias Ringwald services[current_service_uuid_string] = [current_service_start_handle, handle-1] 195729074c4SMatthias Ringwald 196b3fcedb9SMatthias Ringwalddef parseService(fout, parts, service_type): 197b3fcedb9SMatthias Ringwald global handle 198b3fcedb9SMatthias Ringwald global total_size 199b3fcedb9SMatthias Ringwald global current_service_uuid_string 200b3fcedb9SMatthias Ringwald global current_service_start_handle 201b3fcedb9SMatthias Ringwald 202729074c4SMatthias Ringwald serviceDefinitionComplete(fout) 203b3fcedb9SMatthias Ringwald 204b3fcedb9SMatthias Ringwald property = property_flags['READ']; 205b3fcedb9SMatthias Ringwald 206b3fcedb9SMatthias Ringwald write_indent(fout) 207b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts))) 208b3fcedb9SMatthias Ringwald 209b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 210b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 211b3fcedb9SMatthias Ringwald 212b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + uuid_size + 2 213b3fcedb9SMatthias Ringwald 214b3fcedb9SMatthias Ringwald if service_type == 0x2802: 215b3fcedb9SMatthias Ringwald size += 4 216b3fcedb9SMatthias Ringwald 217b3fcedb9SMatthias Ringwald write_indent(fout) 218b3fcedb9SMatthias Ringwald write_16(fout, size) 219b3fcedb9SMatthias Ringwald write_16(fout, property) 220b3fcedb9SMatthias Ringwald write_16(fout, handle) 221b3fcedb9SMatthias Ringwald write_16(fout, service_type) 222b3fcedb9SMatthias Ringwald write_uuid(uuid) 223b3fcedb9SMatthias Ringwald fout.write("\n") 224b3fcedb9SMatthias Ringwald 225729074c4SMatthias Ringwald current_service_uuid_string = c_string_for_uuid(parts[1]) 226b3fcedb9SMatthias Ringwald current_service_start_handle = handle 227b3fcedb9SMatthias Ringwald handle = handle + 1 228b3fcedb9SMatthias Ringwald total_size = total_size + size 229b3fcedb9SMatthias Ringwald 230b3fcedb9SMatthias Ringwalddef parsePrimaryService(fout, parts): 231b3fcedb9SMatthias Ringwald parseService(fout, parts, 0x2800) 232b3fcedb9SMatthias Ringwald 233b3fcedb9SMatthias Ringwalddef parseSecondaryService(fout, parts): 234b3fcedb9SMatthias Ringwald parseService(fout, parts, 0x2801) 235b3fcedb9SMatthias Ringwald 236b3fcedb9SMatthias Ringwalddef parseIncludeService(fout, parts): 237b3fcedb9SMatthias Ringwald global handle 238b3fcedb9SMatthias Ringwald global total_size 239b3fcedb9SMatthias Ringwald 240b3fcedb9SMatthias Ringwald property = property_flags['READ']; 241b3fcedb9SMatthias Ringwald 242b3fcedb9SMatthias Ringwald write_indent(fout) 243b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts))) 244b3fcedb9SMatthias Ringwald 245b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 246b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 247b3fcedb9SMatthias Ringwald if uuid_size > 2: 248b3fcedb9SMatthias Ringwald uuid_size = 0 249729074c4SMatthias Ringwald # print("Include Service ", c_string_for_uuid(uuid)) 250b3fcedb9SMatthias Ringwald 251b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 4 + uuid_size 252b3fcedb9SMatthias Ringwald 253729074c4SMatthias Ringwald keyUUID = c_string_for_uuid(parts[1]) 254b3fcedb9SMatthias Ringwald 255b3fcedb9SMatthias Ringwald write_indent(fout) 256b3fcedb9SMatthias Ringwald write_16(fout, size) 257b3fcedb9SMatthias Ringwald write_16(fout, property) 258b3fcedb9SMatthias Ringwald write_16(fout, handle) 259b3fcedb9SMatthias Ringwald write_16(fout, 0x2802) 260b3fcedb9SMatthias Ringwald write_16(fout, services[keyUUID][0]) 261b3fcedb9SMatthias Ringwald write_16(fout, services[keyUUID][1]) 262b3fcedb9SMatthias Ringwald if uuid_size > 0: 263b3fcedb9SMatthias Ringwald write_uuid(uuid) 264b3fcedb9SMatthias Ringwald fout.write("\n") 265b3fcedb9SMatthias Ringwald 266b3fcedb9SMatthias Ringwald handle = handle + 1 267b3fcedb9SMatthias Ringwald total_size = total_size + size 268b3fcedb9SMatthias Ringwald 269b3fcedb9SMatthias Ringwald 270b3fcedb9SMatthias Ringwalddef parseCharacteristic(fout, parts): 271b3fcedb9SMatthias Ringwald global handle 272b3fcedb9SMatthias Ringwald global total_size 273b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 274b3fcedb9SMatthias Ringwald global characteristic_indices 275b3fcedb9SMatthias Ringwald 276b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 277b3fcedb9SMatthias Ringwald 278b3fcedb9SMatthias Ringwald # enumerate characteristics with same UUID, using optional name tag if available 279b3fcedb9SMatthias Ringwald current_characteristic_uuid_string = c_string_for_uuid(parts[1]); 280b3fcedb9SMatthias Ringwald index = 1 281b3fcedb9SMatthias Ringwald if current_characteristic_uuid_string in characteristic_indices: 282b3fcedb9SMatthias Ringwald index = characteristic_indices[current_characteristic_uuid_string] + 1 283b3fcedb9SMatthias Ringwald characteristic_indices[current_characteristic_uuid_string] = index 284b3fcedb9SMatthias Ringwald if len(parts) > 4: 285b3fcedb9SMatthias Ringwald current_characteristic_uuid_string += '_' + parts[4].upper().replace(' ','_') 286b3fcedb9SMatthias Ringwald else: 287b3fcedb9SMatthias Ringwald current_characteristic_uuid_string += ('_%02x' % index) 288b3fcedb9SMatthias Ringwald 289b3fcedb9SMatthias Ringwald uuid = parseUUID(parts[1]) 290b3fcedb9SMatthias Ringwald uuid_size = len(uuid) 291b3fcedb9SMatthias Ringwald properties = parseProperties(parts[2]) 292b3fcedb9SMatthias Ringwald value = ', '.join([str(x) for x in parts[3:]]) 293b3fcedb9SMatthias Ringwald 294b3fcedb9SMatthias Ringwald # reliable writes is defined in an extended properties 295b3fcedb9SMatthias Ringwald if (properties & property_flags['RELIABLE_WRITE']): 296b3fcedb9SMatthias Ringwald properties = properties | property_flags['EXTENDED_PROPERTIES'] 297b3fcedb9SMatthias Ringwald 298b3fcedb9SMatthias Ringwald write_indent(fout) 299b3fcedb9SMatthias Ringwald fout.write('// 0x%04x %s\n' % (handle, '-'.join(parts[0:3]))) 300b3fcedb9SMatthias Ringwald 301b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + (1+2+uuid_size) 302b3fcedb9SMatthias Ringwald write_indent(fout) 303b3fcedb9SMatthias Ringwald write_16(fout, size) 304b3fcedb9SMatthias Ringwald write_16(fout, property_read) 305b3fcedb9SMatthias Ringwald write_16(fout, handle) 306b3fcedb9SMatthias Ringwald write_16(fout, 0x2803) 307b3fcedb9SMatthias Ringwald write_8(fout, properties) 308b3fcedb9SMatthias Ringwald write_16(fout, handle+1) 309b3fcedb9SMatthias Ringwald write_uuid(uuid) 310b3fcedb9SMatthias Ringwald fout.write("\n") 311b3fcedb9SMatthias Ringwald handle = handle + 1 312b3fcedb9SMatthias Ringwald total_size = total_size + size 313b3fcedb9SMatthias Ringwald 314b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + uuid_size 315b3fcedb9SMatthias Ringwald if is_string(value): 316b3fcedb9SMatthias Ringwald size = size + len(value) 317b3fcedb9SMatthias Ringwald else: 318b3fcedb9SMatthias Ringwald size = size + len(value.split()) 319b3fcedb9SMatthias Ringwald 320b3fcedb9SMatthias Ringwald if uuid_size == 16: 321b3fcedb9SMatthias Ringwald properties = properties | property_flags['LONG_UUID']; 322b3fcedb9SMatthias Ringwald 323b3fcedb9SMatthias Ringwald write_indent(fout) 324b3fcedb9SMatthias Ringwald fout.write('// 0x%04x VALUE-%s-'"'%s'"'\n' % (handle, '-'.join(parts[1:3]),value)) 325*eb6072adSMatthias Ringwald # drop Broadcast, Notify, Indicate - not used for flags 326*eb6072adSMatthias Ringwald value_properties = properties & 0x1ffce 327b3fcedb9SMatthias Ringwald write_indent(fout) 328b3fcedb9SMatthias Ringwald write_16(fout, size) 329*eb6072adSMatthias Ringwald write_16(fout, value_properties) 330b3fcedb9SMatthias Ringwald write_16(fout, handle) 331b3fcedb9SMatthias Ringwald write_uuid(uuid) 332b3fcedb9SMatthias Ringwald if is_string(value): 333b3fcedb9SMatthias Ringwald write_string(fout, value) 334b3fcedb9SMatthias Ringwald else: 335b3fcedb9SMatthias Ringwald write_sequence(fout,value) 336b3fcedb9SMatthias Ringwald 337b3fcedb9SMatthias Ringwald fout.write("\n") 338729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_VALUE_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 339b3fcedb9SMatthias Ringwald handle = handle + 1 340b3fcedb9SMatthias Ringwald 341b3fcedb9SMatthias Ringwald if add_client_characteristic_configuration(properties): 342*eb6072adSMatthias Ringwald # replace GATT Characterstic Properties with READ|WRITE|READ_WITHOUT_AUTHENTICATION|DYNAMIC 343*eb6072adSMatthias Ringwald ccc_properties = (properties & 0x1ff00) | property_flags['READ_WITHOUT_AUTHENTICATION'] | property_flags['READ'] | property_flags['WRITE'] | property_flags['DYNAMIC']; 344b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 2 345b3fcedb9SMatthias Ringwald write_indent(fout) 346b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CLIENT_CHARACTERISTIC_CONFIGURATION\n' % (handle)) 347b3fcedb9SMatthias Ringwald write_indent(fout) 348b3fcedb9SMatthias Ringwald write_16(fout, size) 349*eb6072adSMatthias Ringwald write_16(fout, ccc_properties) 350b3fcedb9SMatthias Ringwald write_16(fout, handle) 351b3fcedb9SMatthias Ringwald write_16(fout, 0x2902) 352b3fcedb9SMatthias Ringwald write_16(fout, 0) 353b3fcedb9SMatthias Ringwald fout.write("\n") 354729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_CLIENT_CONFIGURATION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 355b3fcedb9SMatthias Ringwald handle = handle + 1 356b3fcedb9SMatthias Ringwald 357b3fcedb9SMatthias Ringwald if properties & property_flags['RELIABLE_WRITE']: 358b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 2 359b3fcedb9SMatthias Ringwald write_indent(fout) 360b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_EXTENDED_PROPERTIES\n' % (handle)) 361b3fcedb9SMatthias Ringwald write_indent(fout) 362b3fcedb9SMatthias Ringwald write_16(fout, size) 363b3fcedb9SMatthias Ringwald write_16(fout, property_flags['READ']) 364b3fcedb9SMatthias Ringwald write_16(fout, handle) 365b3fcedb9SMatthias Ringwald write_16(fout, 0x2900) 366b3fcedb9SMatthias Ringwald write_16(fout, 1) # Reliable Write 367b3fcedb9SMatthias Ringwald fout.write("\n") 368b3fcedb9SMatthias Ringwald handle = handle + 1 369b3fcedb9SMatthias Ringwald 370b3fcedb9SMatthias Ringwalddef parseCharacteristicUserDescription(fout, parts): 371b3fcedb9SMatthias Ringwald global handle 372b3fcedb9SMatthias Ringwald global total_size 373b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 374b3fcedb9SMatthias Ringwald 375b3fcedb9SMatthias Ringwald properties = parseProperties(parts[1]) 376b3fcedb9SMatthias Ringwald value = parts[2] 377b3fcedb9SMatthias Ringwald 378b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 379b3fcedb9SMatthias Ringwald if is_string(value): 380b3fcedb9SMatthias Ringwald size = size + len(value) - 2 381b3fcedb9SMatthias Ringwald else: 382b3fcedb9SMatthias Ringwald size = size + len(value.split()) 383b3fcedb9SMatthias Ringwald 384b3fcedb9SMatthias Ringwald write_indent(fout) 385b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_USER_DESCRIPTION-%s\n' % (handle, '-'.join(parts[1:]))) 386b3fcedb9SMatthias Ringwald write_indent(fout) 387b3fcedb9SMatthias Ringwald write_16(fout, size) 388b3fcedb9SMatthias Ringwald write_16(fout, properties) 389b3fcedb9SMatthias Ringwald write_16(fout, handle) 390b3fcedb9SMatthias Ringwald write_16(fout, 0x2901) 391b3fcedb9SMatthias Ringwald if is_string(value): 392b3fcedb9SMatthias Ringwald write_string(fout, value) 393b3fcedb9SMatthias Ringwald else: 394b3fcedb9SMatthias Ringwald write_sequence(fout,value) 395b3fcedb9SMatthias Ringwald fout.write("\n") 396729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_USER_DESCRIPTION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 397b3fcedb9SMatthias Ringwald handle = handle + 1 398b3fcedb9SMatthias Ringwald 399b3fcedb9SMatthias Ringwalddef parseServerCharacteristicConfiguration(fout, parts): 400b3fcedb9SMatthias Ringwald global handle 401b3fcedb9SMatthias Ringwald global total_size 402b3fcedb9SMatthias Ringwald global current_characteristic_uuid_string 403b3fcedb9SMatthias Ringwald 404b3fcedb9SMatthias Ringwald properties = parseProperties(parts[1]) 405b3fcedb9SMatthias Ringwald properties = properties | property_flags['DYNAMIC'] 406b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 407b3fcedb9SMatthias Ringwald 408b3fcedb9SMatthias Ringwald write_indent(fout) 409b3fcedb9SMatthias Ringwald fout.write('// 0x%04x SERVER_CHARACTERISTIC_CONFIGURATION-%s\n' % (handle, '-'.join(parts[1:]))) 410b3fcedb9SMatthias Ringwald write_indent(fout) 411b3fcedb9SMatthias Ringwald write_16(fout, size) 412b3fcedb9SMatthias Ringwald write_16(fout, properties) 413b3fcedb9SMatthias Ringwald write_16(fout, handle) 414b3fcedb9SMatthias Ringwald write_16(fout, 0x2903) 415b3fcedb9SMatthias Ringwald fout.write("\n") 416729074c4SMatthias Ringwald defines_for_characteristics.append('#define ATT_CHARACTERISTIC_%s_SERVER_CONFIGURATION_HANDLE 0x%04x' % (current_characteristic_uuid_string, handle)) 417b3fcedb9SMatthias Ringwald handle = handle + 1 418b3fcedb9SMatthias Ringwald 419b3fcedb9SMatthias Ringwalddef parseCharacteristicFormat(fout, parts): 420b3fcedb9SMatthias Ringwald global handle 421b3fcedb9SMatthias Ringwald global total_size 422b3fcedb9SMatthias Ringwald 423b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 424b3fcedb9SMatthias Ringwald 425b3fcedb9SMatthias Ringwald identifier = parts[1] 426b3fcedb9SMatthias Ringwald presentation_formats[identifier] = handle 427b3fcedb9SMatthias Ringwald # print("format '%s' with handle %d\n" % (identifier, handle)) 428b3fcedb9SMatthias Ringwald 429b3fcedb9SMatthias Ringwald format = parts[2] 430b3fcedb9SMatthias Ringwald exponent = parts[3] 431b3fcedb9SMatthias Ringwald unit = parseUUID(parts[4]) 432b3fcedb9SMatthias Ringwald name_space = parts[5] 433b3fcedb9SMatthias Ringwald description = parseUUID(parts[6]) 434b3fcedb9SMatthias Ringwald 435b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 7 436b3fcedb9SMatthias Ringwald 437b3fcedb9SMatthias Ringwald write_indent(fout) 438b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_FORMAT-%s\n' % (handle, '-'.join(parts[1:]))) 439b3fcedb9SMatthias Ringwald write_indent(fout) 440b3fcedb9SMatthias Ringwald write_16(fout, size) 441b3fcedb9SMatthias Ringwald write_16(fout, property_read) 442b3fcedb9SMatthias Ringwald write_16(fout, handle) 443b3fcedb9SMatthias Ringwald write_16(fout, 0x2904) 444b3fcedb9SMatthias Ringwald write_sequence(fout, format) 445b3fcedb9SMatthias Ringwald write_sequence(fout, exponent) 446b3fcedb9SMatthias Ringwald write_uuid(unit) 447b3fcedb9SMatthias Ringwald write_sequence(fout, name_space) 448b3fcedb9SMatthias Ringwald write_uuid(description) 449b3fcedb9SMatthias Ringwald fout.write("\n") 450b3fcedb9SMatthias Ringwald handle = handle + 1 451b3fcedb9SMatthias Ringwald 452b3fcedb9SMatthias Ringwald 453b3fcedb9SMatthias Ringwalddef parseCharacteristicAggregateFormat(fout, parts): 454b3fcedb9SMatthias Ringwald global handle 455b3fcedb9SMatthias Ringwald global total_size 456b3fcedb9SMatthias Ringwald 457b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 458b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + (len(parts)-1) * 2 459b3fcedb9SMatthias Ringwald 460b3fcedb9SMatthias Ringwald write_indent(fout) 461b3fcedb9SMatthias Ringwald fout.write('// 0x%04x CHARACTERISTIC_AGGREGATE_FORMAT-%s\n' % (handle, '-'.join(parts[1:]))) 462b3fcedb9SMatthias Ringwald write_indent(fout) 463b3fcedb9SMatthias Ringwald write_16(fout, size) 464b3fcedb9SMatthias Ringwald write_16(fout, property_read) 465b3fcedb9SMatthias Ringwald write_16(fout, handle) 466b3fcedb9SMatthias Ringwald write_16(fout, 0x2905) 467b3fcedb9SMatthias Ringwald for identifier in parts[1:]: 468b3fcedb9SMatthias Ringwald format_handle = presentation_formats[identifier] 469b3fcedb9SMatthias Ringwald if format == 0: 470b3fcedb9SMatthias Ringwald print("ERROR: identifier '%s' in CHARACTERISTIC_AGGREGATE_FORMAT undefined" % identifier) 471b3fcedb9SMatthias Ringwald sys.exit(1) 472b3fcedb9SMatthias Ringwald write_16(fout, format_handle) 473b3fcedb9SMatthias Ringwald fout.write("\n") 474b3fcedb9SMatthias Ringwald handle = handle + 1 475b3fcedb9SMatthias Ringwald 476b3fcedb9SMatthias Ringwalddef parseReportReference(fout, parts): 477b3fcedb9SMatthias Ringwald global handle 478b3fcedb9SMatthias Ringwald global total_size 479b3fcedb9SMatthias Ringwald 480b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 481b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 1 + 1 482b3fcedb9SMatthias Ringwald 483231a3c5dSMatthias Ringwald properties = parseProperties(parts[1]) 484231a3c5dSMatthias Ringwald 485231a3c5dSMatthias Ringwald report_id = parts[2] 486231a3c5dSMatthias Ringwald report_type = parts[3] 487b3fcedb9SMatthias Ringwald 488b3fcedb9SMatthias Ringwald write_indent(fout) 489b3fcedb9SMatthias Ringwald fout.write('// 0x%04x REPORT_REFERENCE-%s\n' % (handle, '-'.join(parts[1:]))) 490b3fcedb9SMatthias Ringwald write_indent(fout) 491b3fcedb9SMatthias Ringwald write_16(fout, size) 492b3fcedb9SMatthias Ringwald write_16(fout, property_read) 493b3fcedb9SMatthias Ringwald write_16(fout, handle) 494b3fcedb9SMatthias Ringwald write_16(fout, 0x2908) 495b3fcedb9SMatthias Ringwald write_sequence(fout, report_id) 496b3fcedb9SMatthias Ringwald write_sequence(fout, report_type) 497b3fcedb9SMatthias Ringwald fout.write("\n") 498b3fcedb9SMatthias Ringwald handle = handle + 1 499b3fcedb9SMatthias Ringwald 500b3fcedb9SMatthias Ringwald 501b3fcedb9SMatthias Ringwalddef parseNumberOfDigitals(fout, parts): 502b3fcedb9SMatthias Ringwald global handle 503b3fcedb9SMatthias Ringwald global total_size 504b3fcedb9SMatthias Ringwald 505b3fcedb9SMatthias Ringwald property_read = property_flags['READ']; 506b3fcedb9SMatthias Ringwald size = 2 + 2 + 2 + 2 + 1 507b3fcedb9SMatthias Ringwald 508b3fcedb9SMatthias Ringwald no_of_digitals = parts[1] 509b3fcedb9SMatthias Ringwald 510b3fcedb9SMatthias Ringwald write_indent(fout) 511b3fcedb9SMatthias Ringwald fout.write('// 0x%04x NUMBER_OF_DIGITALS-%s\n' % (handle, '-'.join(parts[1:]))) 512b3fcedb9SMatthias Ringwald write_indent(fout) 513b3fcedb9SMatthias Ringwald write_16(fout, size) 514b3fcedb9SMatthias Ringwald write_16(fout, property_read) 515b3fcedb9SMatthias Ringwald write_16(fout, handle) 516b3fcedb9SMatthias Ringwald write_16(fout, 0x2909) 517b3fcedb9SMatthias Ringwald write_sequence(fout, no_of_digitals) 518b3fcedb9SMatthias Ringwald fout.write("\n") 519b3fcedb9SMatthias Ringwald handle = handle + 1 520b3fcedb9SMatthias Ringwald 52160b51a4cSMatthias Ringwalddef parseLines(fname_in, fin, fout): 522b3fcedb9SMatthias Ringwald global handle 523b3fcedb9SMatthias Ringwald global total_size 524b3fcedb9SMatthias Ringwald 525b165f97bSMatthias Ringwald line_count = 0; 526b3fcedb9SMatthias Ringwald for line in fin: 527b3fcedb9SMatthias Ringwald line = line.strip("\n\r ") 528b165f97bSMatthias Ringwald line_count += 1 529b3fcedb9SMatthias Ringwald 530b165f97bSMatthias Ringwald if line.startswith("//"): 531b165f97bSMatthias Ringwald fout.write(" //" + line.lstrip('/') + '\n') 532b165f97bSMatthias Ringwald continue 533b165f97bSMatthias Ringwald 53460b51a4cSMatthias Ringwald if line.startswith("#import"): 53560b51a4cSMatthias Ringwald imported_file = '' 53660b51a4cSMatthias Ringwald parts = re.match('#import\s+<(.*)>\w*',line) 53760b51a4cSMatthias Ringwald if parts and len(parts.groups()) == 1: 53885a677ecSMatthias Ringwald imported_file = btstack_root+'/src/ble/gatt-service/' + parts.groups()[0] 53960b51a4cSMatthias Ringwald parts = re.match('#import\s+"(.*)"\w*',line) 54060b51a4cSMatthias Ringwald if parts and len(parts.groups()) == 1: 54160b51a4cSMatthias Ringwald imported_file = os.path.abspath(os.path.dirname(fname_in) + '/'+parts.groups()[0]) 54260b51a4cSMatthias Ringwald if len(imported_file) == 0: 54360b51a4cSMatthias Ringwald print('ERROR: #import in file %s - line %u neither <name.gatt> nor "name.gatt" form', (fname_in, line_count)) 54460b51a4cSMatthias Ringwald continue 54560b51a4cSMatthias Ringwald 54660b51a4cSMatthias Ringwald print("Importing %s" % imported_file) 54760b51a4cSMatthias Ringwald try: 54860b51a4cSMatthias Ringwald imported_fin = codecs.open (imported_file, encoding='utf-8') 54960b51a4cSMatthias Ringwald fout.write(' // ' + line + ' -- BEGIN\n') 55060b51a4cSMatthias Ringwald parseLines(imported_file, imported_fin, fout) 55160b51a4cSMatthias Ringwald fout.write(' // ' + line + ' -- END\n') 55260b51a4cSMatthias Ringwald except IOError as e: 55360b51a4cSMatthias Ringwald print('ERROR: Import failed. Please check path.') 55460b51a4cSMatthias Ringwald 55560b51a4cSMatthias Ringwald continue 55660b51a4cSMatthias Ringwald 55760b51a4cSMatthias Ringwald if line.startswith("#TODO"): 55860b51a4cSMatthias Ringwald print ("WARNING: #TODO in file %s - line %u not handled, skipping declaration:" % (fname_in, line_count)) 559b165f97bSMatthias Ringwald print ("'%s'" % line) 560b165f97bSMatthias Ringwald fout.write("// " + line + '\n') 561b3fcedb9SMatthias Ringwald continue 562b3fcedb9SMatthias Ringwald 563b3fcedb9SMatthias Ringwald if len(line) == 0: 564b3fcedb9SMatthias Ringwald continue 565b3fcedb9SMatthias Ringwald 566b3fcedb9SMatthias Ringwald f = io.StringIO(line) 567b3fcedb9SMatthias Ringwald parts_list = csv.reader(f, delimiter=',', quotechar='"') 568b3fcedb9SMatthias Ringwald 569b3fcedb9SMatthias Ringwald for parts in parts_list: 570b3fcedb9SMatthias Ringwald for index, object in enumerate(parts): 571b3fcedb9SMatthias Ringwald parts[index] = object.strip().lstrip('"').rstrip('"') 572b3fcedb9SMatthias Ringwald 573b3fcedb9SMatthias Ringwald if parts[0] == 'PRIMARY_SERVICE': 574b3fcedb9SMatthias Ringwald parsePrimaryService(fout, parts) 575b3fcedb9SMatthias Ringwald continue 576b3fcedb9SMatthias Ringwald 577b3fcedb9SMatthias Ringwald if parts[0] == 'SECONDARY_SERVICE': 578b3fcedb9SMatthias Ringwald parseSecondaryService(fout, parts) 579b3fcedb9SMatthias Ringwald continue 580b3fcedb9SMatthias Ringwald 581b3fcedb9SMatthias Ringwald if parts[0] == 'INCLUDE_SERVICE': 582b3fcedb9SMatthias Ringwald parseIncludeService(fout, parts) 583b3fcedb9SMatthias Ringwald continue 584b3fcedb9SMatthias Ringwald 585b3fcedb9SMatthias Ringwald # 2803 586b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC': 587b3fcedb9SMatthias Ringwald parseCharacteristic(fout, parts) 588b3fcedb9SMatthias Ringwald continue 589b3fcedb9SMatthias Ringwald 590b3fcedb9SMatthias Ringwald # 2900 Characteristic Extended Properties 591b3fcedb9SMatthias Ringwald 592b3fcedb9SMatthias Ringwald # 2901 593b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_USER_DESCRIPTION': 594b3fcedb9SMatthias Ringwald parseCharacteristicUserDescription(fout, parts) 595b3fcedb9SMatthias Ringwald continue 596b3fcedb9SMatthias Ringwald 597b165f97bSMatthias Ringwald 598b165f97bSMatthias Ringwald # 2902 Client Characteristic Configuration - automatically included in Characteristic if 599b3fcedb9SMatthias Ringwald # notification / indication is supported 600231a3c5dSMatthias Ringwald if parts[0] == 'CLIENT_CHARACTERISTIC_CONFIGURATION': 601b165f97bSMatthias Ringwald continue 602b3fcedb9SMatthias Ringwald 603b3fcedb9SMatthias Ringwald # 2903 604b3fcedb9SMatthias Ringwald if parts[0] == 'SERVER_CHARACTERISTIC_CONFIGURATION': 605b3fcedb9SMatthias Ringwald parseServerCharacteristicConfiguration(fout, parts) 606b3fcedb9SMatthias Ringwald continue 607b3fcedb9SMatthias Ringwald 608b3fcedb9SMatthias Ringwald # 2904 609b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_FORMAT': 610b3fcedb9SMatthias Ringwald parseCharacteristicFormat(fout, parts) 611b3fcedb9SMatthias Ringwald continue 612b3fcedb9SMatthias Ringwald 613b3fcedb9SMatthias Ringwald # 2905 614b3fcedb9SMatthias Ringwald if parts[0] == 'CHARACTERISTIC_AGGREGATE_FORMAT': 615b3fcedb9SMatthias Ringwald parseCharacteristicAggregateFormat(fout, parts) 616b3fcedb9SMatthias Ringwald continue 617b3fcedb9SMatthias Ringwald 618b3fcedb9SMatthias Ringwald # 2906 619b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 620b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 621b3fcedb9SMatthias Ringwald continue 622b3fcedb9SMatthias Ringwald 623b3fcedb9SMatthias Ringwald # 2907 624b3fcedb9SMatthias Ringwald if parts[0] == 'EXTERNAL_REPORT_REFERENCE': 625b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 626b3fcedb9SMatthias Ringwald continue 627b3fcedb9SMatthias Ringwald 628b3fcedb9SMatthias Ringwald # 2908 629b3fcedb9SMatthias Ringwald if parts[0] == 'REPORT_REFERENCE': 630b3fcedb9SMatthias Ringwald parseReportReference(fout, parts) 631b3fcedb9SMatthias Ringwald continue 632b3fcedb9SMatthias Ringwald 633b3fcedb9SMatthias Ringwald # 2909 634b3fcedb9SMatthias Ringwald if parts[0] == 'NUMBER_OF_DIGITALS': 635b3fcedb9SMatthias Ringwald parseNumberOfDigitals(fout, parts) 636b3fcedb9SMatthias Ringwald continue 637b3fcedb9SMatthias Ringwald 638b3fcedb9SMatthias Ringwald # 290A 639b3fcedb9SMatthias Ringwald if parts[0] == 'VALUE_TRIGGER_SETTING': 640b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 641b3fcedb9SMatthias Ringwald continue 642b3fcedb9SMatthias Ringwald 643b3fcedb9SMatthias Ringwald # 290B 644b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_CONFIGURATION': 645b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 646b3fcedb9SMatthias Ringwald continue 647b3fcedb9SMatthias Ringwald 648b3fcedb9SMatthias Ringwald # 290C 649b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_MEASUREMENT': 650b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 651b3fcedb9SMatthias Ringwald continue 652b3fcedb9SMatthias Ringwald 653b3fcedb9SMatthias Ringwald # 290D 654b3fcedb9SMatthias Ringwald if parts[0] == 'ENVIRONMENTAL_SENSING_TRIGGER_SETTING': 655b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 656b3fcedb9SMatthias Ringwald continue 657b3fcedb9SMatthias Ringwald 658b3fcedb9SMatthias Ringwald # 2906 659b3fcedb9SMatthias Ringwald if parts[0] == 'VALID_RANGE': 660b3fcedb9SMatthias Ringwald print("WARNING: %s not implemented yet\n" % (parts[0])) 661b3fcedb9SMatthias Ringwald continue 662b3fcedb9SMatthias Ringwald 663b3fcedb9SMatthias Ringwald print("WARNING: unknown token: %s\n" % (parts[0])) 664b3fcedb9SMatthias Ringwald 66560b51a4cSMatthias Ringwalddef parse(fname_in, fin, fname_out, fout): 66660b51a4cSMatthias Ringwald global handle 66760b51a4cSMatthias Ringwald global total_size 66860b51a4cSMatthias Ringwald 66960b51a4cSMatthias Ringwald fout.write(header.format(fname_out, fname_in)) 67060b51a4cSMatthias Ringwald fout.write('{\n') 67160b51a4cSMatthias Ringwald 67260b51a4cSMatthias Ringwald parseLines(fname_in, fin, fout) 67360b51a4cSMatthias Ringwald 674729074c4SMatthias Ringwald serviceDefinitionComplete(fout) 675b3fcedb9SMatthias Ringwald write_indent(fout) 676b3fcedb9SMatthias Ringwald fout.write("// END\n"); 677b3fcedb9SMatthias Ringwald write_indent(fout) 678b3fcedb9SMatthias Ringwald write_16(fout,0) 679b3fcedb9SMatthias Ringwald fout.write("\n") 680b3fcedb9SMatthias Ringwald total_size = total_size + 2 681b3fcedb9SMatthias Ringwald 682b3fcedb9SMatthias Ringwald fout.write("}; // total size %u bytes \n" % total_size); 683b3fcedb9SMatthias Ringwald 684b3fcedb9SMatthias Ringwalddef listHandles(fout): 685b3fcedb9SMatthias Ringwald fout.write('\n\n') 686b3fcedb9SMatthias Ringwald fout.write('//\n') 687729074c4SMatthias Ringwald fout.write('// list service handle ranges\n') 688729074c4SMatthias Ringwald fout.write('//\n') 689729074c4SMatthias Ringwald for define in defines_for_services: 690729074c4SMatthias Ringwald fout.write(define) 691729074c4SMatthias Ringwald fout.write('\n') 692729074c4SMatthias Ringwald fout.write('\n') 693729074c4SMatthias Ringwald fout.write('//\n') 694b3fcedb9SMatthias Ringwald fout.write('// list mapping between characteristics and handles\n') 695b3fcedb9SMatthias Ringwald fout.write('//\n') 696729074c4SMatthias Ringwald for define in defines_for_characteristics: 697b3fcedb9SMatthias Ringwald fout.write(define) 698b3fcedb9SMatthias Ringwald fout.write('\n') 699b3fcedb9SMatthias Ringwald 700b3fcedb9SMatthias Ringwaldif (len(sys.argv) < 3): 701b3fcedb9SMatthias Ringwald print(usage) 702b3fcedb9SMatthias Ringwald sys.exit(1) 703b3fcedb9SMatthias Ringwaldtry: 704b165f97bSMatthias Ringwald # read defines from bluetooth_gatt.h 705b165f97bSMatthias Ringwald btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 706b165f97bSMatthias Ringwald gen_path = btstack_root + '/src/bluetooth_gatt.h' 707b165f97bSMatthias Ringwald bluetooth_gatt = read_defines(gen_path) 708b165f97bSMatthias Ringwald 709b3fcedb9SMatthias Ringwald filename = sys.argv[2] 710b3fcedb9SMatthias Ringwald fin = codecs.open (sys.argv[1], encoding='utf-8') 711b3fcedb9SMatthias Ringwald fout = open (filename, 'w') 712b3fcedb9SMatthias Ringwald parse(sys.argv[1], fin, filename, fout) 713b3fcedb9SMatthias Ringwald listHandles(fout) 714b3fcedb9SMatthias Ringwald fout.close() 715b165f97bSMatthias Ringwald print('Created %s' % filename) 716b3fcedb9SMatthias Ringwald 717b3fcedb9SMatthias Ringwaldexcept IOError as e: 718b3fcedb9SMatthias Ringwald print(usage) 719b3fcedb9SMatthias Ringwald sys.exit(1) 720b3fcedb9SMatthias Ringwald 721b3fcedb9SMatthias Ringwaldprint('Compilation successful!\n') 722