xref: /btstack/tool/btstack_event_generator.py (revision c3b5b8a5c300fae5cc1ad63daf98d4e69704a1f4)
1*c3b5b8a5SMatthias Ringwald#!/usr/bin/env python
2*c3b5b8a5SMatthias Ringwald# BlueKitchen GmbH (c) 2014
3*c3b5b8a5SMatthias Ringwald
4*c3b5b8a5SMatthias Ringwaldimport glob
5*c3b5b8a5SMatthias Ringwaldimport re
6*c3b5b8a5SMatthias Ringwaldimport sys
7*c3b5b8a5SMatthias Ringwaldimport os
8*c3b5b8a5SMatthias Ringwald
9*c3b5b8a5SMatthias Ringwaldimport btstack_parser as parser
10*c3b5b8a5SMatthias Ringwald
11*c3b5b8a5SMatthias Ringwaldprogram_info = '''
12*c3b5b8a5SMatthias RingwaldBTstack Event Getter Generator for BTstack
13*c3b5b8a5SMatthias RingwaldCopyright 2016, BlueKitchen GmbH
14*c3b5b8a5SMatthias Ringwald'''
15*c3b5b8a5SMatthias Ringwald
16*c3b5b8a5SMatthias Ringwaldcopyright = """/*
17*c3b5b8a5SMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH
18*c3b5b8a5SMatthias Ringwald *
19*c3b5b8a5SMatthias Ringwald * Redistribution and use in source and binary forms, with or without
20*c3b5b8a5SMatthias Ringwald * modification, are permitted provided that the following conditions
21*c3b5b8a5SMatthias Ringwald * are met:
22*c3b5b8a5SMatthias Ringwald *
23*c3b5b8a5SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
24*c3b5b8a5SMatthias Ringwald *    notice, this list of conditions and the following disclaimer.
25*c3b5b8a5SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
26*c3b5b8a5SMatthias Ringwald *    notice, this list of conditions and the following disclaimer in the
27*c3b5b8a5SMatthias Ringwald *    documentation and/or other materials provided with the distribution.
28*c3b5b8a5SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
29*c3b5b8a5SMatthias Ringwald *    contributors may be used to endorse or promote products derived
30*c3b5b8a5SMatthias Ringwald *    from this software without specific prior written permission.
31*c3b5b8a5SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for
32*c3b5b8a5SMatthias Ringwald *    personal benefit and not for any commercial purpose or for
33*c3b5b8a5SMatthias Ringwald *    monetary gain.
34*c3b5b8a5SMatthias Ringwald *
35*c3b5b8a5SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
36*c3b5b8a5SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37*c3b5b8a5SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
38*c3b5b8a5SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
39*c3b5b8a5SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40*c3b5b8a5SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41*c3b5b8a5SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42*c3b5b8a5SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
43*c3b5b8a5SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44*c3b5b8a5SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
45*c3b5b8a5SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46*c3b5b8a5SMatthias Ringwald * SUCH DAMAGE.
47*c3b5b8a5SMatthias Ringwald *
48*c3b5b8a5SMatthias Ringwald * Please inquire about commercial licensing options at
49*c3b5b8a5SMatthias Ringwald * [email protected]
50*c3b5b8a5SMatthias Ringwald *
51*c3b5b8a5SMatthias Ringwald */
52*c3b5b8a5SMatthias Ringwald"""
53*c3b5b8a5SMatthias Ringwald
54*c3b5b8a5SMatthias Ringwaldhfile_header_begin = """
55*c3b5b8a5SMatthias Ringwald
56*c3b5b8a5SMatthias Ringwald/*
57*c3b5b8a5SMatthias Ringwald *  btstack_event.h
58*c3b5b8a5SMatthias Ringwald *
59*c3b5b8a5SMatthias Ringwald *  @brief BTstack event getter/setter
60*c3b5b8a5SMatthias Ringwald *  @note  Don't edit - generated by tool/btstack_event_generator.py
61*c3b5b8a5SMatthias Ringwald *
62*c3b5b8a5SMatthias Ringwald */
63*c3b5b8a5SMatthias Ringwald
64*c3b5b8a5SMatthias Ringwald#ifndef __BTSTACK_EVENT_H
65*c3b5b8a5SMatthias Ringwald#define __BTSTACK_EVENT_H
66*c3b5b8a5SMatthias Ringwald
67*c3b5b8a5SMatthias Ringwald#if defined __cplusplus
68*c3b5b8a5SMatthias Ringwaldextern "C" {
69*c3b5b8a5SMatthias Ringwald#endif
70*c3b5b8a5SMatthias Ringwald
71*c3b5b8a5SMatthias Ringwald#include "btstack_util.h"
72*c3b5b8a5SMatthias Ringwald#include <stdint.h>
73*c3b5b8a5SMatthias Ringwald
74*c3b5b8a5SMatthias Ringwald/* API_START */
75*c3b5b8a5SMatthias Ringwald
76*c3b5b8a5SMatthias Ringwald"""
77*c3b5b8a5SMatthias Ringwald
78*c3b5b8a5SMatthias Ringwaldhfile_header_end = """
79*c3b5b8a5SMatthias Ringwald
80*c3b5b8a5SMatthias Ringwald/* API_END */
81*c3b5b8a5SMatthias Ringwald
82*c3b5b8a5SMatthias Ringwald#if defined __cplusplus
83*c3b5b8a5SMatthias Ringwald}
84*c3b5b8a5SMatthias Ringwald#endif
85*c3b5b8a5SMatthias Ringwald
86*c3b5b8a5SMatthias Ringwald#endif // __BTSTACK_EVENT_H
87*c3b5b8a5SMatthias Ringwald"""
88*c3b5b8a5SMatthias Ringwald
89*c3b5b8a5SMatthias Ringwaldc_prototoype_simple_return = '''
90*c3b5b8a5SMatthias Ringwald/**
91*c3b5b8a5SMatthias Ringwald * @brief {description}
92*c3b5b8a5SMatthias Ringwald * @param Event packet
93*c3b5b8a5SMatthias Ringwald * @return {result_name}
94*c3b5b8a5SMatthias Ringwald * @note: btstack_type {format}
95*c3b5b8a5SMatthias Ringwald */
96*c3b5b8a5SMatthias Ringwaldstatic inline {result_type} {fn_name}(const uint8_t * event){{
97*c3b5b8a5SMatthias Ringwald    {code}
98*c3b5b8a5SMatthias Ringwald}}
99*c3b5b8a5SMatthias Ringwald'''
100*c3b5b8a5SMatthias Ringwald
101*c3b5b8a5SMatthias Ringwaldc_prototoype_struct_return = '''
102*c3b5b8a5SMatthias Ringwald/**
103*c3b5b8a5SMatthias Ringwald * @brief {description}
104*c3b5b8a5SMatthias Ringwald * @param Event packet
105*c3b5b8a5SMatthias Ringwald * @param Pointer to storage for {result_name}
106*c3b5b8a5SMatthias Ringwald * @note: btstack_type {format}
107*c3b5b8a5SMatthias Ringwald */
108*c3b5b8a5SMatthias Ringwaldstatic inline void {fn_name}(const uint8_t * event, {result_type} {result_name}){{
109*c3b5b8a5SMatthias Ringwald    {code}
110*c3b5b8a5SMatthias Ringwald}}
111*c3b5b8a5SMatthias Ringwald'''
112*c3b5b8a5SMatthias Ringwald
113*c3b5b8a5SMatthias Ringwaldc_prototoype_unsupported = '''
114*c3b5b8a5SMatthias Ringwald/**
115*c3b5b8a5SMatthias Ringwald * @brief {description}
116*c3b5b8a5SMatthias Ringwald * @param Event packet
117*c3b5b8a5SMatthias Ringwald * @return {result_name}
118*c3b5b8a5SMatthias Ringwald * @note: btstack_type {format}
119*c3b5b8a5SMatthias Ringwald */
120*c3b5b8a5SMatthias Ringwald//  static inline {result_type} {fn_name}(const uint8_t * event){{
121*c3b5b8a5SMatthias Ringwald//      not implemented yet
122*c3b5b8a5SMatthias Ringwald//  }}
123*c3b5b8a5SMatthias Ringwald'''
124*c3b5b8a5SMatthias Ringwald
125*c3b5b8a5SMatthias Ringwald# global variables/defines
126*c3b5b8a5SMatthias Ringwaldgen_path = '../src/btstack_event.h'
127*c3b5b8a5SMatthias Ringwald
128*c3b5b8a5SMatthias Ringwalddefines = dict()
129*c3b5b8a5SMatthias Ringwalddefines_used = set()
130*c3b5b8a5SMatthias Ringwald
131*c3b5b8a5SMatthias Ringwaldparam_read = {
132*c3b5b8a5SMatthias Ringwald    '1' : 'return event[{offset}];',
133*c3b5b8a5SMatthias Ringwald    'J' : 'return event[{offset}];',
134*c3b5b8a5SMatthias Ringwald    'L' : 'return event[{offset}];',
135*c3b5b8a5SMatthias Ringwald    '2' : 'return READ_BT_16(event, {offset});',
136*c3b5b8a5SMatthias Ringwald    '3' : 'return READ_BT_24(event, {offset});',
137*c3b5b8a5SMatthias Ringwald    '4' : 'return READ_BT_32(event, {offset});',
138*c3b5b8a5SMatthias Ringwald    'H' : 'return READ_BT_16(event, {offset});',
139*c3b5b8a5SMatthias Ringwald    'B' : 'bt_flip_addr({result_name}, (uint8_t*) &event[{offset}]);',
140*c3b5b8a5SMatthias Ringwald    'R' : 'return &event[{offset}];'
141*c3b5b8a5SMatthias Ringwald}
142*c3b5b8a5SMatthias Ringwald
143*c3b5b8a5SMatthias Ringwalddef c_type_for_btstack_type(type):
144*c3b5b8a5SMatthias Ringwald    param_types = { '1' : 'uint8_t', '2' : 'uint16_t', '3' : 'uint32_t', '4' : 'uint32_t', 'H' : 'hci_con_handle_t', 'B' : 'bd_addr_t',
145*c3b5b8a5SMatthias Ringwald                    'D' : 'const uint8_t *', 'E' : 'const uint8_t * ', 'N' : 'String' , 'P' : 'const uint8_t *', 'A' : 'const uint8_t *',
146*c3b5b8a5SMatthias Ringwald                    'R' : 'const uint8_t *', 'S' : 'const uint8_t *',
147*c3b5b8a5SMatthias Ringwald                    'J' : 'int', 'L' : 'int', 'V' : 'const uint8_t *', 'U' : 'BT_UUID',
148*c3b5b8a5SMatthias Ringwald                    'X' : 'GATTService', 'Y' : 'GATTCharacteristic', 'Z' : 'GATTCharacteristicDescriptor',
149*c3b5b8a5SMatthias Ringwald                    'T' : 'String'}
150*c3b5b8a5SMatthias Ringwald    return param_types[type]
151*c3b5b8a5SMatthias Ringwald
152*c3b5b8a5SMatthias Ringwalddef size_for_type(type):
153*c3b5b8a5SMatthias Ringwald    param_sizes = { '1' : 1, '2' : 2, '3' : 3, '4' : 4, 'H' : 2, 'B' : 6, 'D' : 8, 'E' : 240, 'N' : 248, 'P' : 16,
154*c3b5b8a5SMatthias Ringwald                    'A' : 31, 'S' : -1, 'V': -1, 'J' : 1, 'L' : 2, 'U' : 16, 'X' : 20, 'Y' : 24, 'Z' : 18, 'T':-1}
155*c3b5b8a5SMatthias Ringwald    return param_sizes[type]
156*c3b5b8a5SMatthias Ringwald
157*c3b5b8a5SMatthias Ringwalddef format_function_name(event_name):
158*c3b5b8a5SMatthias Ringwald    return event_name.lower()
159*c3b5b8a5SMatthias Ringwald
160*c3b5b8a5SMatthias Ringwalddef template_for_type(field_type):
161*c3b5b8a5SMatthias Ringwald    global c_prototoype_simple_return
162*c3b5b8a5SMatthias Ringwald    global c_prototoype_struct_return
163*c3b5b8a5SMatthias Ringwald    types_with_struct_return = "B"
164*c3b5b8a5SMatthias Ringwald    if field_type in types_with_struct_return:
165*c3b5b8a5SMatthias Ringwald        return c_prototoype_struct_return
166*c3b5b8a5SMatthias Ringwald    else:
167*c3b5b8a5SMatthias Ringwald        return c_prototoype_simple_return
168*c3b5b8a5SMatthias Ringwald
169*c3b5b8a5SMatthias Ringwalddef all_fields_supported(format):
170*c3b5b8a5SMatthias Ringwald    global param_read
171*c3b5b8a5SMatthias Ringwald    for f in format:
172*c3b5b8a5SMatthias Ringwald        if not f in param_read:
173*c3b5b8a5SMatthias Ringwald            return False
174*c3b5b8a5SMatthias Ringwald    return True
175*c3b5b8a5SMatthias Ringwald
176*c3b5b8a5SMatthias Ringwalddef create_getter(event_name, field_name, field_type, offset, supported):
177*c3b5b8a5SMatthias Ringwald    global c_prototoype_unsupported
178*c3b5b8a5SMatthias Ringwald    global param_read
179*c3b5b8a5SMatthias Ringwald
180*c3b5b8a5SMatthias Ringwald    description = "Get field %s from event %s" % (field_name, event_name)
181*c3b5b8a5SMatthias Ringwald    result_name = field_name
182*c3b5b8a5SMatthias Ringwald    fn_name     = "%s_get_%s" % (event_name, field_name)
183*c3b5b8a5SMatthias Ringwald    result_type = c_type_for_btstack_type(field_type)
184*c3b5b8a5SMatthias Ringwald    template = c_prototoype_unsupported
185*c3b5b8a5SMatthias Ringwald    code = ''
186*c3b5b8a5SMatthias Ringwald    if supported and field_type in param_read:
187*c3b5b8a5SMatthias Ringwald        template = template_for_type(field_type)
188*c3b5b8a5SMatthias Ringwald        code = param_read[field_type].format(offset=offset, result_name=result_name)
189*c3b5b8a5SMatthias Ringwald    return template.format(description=description, fn_name=fn_name, result_name=result_name, result_type=result_type, code=code, format=field_type)
190*c3b5b8a5SMatthias Ringwald
191*c3b5b8a5SMatthias Ringwalddef create_events(events):
192*c3b5b8a5SMatthias Ringwald    global gen_path
193*c3b5b8a5SMatthias Ringwald    global copyright
194*c3b5b8a5SMatthias Ringwald    global hfile_header_begin
195*c3b5b8a5SMatthias Ringwald    global hfile_header_end
196*c3b5b8a5SMatthias Ringwald
197*c3b5b8a5SMatthias Ringwald    with open(gen_path, 'wt') as fout:
198*c3b5b8a5SMatthias Ringwald        fout.write(copyright)
199*c3b5b8a5SMatthias Ringwald        fout.write(hfile_header_begin)
200*c3b5b8a5SMatthias Ringwald        for event_type, event_name, format, args in events:
201*c3b5b8a5SMatthias Ringwald            event_name = format_function_name(event_name)
202*c3b5b8a5SMatthias Ringwald            offset = 2
203*c3b5b8a5SMatthias Ringwald            supported = all_fields_supported(format)
204*c3b5b8a5SMatthias Ringwald            for f, arg in zip(format, args):
205*c3b5b8a5SMatthias Ringwald                field_name = arg
206*c3b5b8a5SMatthias Ringwald                field_type = f
207*c3b5b8a5SMatthias Ringwald                if field_type == 'V':
208*c3b5b8a5SMatthias Ringwald                    break
209*c3b5b8a5SMatthias Ringwald                text = create_getter(event_name, field_name, field_type, offset, supported)
210*c3b5b8a5SMatthias Ringwald                fout.write(text)
211*c3b5b8a5SMatthias Ringwald                if field_type == 'R':
212*c3b5b8a5SMatthias Ringwald                    break
213*c3b5b8a5SMatthias Ringwald                offset += size_for_type(field_type)
214*c3b5b8a5SMatthias Ringwald
215*c3b5b8a5SMatthias Ringwald        fout.write(hfile_header_end)
216*c3b5b8a5SMatthias Ringwald
217*c3b5b8a5SMatthias Ringwald# set root
218*c3b5b8a5SMatthias Ringwaldparser.set_btstack_root('..')
219*c3b5b8a5SMatthias Ringwald
220*c3b5b8a5SMatthias Ringwaldprint(program_info)
221*c3b5b8a5SMatthias Ringwald
222*c3b5b8a5SMatthias Ringwald# parse events
223*c3b5b8a5SMatthias Ringwald(events, le_events, event_types) = parser.parse_events()
224*c3b5b8a5SMatthias Ringwald
225*c3b5b8a5SMatthias Ringwald# create event field accesors
226*c3b5b8a5SMatthias Ringwaldcreate_events(events + le_events)
227*c3b5b8a5SMatthias Ringwald
228*c3b5b8a5SMatthias Ringwald# done
229*c3b5b8a5SMatthias Ringwaldprint('Done!')
230