1c3b5b8a5SMatthias Ringwald#!/usr/bin/env python 2c3b5b8a5SMatthias Ringwald# BlueKitchen GmbH (c) 2014 3c3b5b8a5SMatthias Ringwald 4c3b5b8a5SMatthias Ringwaldimport glob 5c3b5b8a5SMatthias Ringwaldimport re 6c3b5b8a5SMatthias Ringwaldimport sys 7c3b5b8a5SMatthias Ringwaldimport os 8c3b5b8a5SMatthias Ringwald 9c3b5b8a5SMatthias Ringwaldimport btstack_parser as parser 10c3b5b8a5SMatthias Ringwald 11f1b34e8dSMatthias Ringwaldmeta_events = [ 12f1b34e8dSMatthias Ringwald 'ANCS', 13f1b34e8dSMatthias Ringwald 'AVDTP', 14f1b34e8dSMatthias Ringwald 'AVRCP', 15f1b34e8dSMatthias Ringwald 'GOEP', 16f1b34e8dSMatthias Ringwald 'HFP', 17f1b34e8dSMatthias Ringwald 'HSP', 18f1b34e8dSMatthias Ringwald 'PBAP', 19*dd148ddbSMatthias Ringwald 'LE', 20*dd148ddbSMatthias Ringwald 'HID', 21f1b34e8dSMatthias Ringwald] 22f1b34e8dSMatthias Ringwald 23f1b34e8dSMatthias Ringwaldsupported_event_groups = meta_events + [ 24f1b34e8dSMatthias Ringwald 'BTSTACK', 25f1b34e8dSMatthias Ringwald 'GAP', 26f1b34e8dSMatthias Ringwald 'HCI', 27f1b34e8dSMatthias Ringwald 'SDP', 28f1b34e8dSMatthias Ringwald 'SM', 29f1b34e8dSMatthias Ringwald 'L2CAP', 30f1b34e8dSMatthias Ringwald 'RFCOMM', 31f1b34e8dSMatthias Ringwald 'GATT', 32f1b34e8dSMatthias Ringwald 'BNEP', 33f1b34e8dSMatthias Ringwald 'ATT', 34*dd148ddbSMatthias Ringwald 'HID', 35f1b34e8dSMatthias Ringwald] 36f1b34e8dSMatthias Ringwald 37c3b5b8a5SMatthias Ringwaldprogram_info = ''' 38c3b5b8a5SMatthias RingwaldBTstack Event Getter Generator for BTstack 39c3b5b8a5SMatthias RingwaldCopyright 2016, BlueKitchen GmbH 40c3b5b8a5SMatthias Ringwald''' 41c3b5b8a5SMatthias Ringwald 42c3b5b8a5SMatthias Ringwaldcopyright = """/* 43c3b5b8a5SMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH 44c3b5b8a5SMatthias Ringwald * 45c3b5b8a5SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 46c3b5b8a5SMatthias Ringwald * modification, are permitted provided that the following conditions 47c3b5b8a5SMatthias Ringwald * are met: 48c3b5b8a5SMatthias Ringwald * 49c3b5b8a5SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 50c3b5b8a5SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 51c3b5b8a5SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 52c3b5b8a5SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 53c3b5b8a5SMatthias Ringwald * documentation and/or other materials provided with the distribution. 54c3b5b8a5SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 55c3b5b8a5SMatthias Ringwald * contributors may be used to endorse or promote products derived 56c3b5b8a5SMatthias Ringwald * from this software without specific prior written permission. 57c3b5b8a5SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 58c3b5b8a5SMatthias Ringwald * personal benefit and not for any commercial purpose or for 59c3b5b8a5SMatthias Ringwald * monetary gain. 60c3b5b8a5SMatthias Ringwald * 61c3b5b8a5SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 62c3b5b8a5SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 63c3b5b8a5SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 64c3b5b8a5SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 65c3b5b8a5SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 66c3b5b8a5SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 67c3b5b8a5SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 68c3b5b8a5SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 69c3b5b8a5SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 70c3b5b8a5SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 71c3b5b8a5SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72c3b5b8a5SMatthias Ringwald * SUCH DAMAGE. 73c3b5b8a5SMatthias Ringwald * 74c3b5b8a5SMatthias Ringwald * Please inquire about commercial licensing options at 75c3b5b8a5SMatthias Ringwald * [email protected] 76c3b5b8a5SMatthias Ringwald * 77c3b5b8a5SMatthias Ringwald */ 78c3b5b8a5SMatthias Ringwald""" 79c3b5b8a5SMatthias Ringwald 80c3b5b8a5SMatthias Ringwaldhfile_header_begin = """ 81c3b5b8a5SMatthias Ringwald 82c3b5b8a5SMatthias Ringwald/* 83c3b5b8a5SMatthias Ringwald * btstack_event.h 84c3b5b8a5SMatthias Ringwald * 85c3b5b8a5SMatthias Ringwald * @brief BTstack event getter/setter 86c3b5b8a5SMatthias Ringwald * @note Don't edit - generated by tool/btstack_event_generator.py 87c3b5b8a5SMatthias Ringwald * 88c3b5b8a5SMatthias Ringwald */ 89c3b5b8a5SMatthias Ringwald 90c3b5b8a5SMatthias Ringwald#ifndef __BTSTACK_EVENT_H 91c3b5b8a5SMatthias Ringwald#define __BTSTACK_EVENT_H 92c3b5b8a5SMatthias Ringwald 93c3b5b8a5SMatthias Ringwald#if defined __cplusplus 94c3b5b8a5SMatthias Ringwaldextern "C" { 95c3b5b8a5SMatthias Ringwald#endif 96c3b5b8a5SMatthias Ringwald 97c3b5b8a5SMatthias Ringwald#include "btstack_util.h" 98c3b5b8a5SMatthias Ringwald#include <stdint.h> 99c3b5b8a5SMatthias Ringwald 100313e337bSMatthias Ringwald#ifdef ENABLE_BLE 101313e337bSMatthias Ringwald#include "ble/gatt_client.h" 102313e337bSMatthias Ringwald#endif 103313e337bSMatthias Ringwald 104c3b5b8a5SMatthias Ringwald/* API_START */ 105c3b5b8a5SMatthias Ringwald 1060e2df43fSMatthias Ringwald/** 1070e2df43fSMatthias Ringwald * @brief Get event type 1080e2df43fSMatthias Ringwald * @param event 1090e2df43fSMatthias Ringwald * @return type of event 1100e2df43fSMatthias Ringwald */ 1110e2df43fSMatthias Ringwaldstatic inline uint8_t hci_event_packet_get_type(const uint8_t * event){ 1120e2df43fSMatthias Ringwald return event[0]; 1130e2df43fSMatthias Ringwald} 1140e2df43fSMatthias Ringwald 115c3b5b8a5SMatthias Ringwald""" 116c3b5b8a5SMatthias Ringwald 117c3b5b8a5SMatthias Ringwaldhfile_header_end = """ 118c3b5b8a5SMatthias Ringwald 119c3b5b8a5SMatthias Ringwald/* API_END */ 120c3b5b8a5SMatthias Ringwald 121c3b5b8a5SMatthias Ringwald#if defined __cplusplus 122c3b5b8a5SMatthias Ringwald} 123c3b5b8a5SMatthias Ringwald#endif 124c3b5b8a5SMatthias Ringwald 125c3b5b8a5SMatthias Ringwald#endif // __BTSTACK_EVENT_H 126c3b5b8a5SMatthias Ringwald""" 127c3b5b8a5SMatthias Ringwald 128313e337bSMatthias Ringwaldc_prototoype_simple_return = '''/** 129c3b5b8a5SMatthias Ringwald * @brief {description} 1300e2df43fSMatthias Ringwald * @param event packet 131c3b5b8a5SMatthias Ringwald * @return {result_name} 132c3b5b8a5SMatthias Ringwald * @note: btstack_type {format} 133c3b5b8a5SMatthias Ringwald */ 134c3b5b8a5SMatthias Ringwaldstatic inline {result_type} {fn_name}(const uint8_t * event){{ 135c3b5b8a5SMatthias Ringwald {code} 136c3b5b8a5SMatthias Ringwald}} 137c3b5b8a5SMatthias Ringwald''' 138c3b5b8a5SMatthias Ringwald 139313e337bSMatthias Ringwaldc_prototoype_struct_return = '''/** 140c3b5b8a5SMatthias Ringwald * @brief {description} 1410e2df43fSMatthias Ringwald * @param event packet 142c3b5b8a5SMatthias Ringwald * @param Pointer to storage for {result_name} 143c3b5b8a5SMatthias Ringwald * @note: btstack_type {format} 144c3b5b8a5SMatthias Ringwald */ 145c3b5b8a5SMatthias Ringwaldstatic inline void {fn_name}(const uint8_t * event, {result_type} {result_name}){{ 146c3b5b8a5SMatthias Ringwald {code} 147c3b5b8a5SMatthias Ringwald}} 148c3b5b8a5SMatthias Ringwald''' 149c3b5b8a5SMatthias Ringwald 150313e337bSMatthias Ringwaldc_prototoype_unsupported = '''/** 151c3b5b8a5SMatthias Ringwald * @brief {description} 1520e2df43fSMatthias Ringwald * @param event packet 153c3b5b8a5SMatthias Ringwald * @return {result_name} 154c3b5b8a5SMatthias Ringwald * @note: btstack_type {format} 155c3b5b8a5SMatthias Ringwald */ 156c3b5b8a5SMatthias Ringwald// static inline {result_type} {fn_name}(const uint8_t * event){{ 157c3b5b8a5SMatthias Ringwald// not implemented yet 158c3b5b8a5SMatthias Ringwald// }} 159c3b5b8a5SMatthias Ringwald''' 160c3b5b8a5SMatthias Ringwald 1610e2df43fSMatthias Ringwaldmeta_event_template = '''/*** 1620e2df43fSMatthias Ringwald * @brief Get subevent code for {meta_event} event 1630e2df43fSMatthias Ringwald * @param event packet 1640e2df43fSMatthias Ringwald * @return subevent_code 1650e2df43fSMatthias Ringwald */ 1660e2df43fSMatthias Ringwaldstatic inline uint8_t hci_event_{meta_event}_meta_get_subevent_code(const uint8_t * event){{ 1670e2df43fSMatthias Ringwald return event[2]; 1680e2df43fSMatthias Ringwald}} 1690e2df43fSMatthias Ringwald''' 1700e2df43fSMatthias Ringwald 171c3b5b8a5SMatthias Ringwald# global variables/defines 1729d585a82SMatthias Ringwald# gen_path = '../src/btstack_event.h' 173c3b5b8a5SMatthias Ringwald 174c3b5b8a5SMatthias Ringwalddefines = dict() 175c3b5b8a5SMatthias Ringwalddefines_used = set() 176c3b5b8a5SMatthias Ringwald 177c3b5b8a5SMatthias Ringwaldparam_read = { 178c3b5b8a5SMatthias Ringwald '1' : 'return event[{offset}];', 179c3b5b8a5SMatthias Ringwald 'J' : 'return event[{offset}];', 180f8fbdce0SMatthias Ringwald '2' : 'return little_endian_read_16(event, {offset});', 181f8fbdce0SMatthias Ringwald 'L' : 'return little_endian_read_16(event, {offset});', 182f8fbdce0SMatthias Ringwald '3' : 'return little_endian_read_24(event, {offset});', 183f8fbdce0SMatthias Ringwald '4' : 'return little_endian_read_32(event, {offset});', 184f8fbdce0SMatthias Ringwald 'H' : 'return little_endian_read_16(event, {offset});', 185313e337bSMatthias Ringwald 'B' : 'reverse_bd_addr(&event[{offset}], {result_name});', 1867bd8e93bSMatthias Ringwald 'R' : 'return &event[{offset}];', 1874de250b4SMatthias Ringwald 'T' : 'return (const char *) &event[{offset}];', 18882180fcaSMatthias Ringwald 'Q' : 'reverse_bytes(&event[{offset}], {result_name}, 32);', 1894de250b4SMatthias Ringwald 'V' : 'return &event[{offset}];', 190313e337bSMatthias Ringwald 'X' : 'gatt_client_deserialize_service(event, {offset}, {result_name});', 191313e337bSMatthias Ringwald 'Y' : 'gatt_client_deserialize_characteristic(event, {offset}, {result_name});', 192313e337bSMatthias Ringwald 'Z' : 'gatt_client_deserialize_characteristic_descriptor(event, {offset}, {result_name});', 193c3b5b8a5SMatthias Ringwald} 194c3b5b8a5SMatthias Ringwald 195c3b5b8a5SMatthias Ringwalddef c_type_for_btstack_type(type): 196c3b5b8a5SMatthias Ringwald param_types = { '1' : 'uint8_t', '2' : 'uint16_t', '3' : 'uint32_t', '4' : 'uint32_t', 'H' : 'hci_con_handle_t', 'B' : 'bd_addr_t', 197c3b5b8a5SMatthias Ringwald 'D' : 'const uint8_t *', 'E' : 'const uint8_t * ', 'N' : 'String' , 'P' : 'const uint8_t *', 'A' : 'const uint8_t *', 198c3b5b8a5SMatthias Ringwald 'R' : 'const uint8_t *', 'S' : 'const uint8_t *', 199c3b5b8a5SMatthias Ringwald 'J' : 'int', 'L' : 'int', 'V' : 'const uint8_t *', 'U' : 'BT_UUID', 20082180fcaSMatthias Ringwald 'Q' : 'uint8_t *', 201313e337bSMatthias Ringwald 'X' : 'gatt_client_service_t *', 'Y' : 'gatt_client_characteristic_t *', 'Z' : 'gatt_client_characteristic_descriptor_t *', 2027bd8e93bSMatthias Ringwald 'T' : 'const char *'} 203c3b5b8a5SMatthias Ringwald return param_types[type] 204c3b5b8a5SMatthias Ringwald 205c3b5b8a5SMatthias Ringwalddef size_for_type(type): 20682180fcaSMatthias Ringwald param_sizes = { '1' : 1, '2' : 2, '3' : 3, '4' : 4, 'H' : 2, 'B' : 6, 'D' : 8, 'E' : 240, 'N' : 248, 'P' : 16, 'Q':32, 207c3b5b8a5SMatthias Ringwald 'A' : 31, 'S' : -1, 'V': -1, 'J' : 1, 'L' : 2, 'U' : 16, 'X' : 20, 'Y' : 24, 'Z' : 18, 'T':-1} 208c3b5b8a5SMatthias Ringwald return param_sizes[type] 209c3b5b8a5SMatthias Ringwald 210c3b5b8a5SMatthias Ringwalddef format_function_name(event_name): 2117bd8e93bSMatthias Ringwald event_name = event_name.lower() 2127bd8e93bSMatthias Ringwald if 'event' in event_name: 2137bd8e93bSMatthias Ringwald return event_name; 2147bd8e93bSMatthias Ringwald return event_name+'_event' 215c3b5b8a5SMatthias Ringwald 216c3b5b8a5SMatthias Ringwalddef template_for_type(field_type): 217c3b5b8a5SMatthias Ringwald global c_prototoype_simple_return 218c3b5b8a5SMatthias Ringwald global c_prototoype_struct_return 21982180fcaSMatthias Ringwald types_with_struct_return = "BQXYZ" 220c3b5b8a5SMatthias Ringwald if field_type in types_with_struct_return: 221c3b5b8a5SMatthias Ringwald return c_prototoype_struct_return 222c3b5b8a5SMatthias Ringwald else: 223c3b5b8a5SMatthias Ringwald return c_prototoype_simple_return 224c3b5b8a5SMatthias Ringwald 225c3b5b8a5SMatthias Ringwalddef all_fields_supported(format): 226c3b5b8a5SMatthias Ringwald global param_read 227c3b5b8a5SMatthias Ringwald for f in format: 228c3b5b8a5SMatthias Ringwald if not f in param_read: 229c3b5b8a5SMatthias Ringwald return False 230c3b5b8a5SMatthias Ringwald return True 231c3b5b8a5SMatthias Ringwald 232c3b5b8a5SMatthias Ringwalddef create_getter(event_name, field_name, field_type, offset, supported): 233c3b5b8a5SMatthias Ringwald global c_prototoype_unsupported 234c3b5b8a5SMatthias Ringwald global param_read 235c3b5b8a5SMatthias Ringwald 236568284b0SMatthias Ringwald description = "Get field %s from event %s" % (field_name, event_name.upper()) 237c3b5b8a5SMatthias Ringwald result_name = field_name 238c3b5b8a5SMatthias Ringwald fn_name = "%s_get_%s" % (event_name, field_name) 239c3b5b8a5SMatthias Ringwald result_type = c_type_for_btstack_type(field_type) 240c3b5b8a5SMatthias Ringwald template = c_prototoype_unsupported 241c3b5b8a5SMatthias Ringwald code = '' 242c3b5b8a5SMatthias Ringwald if supported and field_type in param_read: 243c3b5b8a5SMatthias Ringwald template = template_for_type(field_type) 244c3b5b8a5SMatthias Ringwald code = param_read[field_type].format(offset=offset, result_name=result_name) 245c3b5b8a5SMatthias Ringwald return template.format(description=description, fn_name=fn_name, result_name=result_name, result_type=result_type, code=code, format=field_type) 246c3b5b8a5SMatthias Ringwald 247313e337bSMatthias Ringwalddef is_le_event(event_group): 248313e337bSMatthias Ringwald return event_group in ['GATT', 'ANCS', 'SM'] 249313e337bSMatthias Ringwald 250c3b5b8a5SMatthias Ringwalddef create_events(events): 251c3b5b8a5SMatthias Ringwald global gen_path 252c3b5b8a5SMatthias Ringwald global copyright 253c3b5b8a5SMatthias Ringwald global hfile_header_begin 254c3b5b8a5SMatthias Ringwald global hfile_header_end 2550e2df43fSMatthias Ringwald global meta_event_template 256c3b5b8a5SMatthias Ringwald 257c3b5b8a5SMatthias Ringwald with open(gen_path, 'wt') as fout: 258c3b5b8a5SMatthias Ringwald fout.write(copyright) 259c3b5b8a5SMatthias Ringwald fout.write(hfile_header_begin) 2600e2df43fSMatthias Ringwald 2610e2df43fSMatthias Ringwald for meta_event in meta_events: 2620e2df43fSMatthias Ringwald fout.write(meta_event_template.format(meta_event=meta_event.lower())) 2630e2df43fSMatthias Ringwald 264c3b5b8a5SMatthias Ringwald for event_type, event_name, format, args in events: 26572b50801SMatthias Ringwald parts = event_name.split("_") 266313e337bSMatthias Ringwald event_group = parts[0] 267f1b34e8dSMatthias Ringwald if not event_group in supported_event_groups: 268a59bfbf7SMatthias Ringwald print("// %s " % event_name) 2697bd8e93bSMatthias Ringwald continue 2706397af06SMatthias Ringwald # print(event_name) 2716397af06SMatthias Ringwald base_name = format_function_name(event_name) 2724de250b4SMatthias Ringwald length_name = '' 273c3b5b8a5SMatthias Ringwald offset = 2 274e222d6a0SMatthias Ringwald offset_is_number = 1 275e222d6a0SMatthias Ringwald offset_unknown = 0 276c3b5b8a5SMatthias Ringwald supported = all_fields_supported(format) 277e222d6a0SMatthias Ringwald last_variable_length_field_pos = "" 278313e337bSMatthias Ringwald if is_le_event(event_group): 279313e337bSMatthias Ringwald fout.write("#ifdef ENABLE_BLE\n") 2806397af06SMatthias Ringwald if len(format) != len(args): 2816397af06SMatthias Ringwald print(event_name.upper()) 2826397af06SMatthias Ringwald print ("Format %s does not match params %s " % (format, args)) 2836397af06SMatthias Ringwald print 284c3b5b8a5SMatthias Ringwald for f, arg in zip(format, args): 285c3b5b8a5SMatthias Ringwald field_name = arg 28690944a9aSMatthias Ringwald if field_name.lower() == 'subevent_code': 28790944a9aSMatthias Ringwald offset += 1 28890944a9aSMatthias Ringwald continue 289e222d6a0SMatthias Ringwald if offset_unknown: 290e222d6a0SMatthias Ringwald print("Param after variable length field without preceding 'J' lenght field") 291e222d6a0SMatthias Ringwald break 292c3b5b8a5SMatthias Ringwald field_type = f 2936397af06SMatthias Ringwald text = create_getter(base_name, field_name, field_type, offset, supported) 294c3b5b8a5SMatthias Ringwald fout.write(text) 2957bd8e93bSMatthias Ringwald if field_type in 'RT': 296c3b5b8a5SMatthias Ringwald break 297e222d6a0SMatthias Ringwald if field_type in 'J': 298e222d6a0SMatthias Ringwald if offset_is_number: 299e222d6a0SMatthias Ringwald last_variable_length_field_pos = '%u' % offset 300e222d6a0SMatthias Ringwald else: 301e222d6a0SMatthias Ringwald last_variable_length_field_pos = offset 302e222d6a0SMatthias Ringwald if field_type in 'V': 303e222d6a0SMatthias Ringwald if last_variable_length_field_pos >= 0: 304e222d6a0SMatthias Ringwald if offset_is_number: 305e222d6a0SMatthias Ringwald # convert to string 306e222d6a0SMatthias Ringwald offset = '%u' % offset 307e222d6a0SMatthias Ringwald offset_is_number = 0 308e222d6a0SMatthias Ringwald offset = offset + ' + event[%s]' % last_variable_length_field_pos 309e222d6a0SMatthias Ringwald else: 310e222d6a0SMatthias Ringwald offset_unknown = 1 311e222d6a0SMatthias Ringwald else: 312e222d6a0SMatthias Ringwald if offset_is_number: 313c3b5b8a5SMatthias Ringwald offset += size_for_type(field_type) 314e222d6a0SMatthias Ringwald else: 315e222d6a0SMatthias Ringwald offset = offset + ' + %u' % size_for_type(field_type) 316313e337bSMatthias Ringwald if is_le_event(event_group): 317313e337bSMatthias Ringwald fout.write("#endif\n") 318313e337bSMatthias Ringwald fout.write("\n") 319c3b5b8a5SMatthias Ringwald 320c3b5b8a5SMatthias Ringwald fout.write(hfile_header_end) 321c3b5b8a5SMatthias Ringwald 3229d585a82SMatthias Ringwaldbtstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..') 3239d585a82SMatthias Ringwaldgen_path = btstack_root + '/src/btstack_event.h' 324c3b5b8a5SMatthias Ringwald 325c3b5b8a5SMatthias Ringwaldprint(program_info) 326c3b5b8a5SMatthias Ringwald 327c3b5b8a5SMatthias Ringwald# parse events 328c3b5b8a5SMatthias Ringwald(events, le_events, event_types) = parser.parse_events() 329c3b5b8a5SMatthias Ringwald 330c3b5b8a5SMatthias Ringwald# create event field accesors 331c3b5b8a5SMatthias Ringwaldcreate_events(events + le_events) 332c3b5b8a5SMatthias Ringwald 333c3b5b8a5SMatthias Ringwald# done 334c3b5b8a5SMatthias Ringwaldprint('Done!') 335