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, input_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 elif self.module == "input": 112 input_build_file_operation( 113 build_file_path, driver_file_path[0], driver_head_path[0], 114 self.module, self.driver) 115 else: 116 build_file_operation( 117 build_file_path, driver_file_path[0], driver_head_path[0], 118 self.module, self.driver) 119 file_path['BUILD.gn'] = build_file_path 120 121 elif file_name == "Makefile": 122 makefile_path = os.path.join(adapter_model_path, file_name) 123 if self.module == "audio": 124 args_tuple = (driver_file_path, driver_head_path, self.module, 125 self.driver, self.root, self.device, self.kernel) 126 audio_makefile_file_operation(makefile_path, args_tuple) 127 else: 128 makefile_file_operation( 129 makefile_path, driver_file_path[0], driver_head_path[0], 130 self.module, self.driver, self.root) 131 file_path['Makefile'] = makefile_path 132 133 elif file_name == "Kconfig": 134 kconfig_path = os.path.join(adapter_model_path, file_name) 135 kconfig_file_operation(kconfig_path, self.module, 136 self.driver, self.template_file_path) 137 file_path['Kconfig'] = kconfig_path 138 return file_path 139 140 def add_kernel(self, driver_file_path, driver_head_path): 141 config_path_result = self.get_kernel_linux_config_path( 142 driver_file_path, driver_head_path) 143 config_path, file_path, defconfig_patch = config_path_result 144 files = [] 145 patch_list = defconfig_patch.add_module( 146 config_path, files=files, codetype=None) 147 config_path = defconfig_patch.get_config_patch() 148 files1 = [] 149 defconfig_list = defconfig_patch.add_module( 150 config_path, files=files1, codetype=None) 151 file_path[self.module + "_dot_configs"] = \ 152 list(set(patch_list + defconfig_list)) 153 return file_path 154 155 def get_kernel_linux_config_path(self, driver_file_path, driver_head_path): 156 file_path = {} 157 file_path.update(self.linux_operation_config(driver_file_path, driver_head_path)) 158 159 device_info = HdfDeviceInfoHcsFile(self.root, self.vendor, 160 self.module, self.board, 161 self.driver, path="") 162 hcs_file_path = device_info.add_hcs_config_to_exists_model(self.device) 163 file_path["devices_info.hcs"] = hcs_file_path 164 device_enable_config_line = self.__get_enable_config() 165 template_string = "CONFIG_DRIVERS_HDF_${module_upper}_${driver_upper}=y\n" 166 data_model = { 167 "module_upper": self.module.upper(), 168 "driver_upper": self.driver.upper() 169 } 170 171 new_demo_config = Template(template_string).substitute(data_model) 172 if device_enable_config_line: 173 new_demo_config_list = [device_enable_config_line, new_demo_config] 174 else: 175 new_demo_config_list = [new_demo_config] 176 defconfig_patch = HdfDefconfigAndPatch( 177 self.root, self.vendor, self.kernel, self.board, 178 data_model, new_demo_config_list) 179 180 config_path = defconfig_patch.get_config_config() 181 return config_path, file_path, defconfig_patch 182 183 def driver_create_info_format(self, config_file_json, 184 config_item, file_path): 185 board_type = config_file_json.get(self.board) 186 if board_type is None: 187 config_file_json[self.board] = { 188 config_item.get("module_name"): { 189 'module_level_config': {}, 190 "driver_file_list": { 191 config_item.get("driver_name"): 192 config_item.get("driver_file_path") + 193 config_item.get("head_file_path") 194 } 195 } 196 } 197 config_file_json[self.board][self.module]["module_level_config"]\ 198 .update(file_path) 199 else: 200 model_type = board_type.get(config_item.get("module_name")) 201 if model_type is None: 202 temp = config_file_json.get(self.board) 203 temp_module = config_item.get("module_name") 204 temp[temp_module] = { 205 'module_level_config': {}, 206 "driver_file_list": { 207 config_item.get("driver_name"): 208 config_item.get("driver_file_path") + 209 config_item.get("head_file_path") 210 } 211 } 212 config_file_json.get(self.board).get(self.module).\ 213 get("module_level_config").update(file_path) 214 else: 215 temp = config_file_json.get(self.board).\ 216 get(config_item.get("module_name")).get("driver_file_list") 217 temp[config_item.get("driver_name")] = \ 218 config_item.get("driver_file_path") + \ 219 config_item.get("head_file_path") 220 return config_file_json 221 222 def add_driver(self, *args_tuple): 223 root, vendor, module, driver, board, kernel, device = args_tuple 224 drv_converter = hdf_utils.WordsConverter(driver) 225 dev_converter = hdf_utils.WordsConverter(device) 226 # create driver file path 227 source_file, head_path = self.create_model_file_name( 228 root, vendor, module, driver, board, kernel, device) 229 data_model = { 230 'driver_lower_case': drv_converter.lower_case(), 231 'driver_upper_camel_case': drv_converter.upper_camel_case(), 232 'driver_lower_camel_case': drv_converter.lower_camel_case(), 233 'driver_upper_case': drv_converter.upper_case(), 234 'device_lower_case': dev_converter.lower_case(), 235 'device_upper_camel_case': dev_converter.upper_camel_case(), 236 'device_lower_camel_case': dev_converter.lower_camel_case(), 237 'device_upper_case': dev_converter.upper_case() 238 } 239 templates_list, target_path = self.get_model_template_list(module, board) 240 source_file_list, source_statu_exist = self.get_template_source_file( 241 source_file, data_model, templates_list, target_path, args_tuple) 242 head_path_list, head_statu_exist = self.get_template_head_file( 243 head_path, data_model, templates_list, target_path, args_tuple) 244 if head_statu_exist and source_statu_exist: 245 return True, source_file_list, head_path_list 246 child_dir_list, operation_object = hdf_utils.ini_file_read_operation( 247 section_name=module, node_name='file_dir') 248 if device not in child_dir_list: 249 child_dir_list.append(device) 250 hdf_utils.ini_file_write_operation( 251 module, operation_object, child_dir_list) 252 return True, source_file_list, head_path_list 253 254 def get_template_source_file(self, source_file, data_model, 255 templates_list, target_path, *args_tuple): 256 # find model template .c 257 source_statu_exist = False 258 root, vendor, module, driver, board, kernel, device = args_tuple[0] 259 if module == "audio" or module == "display": 260 if board.startswith("rk3568"): 261 source_file_template_list = \ 262 list(filter( 263 lambda file_name: "source" in file_name and 264 file_name.startswith("rk"), 265 templates_list)) 266 else: 267 source_file_template_list = \ 268 list(filter( 269 lambda file_name: "source" in file_name and 270 file_name.startswith("hi"), 271 templates_list)) 272 elif module == "sensor": 273 source_file_template_list = self._sensor_source_head("source", templates_list) 274 else: 275 source_file_template_list = \ 276 list(filter( 277 lambda file_name: "source" in file_name, 278 templates_list)) 279 source_file_template = \ 280 list(map( 281 lambda template_name: os.path.join(target_path, template_name), 282 source_file_template_list)) 283 path_list = list(os.path.split(source_file)) 284 temp_path = os.path.sep.join(path_list[:-1]) 285 if not os.path.exists(temp_path): 286 os.makedirs(temp_path) 287 288 source_file_list = [] 289 for source_file_temp in source_file_template: 290 if not os.path.exists(source_file): 291 os.makedirs(source_file) 292 create_name = re.search(r'[a-z]+_source', source_file_temp).group() 293 create_source_name = "%s_%s_%s.c" % (device, driver, create_name.split("_")[0]) 294 data_model.update({'include_file': "%s_%s_%s.h" % (device, driver, create_name.split("_")[0])}) 295 source_file_name = os.path.join(source_file, create_source_name) 296 if os.path.exists(source_file_name): 297 source_statu_exist = True 298 source_file_list.append(source_file_name) 299 else: 300 self._template_fill(source_file_temp, source_file_name, data_model) 301 source_file_list.append(source_file_name) 302 return source_file_list, source_statu_exist 303 304 def get_template_head_file( 305 self, head_path, data_model, templates_list, target_path, *args_tuple): 306 # find model template .h 307 head_statu_exist = False 308 root, vendor, module, driver, board, kernel, device = args_tuple[0] 309 if module == "audio": 310 if board.startswith("rk3568"): 311 head_file_template_list = list(filter( 312 lambda file_name: 313 ("head" in file_name and file_name.startswith("rk")), 314 templates_list)) 315 else: 316 head_file_template_list = list(filter( 317 lambda file_name: 318 ("head" in file_name and file_name.startswith("hi")), 319 templates_list)) 320 elif module == "sensor": 321 head_file_template_list = self._sensor_source_head("head", templates_list) 322 else: 323 head_file_template_list = list(filter( 324 lambda file_name: "head" in file_name, templates_list)) 325 head_file_template = list(map( 326 lambda template_name: os.path.join(target_path, template_name), 327 head_file_template_list)) 328 path_list = list(os.path.split(head_path)) 329 temp_path = os.path.sep.join(path_list[:-1]) 330 if not os.path.exists(temp_path): 331 os.makedirs(temp_path) 332 head_path_list = [] 333 for head_file_temp in head_file_template: 334 if not os.path.exists(head_path): 335 os.makedirs(head_path) 336 create_name = re.search(r'[a-z]+_head', head_file_temp).group() 337 create_head_name = "%s_%s_%s.h" % (device, driver, 338 create_name.split("_")[0]) 339 head_file_name = os.path.join(head_path, create_head_name) 340 if os.path.exists(head_file_name): 341 head_statu_exist = True 342 head_path_list.append(head_file_name) 343 else: 344 self._template_fill(head_file_temp, head_file_name, data_model) 345 head_path_list.append(head_file_name) 346 return head_path_list, head_statu_exist 347 348 def _sensor_source_head(self, file_type, templates_list): 349 kernel_base_device = f"{self.kernel}_base_device" 350 base_device_list, _ = hdf_utils.ini_file_read_operation( 351 section_name=self.module, node_name=kernel_base_device) 352 if file_type == "head": 353 if self.device == "als" or self.device == "hall" or self.device == "ppg": 354 head_file_template_list = \ 355 list(filter( 356 lambda file_name: "head" in file_name and 357 file_name.startswith(self.device), 358 templates_list)) 359 elif self.device in base_device_list: 360 head_file_template_list = \ 361 list(filter( 362 lambda file_name: "head" in file_name and 363 file_name.startswith("accel"), 364 templates_list)) 365 else: 366 head_file_template_list = \ 367 list(filter( 368 lambda file_name: "head" in file_name and 369 file_name.startswith("com"), 370 templates_list)) 371 return head_file_template_list 372 else: 373 if self.device == "als" or self.device == "hall" or self.device == "ppg": 374 source_file_template_list = \ 375 list(filter( 376 lambda file_name: "source" in file_name and 377 file_name.startswith(self.device), 378 templates_list)) 379 elif self.device in base_device_list: 380 source_file_template_list = \ 381 list(filter( 382 lambda file_name: "source" in file_name and 383 file_name.startswith("accel"), 384 templates_list)) 385 else: 386 source_file_template_list = \ 387 list(filter( 388 lambda file_name: "source" in file_name and 389 file_name.startswith("com"), 390 templates_list)) 391 return source_file_template_list 392 393 def _file_gen_lite(self, template, source_file_path, model): 394 templates_dir = hdf_utils.get_templates_lite_dir() 395 template_path = os.path.join(templates_dir, template) 396 self._template_fill(template_path, source_file_path, model) 397 398 def _template_fill(self, template_path, output_path, data_model): 399 if not os.path.exists(template_path): 400 return 401 raw_content = hdf_utils.read_file(template_path) 402 contents = Template(raw_content).safe_substitute(data_model) 403 hdf_utils.write_file(output_path, contents) 404 405 def create_model_file_name(self, *args_tuple): 406 root, vendor, module, driver, board, kernel, device = args_tuple 407 drv_src_dir = hdf_utils.get_drv_src_dir(root, module) 408 if device.strip(): 409 if module == "sensor": 410 relatively_path, _ = hdf_utils.ini_file_read_operation( 411 section_name=module, node_name='driver_path') 412 new_mkdir_path = os.path.join(root, relatively_path, device) 413 elif module == "audio": 414 relatively_path_dict, _ = hdf_utils.ini_file_read_operation( 415 section_name=module, node_name='driver_path') 416 if board.startswith("rk3568"): 417 relatively_path = relatively_path_dict["rk3568"] 418 else: 419 relatively_path = relatively_path_dict["hi3516"] 420 new_mkdir_path = os.path.join( 421 root, relatively_path, device) 422 else: 423 new_mkdir_path = os.path.join(drv_src_dir, device) 424 425 if not os.path.exists(new_mkdir_path): 426 os.mkdir(new_mkdir_path) 427 if module == "sensor": 428 result_path_source = new_mkdir_path 429 result_path_head = new_mkdir_path 430 else: 431 result_path_source = os.path.join(new_mkdir_path, 'src') 432 result_path_head = os.path.join(new_mkdir_path, 'include') 433 else: 434 if module == "sensor": 435 new_mkdir_path = os.path.join(drv_src_dir, 'chipset', driver) 436 else: 437 new_mkdir_path = os.path.join(drv_src_dir, driver) 438 if not os.path.exists(new_mkdir_path): 439 os.mkdir(new_mkdir_path) 440 result_path_source = os.path.join( 441 new_mkdir_path, '%s_driver.c' % driver) 442 result_path_head = os.path.join( 443 new_mkdir_path, '%s_driver.h' % driver) 444 return result_path_source, result_path_head 445 446 def __get_enable_config(self): 447 device_enable_config = None 448 templates_dir = hdf_utils.get_templates_lite_dir() 449 templates_model_dir = [] 450 for path, dir_name, _ in os.walk(templates_dir): 451 if dir_name: 452 templates_model_dir.extend(dir_name) 453 templates_model_dir = list( 454 filter( 455 lambda model_dir: self.module in model_dir, 456 templates_model_dir)) 457 config_file = [ 458 name for name in os.listdir( 459 os.path.join( 460 templates_dir, 461 templates_model_dir[0])) if name.endswith("ini")] 462 if config_file: 463 config_path = os.path.join( 464 templates_dir, 465 templates_model_dir[0], 466 config_file[0]) 467 config = configparser.ConfigParser() 468 config.read(config_path) 469 section_list = config.options(section=self.kernel) 470 if self.device in section_list: 471 device_enable_config, _ = hdf_utils.ini_file_read_operation( 472 section_name=self.kernel, 473 node_name=self.device, path=config_path) 474 else: 475 if self.kernel == "linux": 476 device_enable_config = [ 477 "CONFIG_DRIVERS_HDF_SENSOR_ACCEL=y\n"] 478 else: 479 device_enable_config = [ 480 "LOSCFG_DRIVERS_HDF_SENSOR_ACCEL=y\n"] 481 482 if device_enable_config: 483 return device_enable_config[0] 484 else: 485 return "" 486 487 def get_model_template_list(self, module, board): 488 templates_dir = hdf_utils.get_templates_lite_dir() 489 templates_model_dir = [] 490 for path, dir_name, _ in os.walk(templates_dir): 491 if dir_name: 492 templates_model_dir.extend(dir_name) 493 templates_model_dir = list(filter( 494 lambda model_dir: self.module in model_dir, 495 templates_model_dir)) 496 target_template_path = list(map( 497 lambda dir_name: os.path.join(templates_dir, dir_name), 498 templates_model_dir))[0] 499 templates_file_list = os.listdir(target_template_path) 500 if module == "audio" and board.startswith("hispark_taurus"): 501 templates_file_list = list(filter( 502 lambda x: x.startswith("hi35xx"), templates_file_list)) 503 return templates_file_list, target_template_path 504 505 def linux_operation_config(self, driver_file_path, driver_head_path): 506 adapter_hdf = hdf_utils.get_vendor_hdf_dir_adapter( 507 self.root, self.kernel) 508 hdf_utils.judge_file_path_exists(adapter_hdf) 509 510 adapter_model_path = os.path.join(adapter_hdf, 'model', self.module) 511 hdf_utils.judge_file_path_exists(adapter_model_path) 512 513 liteos_file_name = ['Makefile', 'Kconfig'] 514 file_path_temp = {} 515 for file_name in liteos_file_name: 516 if file_name == "Makefile": 517 linux_makefile_file_path = os.path.join(adapter_model_path, file_name) 518 if self.module == "audio": 519 args_tuple = (driver_file_path, driver_head_path, self.module, 520 self.driver, self.root, self.device, self.board) 521 linux_makefile_file_path = audio_linux_makefile_operation( 522 linux_makefile_file_path, args_tuple) 523 else: 524 linux_makefile_operation( 525 linux_makefile_file_path, driver_file_path[0], driver_head_path[0], 526 self.module, self.driver) 527 file_path_temp['Makefile'] = linux_makefile_file_path 528 529 elif file_name == "Kconfig": 530 kconfig_path = os.path.join(adapter_model_path, file_name) 531 kconfig_file_operation(kconfig_path, self.module, 532 self.driver, self.template_file_path) 533 file_path_temp['Kconfig'] = kconfig_path 534 return file_path_temp 535 536