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 os
12import re
13from string import Template
14
15import hdf_utils
16from hdf_tool_exception import HdfToolException
17from hdf_tool_settings import HdfToolSettings
18from .hdf_command_error_code import CommandErrorCode
19
20
21class HdfDeviceInfoHcsFile(object):
22    def __init__(self, root, vendor, module, board, driver, path):
23        self.model_space_num = " " * 8
24        self.driver_space_num = " " * 12
25        if not path:
26            self.module = module
27            self.vendor = vendor
28            self.board = board
29            self.root = root
30            self.driver = driver
31            self.lines = None
32            board_hcs_temp = HdfToolSettings().get_board_parent_path(self.board)
33            board_hcs_path = board_hcs_temp.format(vendor=vendor, board=board)
34            self.hcspath = os.path.join(self.root, board_hcs_path, "device_info.hcs")
35            self.data = {
36                "driver_name": self.driver,
37                "model_name": self.module,
38                "module_upper_case": self.module.upper(),
39                "driver_upper_case": self.driver.upper(),
40                "module_name": "_".join([self.module, self.driver]).upper()
41            }
42        else:
43            self.hcspath = path
44            self.root = root
45        self.file_path = hdf_utils.get_template_file_path(root)
46        if not os.path.exists(self.file_path):
47            raise HdfToolException(
48                'template file: %s not exist' %
49                self.file_path, CommandErrorCode.TARGET_NOT_EXIST)
50        if not os.path.exists(self.hcspath):
51            raise HdfToolException(
52                'hcs file: %s not exist' %
53                self.hcspath, CommandErrorCode.TARGET_NOT_EXIST)
54
55    def _save(self):
56        if self.lines:
57            config_info = HdfToolSettings().get_file_config_info()
58            write_fd = os.open(self.hcspath, config_info["flags"], config_info["modes"])
59            with os.fdopen(write_fd, "w+", encoding="utf-8") as lwrite:
60                for line in self.lines:
61                    lwrite.write(line)
62
63    def delete_driver(self, module, temp_flag="host"):
64        hcs_config = hdf_utils.read_file_lines(self.hcspath)
65        index_info = {}
66        count = 0
67        for index, line in enumerate(hcs_config):
68            if line.find("%s :: %s" % (module, temp_flag)) == -1:
69                continue
70            index_info["start_index"] = index
71            for child_index in range(
72                    index_info.get("start_index"), len(hcs_config)):
73                if hcs_config[child_index].strip().find("{") != -1:
74                    count += 1
75                elif hcs_config[child_index].strip() == "}":
76                    count -= 1
77                if count == 0:
78                    index_info["end_index"] = child_index
79                    break
80            break
81        if index_info:
82            self.lines = hcs_config[0:index_info.get("start_index")] \
83                         + hcs_config[index_info.get("end_index") + 1:]
84            self._save()
85            return True
86
87    def add_model_hcs_file_config(self):
88        template_file_path = os.path.join(
89            self.file_path, 'device_info_hcs.template')
90        return self.add_model_hcs_config_common(template_file_path)
91
92    def add_model_hcs_file_config_user(self):
93        template_file_path = os.path.join(
94            self.file_path, 'User_device_info_hcs.template')
95        return self.add_model_hcs_config_common(template_file_path)
96
97    def add_model_hcs_config_common(self, template_file_path):
98        temp_lines = list(map(
99            lambda x: self.model_space_num + x,
100            hdf_utils.read_file_lines(template_file_path)))
101
102        old_lines = list(filter(
103            lambda x: x != "\n",
104            hdf_utils.read_file_lines(self.hcspath)))
105
106        for index, _ in enumerate(temp_lines):
107            temp_lines[index] = Template(
108                temp_lines[index]).substitute(self.data)
109        if temp_lines[0] not in old_lines:
110            new_data = old_lines[:-2] + temp_lines + old_lines[-2:]
111            self.lines = new_data
112            self._save()
113        return self.hcspath
114
115    def add_hcs_config_to_exists_model(self, device):
116        template_path = os.path.join(
117            self.file_path, 'exists_model_hcs_info.template')
118        lines = list(map(
119            lambda x: self.driver_space_num + x,
120            hdf_utils.read_file_lines(template_path)))
121
122        old_lines = list(filter(
123            lambda x: x != "\n",
124            hdf_utils.read_file_lines(self.hcspath)))
125
126        if self.judge_module_branch_exists(date_lines=old_lines):
127            return self.hcspath
128        end_index, start_index = self._get_model_index(old_lines)
129        model_hcs_lines = old_lines[start_index:end_index]
130        hcs_judge = self.judge_driver_hcs_exists(date_lines=model_hcs_lines)
131        if hcs_judge:
132            return self.hcspath
133        temp_replace_dict = {
134            "device_upper_case": device.upper()
135        }
136        self.data.update(temp_replace_dict)
137        for index, _ in enumerate(lines):
138            lines[index] = Template(lines[index]).substitute(self.data)
139        self.lines = old_lines[:end_index] + lines + old_lines[end_index:]
140        self._save()
141        return self.hcspath
142
143    def _get_model_index(self, old_lines):
144        model_start_index = 0
145        model_end_index = 0
146        start_state = False
147        count = 0
148        for index, old_line in enumerate(old_lines):
149            if old_line.strip().startswith(self.module) and start_state == False:
150                model_start_index = index
151                start_state = True
152            if start_state and old_line.find("{") != -1:
153                count += 1
154            elif start_state and old_line.find("}") != -1:
155                count -= 1
156                if count != 0:
157                    continue
158                start_state = False
159                model_end_index = index
160        return model_end_index, model_start_index
161
162    def judge_driver_hcs_exists(self, date_lines):
163        for _, line in enumerate(date_lines):
164            if line.startswith("#"):
165                continue
166            elif line.find(self.driver) != -1:
167                return True
168        return False
169
170    def judge_module_branch_exists(self, date_lines):
171        module_branch_start = "%s :: host" % self.module
172        for _, line in enumerate(date_lines):
173            if line.startswith("#"):
174                continue
175            elif line.strip().find(module_branch_start) != -1:
176                return False
177        return True
178
179    @staticmethod
180    def hdi_hcs_delete(file_path, driver_name):
181        hcs_config = hdf_utils.read_file_lines(file_path)
182        index_info = {}
183        count = 0
184        for index, line in enumerate(hcs_config):
185            if line.find("%s_dal :: %s" % (driver_name, "host")) == -1:
186                continue
187            index_info["start_index"] = index
188            for child_index in range(
189                    index_info.get("start_index"), len(hcs_config)):
190                if hcs_config[child_index].strip().find("{") != -1:
191                    count += 1
192                elif hcs_config[child_index].strip() == "}":
193                    count -= 1
194                if count == 0:
195                    index_info["end_index"] = child_index
196                    break
197            break
198        if index_info:
199            temp_lines = hcs_config[0:index_info.get("start_index")] \
200                         + hcs_config[index_info.get("end_index") + 1:]
201            hdf_utils.write_file_lines(file_path, temp_lines)
202