• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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