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