• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3#   Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
4#    Licensed under the Apache License, Version 2.0 (the "License");
5#    you may not use this file except in compliance with the License.
6#    You may obtain a copy of the License at
7#
8#        http://www.apache.org/licenses/LICENSE-2.0
9#
10#    Unless required by applicable law or agreed to in writing, software
11#    distributed under the License is distributed on an "AS IS" BASIS,
12#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#    See the License for the specific language governing permissions and
14#    limitations under the License.
15
16import os
17import re
18import sys
19import platform
20import string
21import shutil
22import time
23import json
24import xml.etree.ElementTree as ET
25
26py_version = platform.python_version()
27
28G_PARAMS = {}
29XML_PATH="build/config/target_config/<chip>/hdb_config/database_cfg/mk_hdb_xml.json"
30
31g_fsm_status = ""
32enum_dict = {}
33stuct_dict = {}
34
35def print_enum_dict(dict_info):
36    for name in dict_info:
37        print("    %s" % name)
38        xx = dict_info[name]
39        for key in xx:
40            print("        %s" % key)
41
42def print_struct_dict(dict_info):
43    for msg_id in dict_info:
44        print("    %s" % msg_id)
45        msg_dict = dict_info[msg_id]
46        for key in msg_dict:
47            print("        %s" % key)
48            if key != "struct_para_list":
49                print("            %s" % msg_dict[key])
50            else:
51                for para in msg_dict[key]:
52                    print("            %s" % para)
53
54def gen_enum_dict_fun(datalines):
55    global g_fsm_status
56    global enum_dict
57    enum_name = ""
58    g_fsm_status = "FIND_ENUM_START"
59    # 遍历行内容
60    for line in datalines:
61        line = line.replace('\r\n', '')
62        line = line.replace('\t', ' ')
63        if len(line) == 0:
64            continue
65        m = re.search(r'^\/\/', line.strip())
66        if m is not None:
67            continue
68        if g_fsm_status == "FIND_ENUM_START":
69            m = re.search(r'\{\s*(.*)\s*START\s*\}', line.strip())
70            if m is not None:
71                enum_name = m.groups()[0].strip().replace(" ", "_")
72                g_fsm_status = "FIND_ENUM_MEMBER"
73                if enum_name not in enum_dict:
74                    enum_dict[enum_name] = []
75        elif g_fsm_status == "FIND_ENUM_MEMBER":
76            m = re.search(r'\{\s*PUBLIC\s*END\s*\}', line.strip())
77            if m is not None:
78                g_fsm_status = "FIND_ENUM_START"
79            else:
80                member = line.strip().split(" ")
81                if len(member) == 2:
82                    temp = ("    %s = %s," % (member[1].split(".")[0], member[0]))
83                    if enum_dict[enum_name].count(temp) == 0:
84                        enum_dict[enum_name].append(temp)
85    g_fsm_status = ""
86    #print_enum_dict(enum_dict)
87
88def add_enum_dict_fun(msg_id, para_index, enum_list):
89    enum_name = ("bt_status_enum_msg_id_%x_%d" % (msg_id, para_index))
90    if enum_name not in enum_dict:
91        enum_dict[enum_name] = []
92    for item in enum_list:
93        member = item.strip().split(" ")
94        if len(member) == 2:
95            temp = ("    %s = %s," % (member[1], member[0]))
96            if enum_dict[enum_name].count(temp) == 0:
97                enum_dict[enum_name].append(temp)
98    return enum_name
99
100def merge_enum_dict_fun(msg_id, para_index, enum_list):
101    enum_name = ("bt_status_enum_msg_id_%x_%d_" % (msg_id, para_index))
102    for item in enum_list:
103        enum_name = ("%s%s_" % (enum_name, item.strip()[2:].replace(" ", "_")))
104
105    if enum_name not in enum_dict:
106        enum_dict[enum_name] = []
107
108    for item in enum_list:
109        temp = item.strip()[2:].replace(" ", "_")
110        enum_dict[enum_name] += enum_dict[temp]
111    return enum_name
112
113def gen_struct_dict_fun(datalines):
114    global g_fsm_status
115    g_fsm_status = "FIND_STRUCT_START"
116    para_count = 0
117    msg_id = 0
118    msg_fmt = ""
119
120    for line in datalines:
121        line = line.replace('\r\n', '')
122        line = line.replace('\t', ' ')
123        line = line.replace('\\r', "")
124        line = line.replace('\\n', "")
125        line = line.replace('\r', "")
126        line = line.replace('\n', "")
127        line = line.replace("\\", "")
128        if len(line) == 0:
129            continue
130        m = re.search(r'^\/\/(.*)', line.strip())
131        if m is not None:
132            continue
133        if g_fsm_status == "FIND_STRUCT_START":
134            m = re.search(r'(MsgID=\S*)\s*;\s*(Parameter Number=[0-9]*)\s*;\s*(.*)\]', line.strip())
135            if m is not None:
136                para_count = int(m.groups()[1].strip().split("=")[1], 10)
137                msg_id = int(m.groups()[0].strip().split("=")[1], 16)
138                msg_fmt = m.groups()[2].strip()
139                if msg_id not in stuct_dict:
140                    temp = { }
141                    temp["full_str"] = line
142                    temp["para_count"] = para_count
143                    temp["msg_id"] = msg_id
144                    temp["msg_fmt"] = msg_fmt
145                    temp["struct_para_list"] = []
146                    stuct_dict[msg_id] = temp
147                g_fsm_status = "FIND_STRUCT_MEM"
148        elif g_fsm_status == "FIND_STRUCT_MEM":
149            temp = ("Parameter%d_CommandList\s*End" % (para_count))
150            m = re.search(temp, line.strip())
151            if m is not None:
152                g_fsm_status = "FIND_STRUCT_START"
153            stuct_dict[msg_id]["struct_para_list"].append(line)
154    #print_struct_dict(stuct_dict)
155
156def parse_struct_para_list(msg_id, struct_para_list):
157    global g_fsm_status
158    g_fsm_status = "FIND_PARA_START"
159    index = 0
160    para_mem_dict = {}
161    struct_str = "typedef struct {\n"
162    while len(struct_para_list) > 0:
163        para_str = struct_para_list.pop(0)
164        if g_fsm_status == "FIND_PARA_START":
165            m = re.search(r'CommandList\s*Start', para_str)
166            if m is not None:
167                g_fsm_status = "FIND_PARA_MEM"
168                index += 1
169                if index not in para_mem_dict:
170                    para_mem_dict[index] = []
171        elif g_fsm_status == "FIND_PARA_MEM":
172            m = re.search(r'CommandList\s*End', para_str)
173            if m is not None:
174                g_fsm_status = "FIND_PARA_START"
175            else:
176                m = re.search(r'Index\s*Show', para_str)
177                if m is None:
178                    para_mem_dict[index].append(para_str)
179
180    for item in para_mem_dict:
181        need_enum_ref = 0
182        if len(para_mem_dict[item]) == 0:
183            struct_str += ("    td_u32 para_%s;\n" % (item))
184        else:
185            for str in para_mem_dict[item]:
186                if str.find("$$") != -1:
187                    need_enum_ref = 1
188                    break
189            if need_enum_ref == 0:
190                enum_name = add_enum_dict_fun(msg_id, item, para_mem_dict[item])
191                struct_str += ("    %s para_%s;\n" % (enum_name, item))
192            else:
193                if len(para_mem_dict[item]) > 1:
194                    enum_name = merge_enum_dict_fun(msg_id, item, para_mem_dict[item])
195                    struct_str += ("    %s para_%s;\n" % (enum_name, item))
196                else:
197                    enum_name = para_mem_dict[item][0].strip()[2:].replace(" ", "_")
198                    struct_str += ("    %s para_%s;\n" % (enum_name, item))
199
200
201    struct_str += ("} bt_status_msg_id_%x;\n\n" % (msg_id))
202    return struct_str
203
204def get_struct_def_string():
205    struct_str = ""
206    for msg_id in stuct_dict:
207        msg_dict = stuct_dict[msg_id]
208        for key in msg_dict:
209            if key == "struct_para_list":
210                struct_str += parse_struct_para_list(msg_id, list(msg_dict[key]))
211    return struct_str
212
213def get_enum_def_string():
214    enum_str = ""
215    for item in enum_dict:
216        enum_str = "%stypedef enum {\n" % enum_str
217        for i in enum_dict[item]:
218            enum_str = ("%s%s\n" % (enum_str, i))
219        enum_str = ("%s} %s;\n\n" % (enum_str, item))
220    return enum_str
221
222def write_bt_status_def_file():
223    global G_PARAMS
224    txt_dst_dir = G_PARAMS["HDB_TXT_DST_DIR"]
225
226    struct_str = get_struct_def_string()
227    enum_str = get_enum_def_string()
228
229    dst_file = os.path.join(txt_dst_dir, "bt_status_hso_msg_struct_def.txt")
230
231    with open(dst_file, 'w') as dst_f:
232        dst_f.write('#include "base_datatype_def.txt"' + '\n')
233        dst_f.write(enum_str)
234        dst_f.write(struct_str)
235
236def add_content_to_xml(data, msg_root_element):
237    new_element = ET.Element('')
238    new_element.tag = 'MSG'
239    new_element.attrib['STRUCTURE'] = ("bt_status_msg_id_%x" % (data["msg_id"]))
240    new_element.attrib['NAME'] = data["msg_fmt"]
241    new_element.attrib['ID'] = hex((31 << 16) | (0xffff & data["msg_id"])) # OM_MSG_TYPE_STATUS = 31
242    new_element.tail = '\n\t\t\t'
243    msg_root_element.append(new_element)
244
245def write_bt_status_prim_xml_file():
246    global G_PARAMS
247
248    base_file_dir = os.path.join(G_PARAMS['HDB_XML_TEMP_BASE_DIR'], "bt_status")
249    if not os.path.isdir(base_file_dir):
250        os.makedirs(base_file_dir)
251
252    dst_xml_full_name = os.path.join(base_file_dir, "bt_status.xml")
253
254    msg_root_element = ET.Element('MSG_LOG')
255    for msg_id in stuct_dict:
256        add_content_to_xml(stuct_dict[msg_id], msg_root_element)
257
258    tree = ET.ElementTree(msg_root_element)
259    tree.write(dst_xml_full_name)
260
261def generate_db_file():
262    global G_PARAMS
263    bt_status_dir = G_PARAMS["BT_STATUS_DIR"]
264
265    bt_status_file = os.path.join(bt_status_dir, "STATUS_CommandList.txt")
266    try:
267        if py_version.startswith("3"):
268            try:
269                with open(bt_status_file, 'r', encoding="UTF-8") as fd_src:
270                    datalines = [line for line in fd_src]
271            except Exception:
272                with open(bt_status_file, 'r', encoding="ISO-8859-1") as fd_src:
273                    datalines = [line for line in fd_src]
274        else:
275            with open(bt_status_file, 'r') as fd_src:
276                datalines = [line for line in fd_src]
277    except Exception:
278        print("open file %s failed." % cfilepath)
279        return
280
281    gen_enum_dict_fun(datalines)
282    gen_struct_dict_fun(datalines)
283
284    write_bt_status_def_file()
285    write_bt_status_prim_xml_file()
286
287def generate_db():
288    global G_PARAMS
289    root = sys.argv[1]
290    chip = sys.argv[2]
291    in_path = XML_PATH
292    in_path = in_path.replace('<chip>', chip)
293
294    db_conf = None
295    conf = os.path.join(root, in_path)
296    with open(conf, 'r') as f:
297        db_conf = json.load(f)
298
299    G_PARAMS = {}
300    G_PARAMS['HDB_XML_TEMP_BASE_DIR'] = os.path.join(root, db_conf["HDB_XML_TEMP_BASE_DIR"])
301    G_PARAMS["HDB_TXT_DST_DIR"] = os.path.join(root, db_conf["HDB_TXT_DST_DIR"])
302    G_PARAMS["HDB_TXT_BASE_DATATYPE"] = os.path.join(root, db_conf["HDB_TXT_BASE_DATATYPE"])
303    G_PARAMS["HDB_TXT_SRC_DIR"] = os.path.join(root, db_conf["HDB_TXT_SRC_DIR"])
304    G_PARAMS["BT_STATUS_DIR"] = os.path.join(root, db_conf["BT_STATUS_DIR"])
305
306    txt_src_dir = G_PARAMS["HDB_TXT_SRC_DIR"]
307    txt_dst_dir = G_PARAMS["HDB_TXT_DST_DIR"]
308    base_datatype_def_txt = G_PARAMS["HDB_TXT_BASE_DATATYPE"]
309    bt_status_dir = G_PARAMS["BT_STATUS_DIR"]
310
311    if not os.path.exists(txt_src_dir):
312        return
313    if not os.path.exists(base_datatype_def_txt):
314        return
315    if not os.path.exists(bt_status_dir):
316        return
317    if not os.path.exists(txt_dst_dir):
318        os.makedirs(txt_dst_dir)
319
320    generate_db_file()
321
322# main
323if __name__ == "__main__":
324    generate_db()
325