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