1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2022 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 configparser 12import os 13import re 14from string import Template 15 16import hdf_utils 17from hdf_tool_exception import HdfToolException 18from .linux.kconfig_file_add_config import kconfig_file_operation 19from .linux.mk_file_add_config import audio_linux_makefile_operation, linux_makefile_operation 20 21from .liteos.gn_file_add_config import audio_build_file_operation, build_file_operation 22from .liteos.mk_file_add_config import audio_makefile_file_operation, makefile_file_operation 23from ..hdf_command_error_code import CommandErrorCode 24from ..hdf_defconfig_patch import HdfDefconfigAndPatch 25from ..hdf_device_info_hcs import HdfDeviceInfoHcsFile 26 27 28class HdfAddDriver(object): 29 def __init__(self, args): 30 super(HdfAddDriver, self).__init__() 31 self.root, self.vendor, self.module, self.driver, \ 32 self.board, self.kernel, self.device = args 33 self.template_file_path = hdf_utils.get_template_file_path(self.root) 34 if not os.path.exists(self.template_file_path): 35 raise HdfToolException( 36 'template file: %s not exist' % 37 self.template_file_path, CommandErrorCode.TARGET_NOT_EXIST) 38 39 def add_linux(self, driver_file_path, driver_head_path): 40 config_path_result = self.get_kernel_linux_config_path( 41 driver_file_path, driver_head_path) 42 config_path, file_path, defconfig_patch = config_path_result 43 pat_files = [] 44 patch_list = defconfig_patch.add_module( 45 config_path, files=pat_files, codetype=None) 46 config_path = defconfig_patch.get_config_patch() 47 def_files = [] 48 defconfig_list = defconfig_patch.add_module( 49 config_path, files=def_files, codetype=None) 50 file_path[self.module + "_dot_configs"] = \ 51 list(set(patch_list + defconfig_list)) 52 return file_path 53 54 def add_liteos(self, driver_file_path, driver_head_path): 55 adapter_hdf = hdf_utils.get_vendor_hdf_dir_adapter( 56 self.root, self.kernel) 57 hdf_utils.judge_file_path_exists(adapter_hdf) 58 59 adapter_model_path = os.path.join(adapter_hdf, 'model', self.module) 60 hdf_utils.judge_file_path_exists(adapter_model_path) 61 62 liteos_file_name = ['BUILD.gn', 'Makefile', 'Kconfig'] 63 file_path = {} 64 for file_name in liteos_file_name: 65 file_path = self._liteos_config_file_configure( 66 file_path, file_name, adapter_model_path, 67 driver_file_path, driver_head_path) 68 # Modify hcs file 69 device_info = HdfDeviceInfoHcsFile( 70 self.root, self.vendor, self.module, 71 self.board, self.driver, path="") 72 hcs_file_path = device_info.add_hcs_config_to_exists_model(self.device) 73 file_path["devices_info.hcs"] = hcs_file_path 74 75 dot_file_list = hdf_utils.get_dot_configs_path( 76 self.root, self.vendor, self.board) 77 template_string = "LOSCFG_DRIVERS_HDF_${module_upper}_${driver_upper}=y\n" 78 new_demo_config = Template(template_string).substitute( 79 {"module_upper": self.module.upper(), 80 "driver_upper": self.driver.upper()}) 81 82 device_enable = self.__get_enable_config() 83 for dot_file in dot_file_list: 84 file_lines_old = hdf_utils.read_file_lines(dot_file) 85 if device_enable: 86 file_lines = list( 87 filter( 88 lambda x: hdf_utils.judge_enable_line( 89 enable_line=x, 90 device_base=device_enable.split("=")[0]), 91 file_lines_old)) 92 if device_enable not in file_lines: 93 file_lines.append(device_enable) 94 else: 95 file_lines = file_lines_old 96 file_lines[-1] = "{}\n".format(file_lines[-1].strip()) 97 if new_demo_config not in file_lines: 98 file_lines.append(new_demo_config) 99 hdf_utils.write_file_lines(dot_file, file_lines) 100 file_path[self.module + "_dot_configs"] = dot_file_list 101 return file_path 102 103 def _liteos_config_file_configure(self, file_path, file_name, adapter_model_path, 104 driver_file_path, driver_head_path): 105 if file_name == "BUILD.gn": 106 build_file_path = os.path.join(adapter_model_path, file_name) 107 if self.module == "audio": 108 args_tuple = (driver_file_path, driver_head_path, self.module, 109 self.driver, self.root, self.device, self.kernel) 110 audio_build_file_operation(build_file_path, args_tuple) 111 else: 112 build_file_operation( 113 build_file_path, driver_file_path[0], driver_head_path[0], 114 self.module, self.driver) 115 file_path['BUILD.gn'] = build_file_path 116 117 elif file_name == "Makefile": 118 makefile_path = os.path.join(adapter_model_path, file_name) 119 if self.module == "audio": 120 args_tuple = (driver_file_path, driver_head_path, self.module, 121 self.driver, self.root, self.device, self.kernel) 122 audio_makefile_file_operation(makefile_path, args_tuple) 123 else: 124 makefile_file_operation( 125 makefile_path, driver_file_path[0], driver_head_path[0], 126 self.module, self.driver, self.root) 127 file_path['Makefile'] = makefile_path 128 129 elif file_name == "Kconfig": 130 kconfig_path = os.path.join(adapter_model_path, file_name) 131 kconfig_file_operation(kconfig_path, self.module, 132 self.driver, self.template_file_path) 133 file_path['Kconfig'] = kconfig_path 134 return file_path 135 136 def add_kernel(self, driver_file_path, driver_head_path): 137 config_path_result = self.get_kernel_linux_config_path( 138 driver_file_path, driver_head_path) 139 config_path, file_path, defconfig_patch = config_path_result 140 files = [] 141 patch_list = defconfig_patch.add_module( 142 config_path, files=files, codetype=None) 143 config_path = defconfig_patch.get_config_patch() 144 files1 = [] 145 defconfig_list = defconfig_patch.add_module( 146 config_path, files=files1, codetype=None) 147 file_path[self.module + "_dot_configs"] = \ 148 list(set(patch_list + defconfig_list)) 149 return file_path 150 151 def get_kernel_linux_config_path(self, driver_file_path, driver_head_path): 152 file_path = {} 153 file_path.update(self.linux_operation_config(driver_file_path, driver_head_path)) 154 155 device_info = HdfDeviceInfoHcsFile(self.root, self.vendor, 156 self.module, self.board, 157 self.driver, path="") 158 hcs_file_path = device_info.add_hcs_config_to_exists_model(self.device) 159 file_path["devices_info.hcs"] = hcs_file_path 160 device_enable_config_line = self.__get_enable_config() 161 template_string = "CONFIG_DRIVERS_HDF_${module_upper}_${driver_upper}=y\n" 162 data_model = { 163 "module_upper": self.module.upper(), 164 "driver_upper": self.driver.upper() 165 } 166 167 new_demo_config = Template(template_string).substitute(data_model) 168 if device_enable_config_line: 169 new_demo_config_list = [device_enable_config_line, new_demo_config] 170 else: 171 new_demo_config_list = [new_demo_config] 172 defconfig_patch = HdfDefconfigAndPatch( 173 self.root, self.vendor, self.kernel, self.board, 174 data_model, new_demo_config_list) 175 176 config_path = defconfig_patch.get_config_config() 177 return config_path, file_path, defconfig_patch 178 179 def driver_create_info_format(self, config_file_json, 180 config_item, file_path): 181 board_type = config_file_json.get(self.board) 182 if board_type is None: 183 config_file_json[self.board] = { 184 config_item.get("module_name"): { 185 'module_level_config': {}, 186 "driver_file_list": { 187 config_item.get("driver_name"): 188 config_item.get("driver_file_path") + 189 config_item.get("head_file_path") 190 } 191 } 192 } 193 config_file_json[self.board][self.module]["module_level_config"]\ 194 .update(file_path) 195 else: 196 model_type = board_type.get(config_item.get("module_name")) 197 if model_type is None: 198 temp = config_file_json.get(self.board) 199 temp_module = config_item.get("module_name") 200 temp[temp_module] = { 201 'module_level_config': {}, 202 "driver_file_list": { 203 config_item.get("driver_name"): 204 config_item.get("driver_file_path") + 205 config_item.get("head_file_path") 206 } 207 } 208 config_file_json.get(self.board).get(self.module).\ 209 get("module_level_config").update(file_path) 210 else: 211 temp = config_file_json.get(self.board).\ 212 get(config_item.get("module_name")).get("driver_file_list") 213 temp[config_item.get("driver_name")] = \ 214 config_item.get("driver_file_path") + \ 215 config_item.get("head_file_path") 216 return config_file_json 217 218 def add_driver(self, *args_tuple): 219 root, vendor, module, driver, board, kernel, device = args_tuple 220 drv_converter = hdf_utils.WordsConverter(driver) 221 dev_converter = hdf_utils.WordsConverter(device) 222 # create driver file path 223 source_file, head_path = self.create_model_file_name( 224 root, vendor, module, driver, board, kernel, device) 225 data_model = { 226 'driver_lower_case': drv_converter.lower_case(), 227 'driver_upper_camel_case': drv_converter.upper_camel_case(), 228 'driver_lower_camel_case': drv_converter.lower_camel_case(), 229 'driver_upper_case': drv_converter.upper_case(), 230 'device_lower_case': dev_converter.lower_case(), 231 'device_upper_camel_case': dev_converter.upper_camel_case(), 232 'device_lower_camel_case': dev_converter.lower_camel_case(), 233 'device_upper_case': dev_converter.upper_case() 234 } 235 templates_list, target_path = self.get_model_template_list(module, board) 236 source_file_list, source_statu_exist = self.get_template_source_file( 237 source_file, data_model, templates_list, target_path, args_tuple) 238 head_path_list, head_statu_exist = self.get_template_head_file( 239 head_path, data_model, templates_list, target_path, args_tuple) 240 if head_statu_exist and source_statu_exist: 241 return True, source_file_list, head_path_list 242 child_dir_list, operation_object = hdf_utils.ini_file_read_operation( 243 section_name=module, node_name='file_dir') 244 if device not in child_dir_list: 245 child_dir_list.append(device) 246 hdf_utils.ini_file_write_operation( 247 module, operation_object, child_dir_list) 248 return True, source_file_list, head_path_list 249 250 def get_template_source_file(self, source_file, data_model, 251 templates_list, target_path, *args_tuple): 252 # find model template .c 253 source_statu_exist = False 254 root, vendor, module, driver, board, kernel, device = args_tuple[0] 255 if module == "audio" or module == "display": 256 if board.startswith("rk3568"): 257 source_file_template_list = list( 258 filter(lambda file_name: "source" in file_name and 259 file_name.startswith("rk"), 260 templates_list)) 261 else: 262 source_file_template_list = list( 263 filter(lambda file_name: "source" in file_name and 264 file_name.startswith("hi"), 265 templates_list)) 266 else: 267 source_file_template_list = list(filter( 268 lambda file_name: "source" in file_name, templates_list)) 269 source_file_template = list( 270 map(lambda template_name: os.path.join(target_path, template_name), 271 source_file_template_list)) 272 path_list = list(os.path.split(source_file)) 273 temp_path = os.path.sep.join(path_list[:-1]) 274 if not os.path.exists(temp_path): 275 os.makedirs(temp_path) 276 277 source_file_list = [] 278 for source_file_temp in source_file_template: 279 if not os.path.exists(source_file): 280 os.makedirs(source_file) 281 create_name = re.search(r'[a-z]+_source', source_file_temp).group() 282 create_source_name = "%s_%s_%s.c" % (device, driver, create_name.split("_")[0]) 283 data_model.update({'include_file': "%s_%s_%s.h" % (device, driver, create_name.split("_")[0])}) 284 source_file_name = os.path.join(source_file, create_source_name) 285 if os.path.exists(source_file_name): 286 source_statu_exist = True 287 source_file_list.append(source_file_name) 288 else: 289 self._template_fill(source_file_temp, source_file_name, data_model) 290 source_file_list.append(source_file_name) 291 return source_file_list, source_statu_exist 292 293 def get_template_head_file(self, head_path, data_model, 294 templates_list, target_path, *args_tuple): 295 # find model template .h 296 head_statu_exist = False 297 root, vendor, module, driver, board, kernel, device = args_tuple[0] 298 if module == "audio": 299 if board.startswith("rk3568"): 300 head_file_template_list = list(filter( 301 lambda file_name: 302 ("head" in file_name and file_name.startswith("rk")), 303 templates_list)) 304 else: 305 head_file_template_list = list(filter( 306 lambda file_name: 307 ("head" in file_name and file_name.startswith("hi")), 308 templates_list)) 309 else: 310 head_file_template_list = list(filter( 311 lambda file_name: "head" in file_name, templates_list)) 312 head_file_template = list(map( 313 lambda template_name: os.path.join(target_path, template_name), 314 head_file_template_list)) 315 path_list = list(os.path.split(head_path)) 316 temp_path = os.path.sep.join(path_list[:-1]) 317 if not os.path.exists(temp_path): 318 os.makedirs(temp_path) 319 head_path_list = [] 320 for head_file_temp in head_file_template: 321 if not os.path.exists(head_path): 322 os.makedirs(head_path) 323 create_name = re.search(r'[a-z]+_head', head_file_temp).group() 324 create_head_name = "%s_%s_%s.h" % (device, driver, 325 create_name.split("_")[0]) 326 head_file_name = os.path.join(head_path, create_head_name) 327 if os.path.exists(head_file_name): 328 head_statu_exist = True 329 head_path_list.append(head_file_name) 330 else: 331 self._template_fill(head_file_temp, head_file_name, data_model) 332 head_path_list.append(head_file_name) 333 return head_path_list, head_statu_exist 334 335 def _file_gen_lite(self, template, source_file_path, model): 336 templates_dir = hdf_utils.get_templates_lite_dir() 337 template_path = os.path.join(templates_dir, template) 338 self._template_fill(template_path, source_file_path, model) 339 340 def _template_fill(self, template_path, output_path, data_model): 341 if not os.path.exists(template_path): 342 return 343 raw_content = hdf_utils.read_file(template_path) 344 contents = Template(raw_content).safe_substitute(data_model) 345 hdf_utils.write_file(output_path, contents) 346 347 def create_model_file_name(self, *args_tuple): 348 root, vendor, module, driver, board, kernel, device = args_tuple 349 drv_src_dir = hdf_utils.get_drv_src_dir(root, module) 350 if device.strip(): 351 if module == "sensor": 352 relatively_path, _ = hdf_utils.ini_file_read_operation( 353 section_name=module, node_name='driver_path') 354 new_mkdir_path = os.path.join(root, relatively_path, device) 355 elif module == "audio": 356 relatively_path_dict, _ = hdf_utils.ini_file_read_operation( 357 section_name=module, node_name='driver_path') 358 if board.startswith("rk3568"): 359 relatively_path = relatively_path_dict["rk3568"] 360 else: 361 relatively_path = relatively_path_dict["hi3516"] 362 new_mkdir_path = os.path.join( 363 root, relatively_path, device) 364 else: 365 new_mkdir_path = os.path.join(drv_src_dir, device) 366 367 if not os.path.exists(new_mkdir_path): 368 os.mkdir(new_mkdir_path) 369 if module == "sensor": 370 result_path_source = new_mkdir_path 371 result_path_head = new_mkdir_path 372 else: 373 result_path_source = os.path.join(new_mkdir_path, 'src') 374 result_path_head = os.path.join(new_mkdir_path, 'include') 375 else: 376 if module == "sensor": 377 new_mkdir_path = os.path.join(drv_src_dir, 'chipset', driver) 378 else: 379 new_mkdir_path = os.path.join(drv_src_dir, driver) 380 if not os.path.exists(new_mkdir_path): 381 os.mkdir(new_mkdir_path) 382 result_path_source = os.path.join( 383 new_mkdir_path, '%s_driver.c' % driver) 384 result_path_head = os.path.join( 385 new_mkdir_path, '%s_driver.h' % driver) 386 return result_path_source, result_path_head 387 388 def __get_enable_config(self): 389 device_enable_config = None 390 templates_dir = hdf_utils.get_templates_lite_dir() 391 templates_model_dir = [] 392 for path, dir_name, _ in os.walk(templates_dir): 393 if dir_name: 394 templates_model_dir.extend(dir_name) 395 templates_model_dir = list( 396 filter( 397 lambda model_dir: self.module in model_dir, 398 templates_model_dir)) 399 config_file = [ 400 name for name in os.listdir( 401 os.path.join( 402 templates_dir, 403 templates_model_dir[0])) if name.endswith("ini")] 404 if config_file: 405 config_path = os.path.join( 406 templates_dir, 407 templates_model_dir[0], 408 config_file[0]) 409 config = configparser.ConfigParser() 410 config.read(config_path) 411 section_list = config.options(section=self.kernel) 412 if self.device in section_list: 413 device_enable_config, _ = hdf_utils.ini_file_read_operation( 414 section_name=self.kernel, node_name=self.device, path=config_path) 415 else: 416 if self.kernel == "linux": 417 device_enable_config = [ 418 "CONFIG_DRIVERS_HDF_SENSOR_ACCEL=y\n"] 419 else: 420 device_enable_config = [ 421 "LOSCFG_DRIVERS_HDF_SENSOR_ACCEL=y\n"] 422 if device_enable_config: 423 return device_enable_config[0] 424 else: 425 return "" 426 427 def get_model_template_list(self, module, board): 428 templates_dir = hdf_utils.get_templates_lite_dir() 429 templates_model_dir = [] 430 for path, dir_name, _ in os.walk(templates_dir): 431 if dir_name: 432 templates_model_dir.extend(dir_name) 433 templates_model_dir = list(filter( 434 lambda model_dir: self.module in model_dir, 435 templates_model_dir)) 436 target_template_path = list(map( 437 lambda dir_name: os.path.join(templates_dir, dir_name), 438 templates_model_dir))[0] 439 templates_file_list = os.listdir(target_template_path) 440 if module == "audio" and board.startswith("hispark_taurus"): 441 templates_file_list = list(filter( 442 lambda x: x.startswith("hi35xx"), templates_file_list)) 443 return templates_file_list, target_template_path 444 445 def linux_operation_config(self, driver_file_path, driver_head_path): 446 adapter_hdf = hdf_utils.get_vendor_hdf_dir_adapter( 447 self.root, self.kernel) 448 hdf_utils.judge_file_path_exists(adapter_hdf) 449 450 adapter_model_path = os.path.join(adapter_hdf, 'model', self.module) 451 hdf_utils.judge_file_path_exists(adapter_model_path) 452 453 liteos_file_name = ['Makefile', 'Kconfig'] 454 file_path_temp = {} 455 for file_name in liteos_file_name: 456 if file_name == "Makefile": 457 linux_makefile_file_path = os.path.join(adapter_model_path, file_name) 458 if self.module == "audio": 459 args_tuple = (driver_file_path, driver_head_path, self.module, 460 self.driver, self.root, self.device) 461 audio_linux_makefile_operation(linux_makefile_file_path, args_tuple) 462 else: 463 linux_makefile_operation( 464 linux_makefile_file_path, driver_file_path[0], driver_head_path[0], 465 self.module, self.driver) 466 file_path_temp['Makefile'] = linux_makefile_file_path 467 468 elif file_name == "Kconfig": 469 kconfig_path = os.path.join(adapter_model_path, file_name) 470 kconfig_file_operation(kconfig_path, self.module, 471 self.driver, self.template_file_path) 472 file_path_temp['Kconfig'] = kconfig_path 473 return file_path_temp 474 475