1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2020-2021 Huawei Device Co., Ltd. 5# 6# HDF is dual licensed: you can use it either under the terms of 7# the GPL, or the BSD license, at your option. 8# See the LICENSE file in the root of this repository for complete details. 9 10 11import json 12from string import Template 13import os 14 15import hdf_utils 16from hdf_tool_settings import HdfToolSettings 17from hdf_tool_exception import HdfToolException 18from command_line.operate_group_passwd import OperateGroupPasswd 19from .driver_add.hdf_add_driver import HdfAddDriver 20from .hdf_command_handler_base import HdfCommandHandlerBase 21from .hdf_command_error_code import CommandErrorCode 22from .hdf_device_info_hcs import HdfDeviceInfoHcsFile 23from .hdf_get_handler import HdfGetHandler 24from .hdf_vendor_build_file import HdfVendorBuildFile 25from .hdf_vendor_kconfig_file import HdfVendorKconfigFile 26from .hdf_vendor_mk_file import HdfVendorMkFile 27from .hdf_driver_config_file import HdfDriverConfigFile 28from .hdf_vendor_makefile import HdfVendorMakeFile 29from .hdf_defconfig_patch import HdfDefconfigAndPatch 30 31 32class HdfAddHandler(HdfCommandHandlerBase): 33 def __init__(self, args): 34 super(HdfAddHandler, self).__init__() 35 self.cmd = 'add' 36 self.handlers = { 37 'vendor': self._add_vendor_handler, 38 'module': self._add_module_handler, 39 'driver': self._add_driver_handler, 40 'config': self._add_config_handler, 41 } 42 self.parser.add_argument("--action_type", 43 help=' '.join(self.handlers.keys()), 44 required=True) 45 self.parser.add_argument("--root_dir", required=True) 46 self.parser.add_argument("--vendor_name") 47 self.parser.add_argument("--module_name") 48 self.parser.add_argument("--driver_name") 49 self.parser.add_argument("--board_name") 50 self.parser.add_argument("--kernel_name") 51 self.parser.add_argument("--runmode") 52 self.parser.add_argument("--device_name") 53 self.args_original = args 54 self.args = self.parser.parse_args(args) 55 self.hdf_tool = HdfToolSettings() 56 57 @staticmethod 58 def _render(template_path, output_path, data_model): 59 if not os.path.exists(template_path): 60 return 61 raw_content = hdf_utils.read_file(template_path) 62 contents = Template(raw_content).safe_substitute(data_model) 63 hdf_utils.write_file(output_path, contents) 64 65 def _file_gen_lite(self, template, out_dir, filename, model): 66 templates_dir = hdf_utils.get_templates_lite_dir() 67 template_path = os.path.join(templates_dir, template) 68 file_path = os.path.join(out_dir, filename) 69 self._render(template_path, file_path, model) 70 71 def _add_vendor_handler(self): 72 self.check_arg_raise_if_not_exist("vendor_name") 73 root, vendor, _, _, board = self.get_args() 74 target_dir = hdf_utils.get_vendor_hdf_dir(root, vendor) 75 if os.path.exists(target_dir): 76 raise HdfToolException( 77 "%s already exists" % 78 target_dir, CommandErrorCode.TARGET_ALREADY_EXIST) 79 os.makedirs(target_dir) 80 self._file_gen_lite('hdf_vendor_kconfig.template', target_dir, 81 'Kconfig', {}) 82 board_parent_path = self.hdf_tool.get_board_parent_path(board) 83 if not board_parent_path: 84 board_parent_path = 'vendor/hisilicon' 85 data_model = { 86 "board_parent_path": board_parent_path 87 } 88 self._file_gen_lite('hdf_vendor_mk.template', target_dir, 89 'hdf_vendor.mk', data_model) 90 91 def _add_module_handler(self): 92 self.check_arg_raise_if_not_exist("vendor_name") 93 self.check_arg_raise_if_not_exist("module_name") 94 self.check_arg_raise_if_not_exist("kernel_name") 95 self.check_arg_raise_if_not_exist("board_name") 96 self.check_arg_raise_if_not_exist("driver_name") 97 args_tuple = self.get_args() 98 root, vendor, module, driver, board, kernel, _ = args_tuple 99 board_list = self.hdf_tool.get_board_list() 100 if board not in board_list: 101 raise HdfToolException( 102 'supported boards name : %s not exits ' % board) 103 framework_hdf = hdf_utils.get_vendor_hdf_dir_framework(root) 104 if not os.path.exists(framework_hdf): 105 raise HdfToolException( 106 ' framework model path "%s" not exist' % 107 framework_hdf, CommandErrorCode.TARGET_NOT_EXIST) 108 # framework create file .c 109 framework_drv_root_dir = hdf_utils.get_drv_root_dir( 110 root, module) 111 if os.path.exists(framework_drv_root_dir): 112 raise HdfToolException('module "%s" already exist' % module, 113 CommandErrorCode.TARGET_ALREADY_EXIST) 114 os.makedirs(framework_drv_root_dir) 115 # create .c template driver file 116 state, driver_file_path = self._add_driver(*args_tuple) 117 if not state: 118 raise HdfToolException( 119 'create drivers file fail "%s" ' % 120 driver_file_path.split("\\")[-1]) 121 config_item, config_file_out = \ 122 self.diff_type_module_add_operation( 123 framework_hdf, driver_file_path, args_tuple) 124 config_name = "create_model.config" 125 config_file = hdf_utils.read_file( 126 os.path.join('resources', config_name)) 127 config_file_json = json.loads(config_file) 128 config_file_json[module] = config_file_out 129 hdf_utils.write_config( 130 root_path=root, config_file_json=config_file_json, 131 config_name=config_name) 132 return json.dumps(config_item) 133 134 def diff_type_module_add_operation(self, framework_hdf, 135 driver_file_path, args_tuple): 136 root, vendor, module, driver, board, kernel, _ = args_tuple 137 converter = hdf_utils.WordsConverter(self.args.module_name) 138 driver_name_converter = hdf_utils.WordsConverter(self.args.driver_name) 139 if board.endswith("user"): 140 file_path, model_level_config = \ 141 self._add_module_handler_linux_user( 142 framework_hdf, driver_file_path, 143 *args_tuple) 144 else: 145 adapter_hdf = hdf_utils.get_vendor_hdf_dir_adapter(root, kernel) 146 if not os.path.exists(adapter_hdf): 147 raise HdfToolException( 148 ' adapter model path "%s" not exist' % 149 adapter_hdf, CommandErrorCode.TARGET_NOT_EXIST) 150 # create module folder under the adapter path 151 adapter_model_path = os.path.join(adapter_hdf, 'model', module) 152 if not os.path.exists(adapter_model_path): 153 os.makedirs(adapter_model_path) 154 data_model = { 155 "module_upper_case": converter.upper_case(), 156 "module_lower_case": converter.lower_case(), 157 "driver_file_name": ("%s_driver.c" % driver_name_converter.lower_case()), 158 "driver_name": driver_name_converter.lower_case() 159 } 160 # create files in the module under the adapter 161 if kernel == 'liteos': 162 file_path, model_level_config = \ 163 self._add_module_handler_liteos( 164 framework_hdf, adapter_model_path, 165 data_model, converter, *args_tuple) 166 elif kernel == "linux": 167 file_path, model_level_config = \ 168 self._add_module_handler_linux( 169 framework_hdf, adapter_model_path, 170 data_model, *args_tuple) 171 else: 172 model_level_config = "" 173 base_config = { 174 'module_name': module, 175 'module_path': file_path, 176 'driver_name': "%s_driver" % driver, 177 'driver_file_path': driver_file_path, 178 } 179 config_item = {'enabled': True} 180 config_item.update(base_config) 181 config_file_out = {'module_level_config_path': model_level_config} 182 config_file_out.update(base_config) 183 return config_item, config_file_out 184 185 def _add_module_handler_liteos(self, framework_hdf, adapter_model_path, 186 data_model, converter, *args_tuple): 187 root, vendor, module, driver, board, kernel, _ = args_tuple 188 liteos_file_path = {} 189 liteos_level_config_file_path = {} 190 liteos_file_name = ['BUILD.gn', 'Kconfig', 'Makefile'] 191 temp_path = self.hdf_tool.get_template_path() 192 template_path = os.path.join(framework_hdf, temp_path) 193 for file_name in liteos_file_name: 194 for i in hdf_utils.template_filename_filtrate( 195 template_path, kernel): 196 if i.find(file_name.split(".")[0]) > 0: 197 out_path = os.path.join(adapter_model_path, file_name) 198 self._render(os.path.join(template_path, i), 199 out_path, data_model) 200 liteos_file_path[file_name] = out_path 201 202 # Modify Kconfig file 203 vendor_k = HdfVendorKconfigFile(root, vendor, kernel, path="") 204 vendor_k_path = vendor_k.add_module([module, 'Kconfig']) 205 liteos_level_config_file_path[module + "_Kconfig"] = vendor_k_path 206 207 # Modify hdf_lite.mk file 208 vendor_mk = HdfVendorMkFile(root, vendor) 209 vendor_mk_path = vendor_mk.add_module(module) 210 liteos_level_config_file_path[module + "_hdf_lite"] = vendor_mk_path 211 212 # Modify Build.gn file 213 vendor_gn = HdfVendorBuildFile(root, vendor) 214 vendor_gn_path = vendor_gn.add_module(module) 215 liteos_level_config_file_path[module + "Build"] = vendor_gn_path 216 217 # Modify config file 218 device_info = HdfDeviceInfoHcsFile( 219 root, vendor, module, board, driver, path="") 220 hcs_file_path = device_info.add_model_hcs_file_config() 221 liteos_file_path["devices_info.hcs"] = hcs_file_path 222 223 dot_file_list = hdf_utils.get_dot_configs_path(root, vendor, board) 224 template_string = "LOSCFG_DRIVERS_HDF_${module_upper_case}=y\n" 225 new_demo_config = Template(template_string).substitute( 226 {"module_upper_case": converter.upper_case()}) 227 for dot_file in dot_file_list: 228 file_lines = hdf_utils.read_file_lines(dot_file) 229 file_lines[-1] = "{}\n".format(file_lines[-1].strip()) 230 if new_demo_config != file_lines[-1]: 231 file_lines.append(new_demo_config) 232 hdf_utils.write_file_lines(dot_file, file_lines) 233 liteos_level_config_file_path[module + "_dot_configs"] = dot_file_list 234 return liteos_file_path, liteos_level_config_file_path 235 236 def _add_module_handler_linux(self, framework_hdf, adapter_model_path, 237 data_model, *args_tuple): 238 root, vendor, module, driver, board, kernel, _ = args_tuple 239 linux_file_path = {} 240 linux_level_config_file_path = {} 241 linux_file_name = ['Kconfig', 'Makefile'] 242 temp_path = self.hdf_tool.get_template_path() 243 template_path = os.path.join(framework_hdf, temp_path) 244 for file_name in linux_file_name: 245 for i in hdf_utils.template_filename_filtrate( 246 template_path, kernel): 247 if i.find(file_name.split(".")[0]) > 0: 248 out_path = os.path.join(adapter_model_path, file_name) 249 self._render(os.path.join(template_path, i), 250 out_path, data_model) 251 linux_file_path[file_name] = out_path 252 253 # Modify Kconfig file 254 vendor_k = HdfVendorKconfigFile(root, vendor, kernel, path="") 255 vendor_k_path = vendor_k.add_module([module, 'Kconfig']) 256 linux_level_config_file_path[module + "_Kconfig"] = vendor_k_path 257 258 # Modify Makefile file 259 vendor_mk = HdfVendorMakeFile(root, vendor, kernel, path='') 260 vendor_mk_path = vendor_mk.add_module(data_model) 261 linux_level_config_file_path[module + "_Makefile"] = vendor_mk_path 262 # device_info.hcs 263 device_info = HdfDeviceInfoHcsFile( 264 root, vendor, module, board, driver, path="") 265 hcs_file_path = device_info.add_model_hcs_file_config() 266 linux_file_path["devices_info.hcs"] = hcs_file_path 267 268 # dot_configs config file 269 template_string = "CONFIG_DRIVERS_HDF_${module_upper_case}=y\n" 270 new_demo_config = [Template(template_string).substitute(data_model)] 271 defconfig_patch = HdfDefconfigAndPatch( 272 root, vendor, kernel, board, 273 data_model, new_demo_config) 274 275 config_path = defconfig_patch.get_config_config() 276 files = [] 277 patch_list = defconfig_patch.add_module(config_path, files=files, codetype=None) 278 config_path = defconfig_patch.get_config_patch() 279 files1 = [] 280 defconfig_list = defconfig_patch.add_module(config_path, files=files1, codetype=None) 281 linux_level_config_file_path[module + "_dot_configs"] = \ 282 list(set(patch_list + defconfig_list)) 283 return linux_file_path, linux_level_config_file_path 284 285 def _add_module_handler_linux_user(self, framework_hdf, driver_file_path, 286 *args_tuple): 287 linux_file_path = {} 288 linux_level_config_file_path = {} 289 # create user build.gn files 290 root, vendor, module, driver, board, kernel, _ = args_tuple 291 relative_path = self.hdf_tool.get_user_adapter_path() 292 user_model_path = os.path.join(root, relative_path, module) 293 if not os.path.exists(user_model_path): 294 os.makedirs(user_model_path) 295 user_model_file_path = os.path.join(user_model_path, "BUILD.gn") 296 temp_path = self.hdf_tool.get_template_path() 297 template_path = os.path.join(framework_hdf, temp_path) 298 user_file_path = driver_file_path.split(root)[-1].replace("\\", "/") 299 if user_file_path.startswith("/"): 300 driver_file_name = "".join(["/", user_file_path.replace("\\", "/")]) 301 else: 302 driver_file_name = "".join(["//", user_file_path.replace("\\", "/")]) 303 data_model = { 304 "model_path": "/".join(["/", relative_path, module]), 305 "driver_file_name": driver_file_name, 306 "model_name": module, 307 } 308 for file_name in os.listdir(template_path): 309 if file_name.startswith("User_build"): 310 user_template_build = os.path.join(template_path, file_name) 311 if os.path.exists(user_template_build): 312 self._render(user_template_build, 313 user_model_file_path, data_model) 314 linux_file_path["BUILD.gn"] = user_model_file_path 315 linux_file_path = self.revise_passwd_group_file( 316 root_path=root, linux_file_path=linux_file_path, model_name=module) 317 # build.gn file add path 318 ohos_relative_path = '/'.join(relative_path.split("/")[:-1]) 319 ohos_path = os.path.join(root, ohos_relative_path, 'BUILD.gn') 320 user_build_info = hdf_utils.read_file_lines(ohos_path) 321 ohos_template_line = "${model_path}:libhdf_${model_name}_hotplug" 322 need_add_line = Template(ohos_template_line).substitute(data_model) 323 temp_line = (' "%s",' % need_add_line) + '\n' 324 for index, info in enumerate(user_build_info): 325 if info.find("else") > 0 and temp_line not in user_build_info: 326 user_build_info.insert(index + 3, temp_line) 327 hdf_utils.write_file_lines(ohos_path, user_build_info) 328 break 329 linux_file_path["adapter_build.gn"] = ohos_path 330 # add hcs file 331 device_info = HdfDeviceInfoHcsFile( 332 root, vendor, module, board, driver, path="") 333 hcs_file_path = device_info.add_model_hcs_file_config_user() 334 linux_file_path["devices_info.hcs"] = hcs_file_path 335 return linux_file_path, linux_level_config_file_path 336 337 def _add_driver(self, *args_tuple): 338 root, vendor, module, driver, board, kernel, _ = args_tuple 339 drv_converter = hdf_utils.WordsConverter(self.args.driver_name) 340 drv_src_dir = hdf_utils.get_drv_src_dir(root, module) 341 342 parent_depth = len(drv_src_dir.split(os.path.sep)) 343 dir_dict = {} 344 for root, dirs, _ in os.walk(drv_src_dir, topdown=True): 345 for dir_name in dirs: 346 dir_path = os.path.join(root, dir_name) 347 if len(dir_path.split(os.path.sep)) == parent_depth + 1: 348 dir_dict[dir_name] = [] 349 if len(dir_path.split(os.path.sep)) == parent_depth + 2: 350 dir_dict.get(dir_path.split(os.path.sep)[-2]).append(dir_name) 351 352 common_dir_list = dir_dict.get("common") 353 if common_dir_list is not None: 354 if "src" in common_dir_list: 355 driver_file_path = os.path.join(drv_src_dir, "common", "src") 356 else: 357 driver_file_path = os.path.join(drv_src_dir, "common") 358 else: 359 driver_file_path = drv_src_dir 360 361 if not os.path.exists(driver_file_path): 362 raise HdfToolException( 363 '"%s" is path not exist' % 364 driver_file_path, CommandErrorCode.TARGET_NOT_EXIST) 365 data_model = { 366 'driver_lower_case': drv_converter.lower_case(), 367 'driver_upper_camel_case': drv_converter.upper_camel_case(), 368 'driver_lower_camel_case': drv_converter.lower_camel_case(), 369 'driver_upper_case': drv_converter.upper_case() 370 } 371 self._file_gen_lite('hdf_driver.c.template', driver_file_path, 372 '%s_driver.c' % driver, data_model) 373 result_path = os.path.join(driver_file_path, '%s_driver.c' % driver) 374 return True, result_path 375 376 def _add_driver_handler(self): 377 self.check_arg_raise_if_not_exist("vendor_name") 378 self.check_arg_raise_if_not_exist("module_name") 379 self.check_arg_raise_if_not_exist("kernel_name") 380 self.check_arg_raise_if_not_exist("board_name") 381 self.check_arg_raise_if_not_exist("driver_name") 382 self.check_arg_raise_if_not_exist("device_name") 383 args_tuple = self.get_args() 384 root, vendor, module, driver, board, kernel, device = args_tuple 385 board_list = self.hdf_tool.get_create_board_type() 386 if board not in board_list: 387 raise HdfToolException( 388 'supported boards name : %s not exits ' % board, 389 CommandErrorCode.TARGET_NOT_EXIST) 390 if "--runmode" in self.args_original: 391 runmode_index = self.args_original.index("--runmode") 392 temp_args = self.args_original[:runmode_index] + \ 393 self.args_original[runmode_index + 2:] 394 else: 395 temp_args = self.args_original 396 get_board = HdfGetHandler(temp_args) 397 temp_board_dict = json.loads(get_board.judge_create_driver_exist()) 398 if temp_board_dict: 399 temp_board_device_dict = temp_board_dict.get(board) 400 if temp_board_device_dict is not None and\ 401 temp_board_device_dict.get("driver_file_list") is not None: 402 driver_name_list = temp_board_device_dict.get("driver_file_list").get(device, []) 403 if driver_name_list and driver in driver_name_list: 404 raise HdfToolException( 405 'driver name %s exist in device %s' % 406 (driver, device), 407 CommandErrorCode.TARGET_ALREADY_EXIST) 408 framework_hdf = hdf_utils.get_vendor_hdf_dir_framework(root) 409 hdf_utils.judge_file_path_exists(framework_hdf) 410 framework_drv_root_dir = hdf_utils.get_module_dir(root, module) 411 hdf_utils.judge_file_path_exists(framework_drv_root_dir) 412 add_driver = HdfAddDriver(args=args_tuple) 413 # create driver Source File (.c 、.h) 414 resources_path, temp_file_name, config_item, file_path =\ 415 self._add_create_common(add_driver, args_tuple) 416 model_driver_file_path = os.path.join(resources_path, temp_file_name) 417 config_file = hdf_utils.read_file(model_driver_file_path) 418 config_file_json = json.loads(config_file) 419 result_config_file_json = add_driver.driver_create_info_format( 420 config_file_json, config_item, file_path) 421 hdf_utils.write_config(root_path=root, 422 config_file_json=result_config_file_json, 423 config_name=temp_file_name) 424 return json.dumps(config_item, indent=4) 425 426 def _add_create_common(self, add_driver, args_tuple): 427 _, _, module, driver, board, _, device = args_tuple 428 state, file_list, head_list = add_driver.add_driver(*args_tuple) 429 if board == "hispark_taurus": 430 file_path = add_driver.add_liteos(file_list, head_list) 431 elif board.endswith("linux"): 432 file_path = add_driver.add_linux(file_list, head_list) 433 elif board.startswith("rk3568_kernel"): 434 file_path = add_driver.add_kernel(file_list, head_list) 435 elif board.startswith("hispark_taurus_standard_kernel"): 436 file_path = add_driver.add_kernel(file_list, head_list) 437 438 config_item = { 439 'module_name': module, 440 'module_path': file_path, 441 'driver_name': "-".join([device, driver]), 442 'driver_file_path': file_list, 443 'head_file_path': head_list, 444 'enabled': "true" 445 } 446 resources_path = self.hdf_tool.get_resources_file_path() 447 config_setting_dict = self.hdf_tool.get_config_setting_info() 448 temp_file_name = config_setting_dict["create_driver_file"] 449 return resources_path, temp_file_name, config_item, file_path 450 451 def _add_config_handler(self): 452 self.check_arg_raise_if_not_exist("module_name") 453 self.check_arg_raise_if_not_exist("driver_name") 454 self.check_arg_raise_if_not_exist("board_name") 455 root, _, module, driver, board, kernel = self.get_args() 456 drv_config = HdfDriverConfigFile(root, board, module, driver, kernel) 457 drv_config.create_driver() 458 return drv_config.get_drv_config_path() 459 460 def revise_passwd_group_file(self, root_path, linux_file_path, model_name): 461 group_passwd = OperateGroupPasswd(tool_settings=self.hdf_tool, root_path=root_path) 462 # group 463 peripheral_name = "_".join([model_name, "user"]) 464 group_file_path = group_passwd.operate_group(name=peripheral_name) 465 # passwd 466 passwd_file_path = group_passwd.operate_passwd(name=peripheral_name) 467 linux_file_path["passwd"] = passwd_file_path 468 linux_file_path["group"] = group_file_path 469 return linux_file_path 470