xref: /btstack/tool/compile_gatt.py (revision 729074c4fd1532f1490a8d5fa5e5ad3c76e8de4d)
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