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 json
13from ast import literal_eval
14
15import hdf_utils
16import hdf_tool_version
17from hdf_tool_settings import HdfToolSettings
18from hdf_tool_exception import HdfToolException
19from hdf_tool_version import GetToolVersion
20from .hdf_command_handler_base import HdfCommandHandlerBase
21from .hdf_linux_scann import HdfLinuxScan
22from .hdf_lite_mk_file import HdfLiteMkFile
23from .hdf_liteos_scann import HdfLiteScan
24from .hdf_vendor_kconfig_file import HdfVendorKconfigFile
25from .hdf_module_kconfig_file import HdfModuleKconfigFile
26from .hdf_driver_config_file import HdfDriverConfigFile
27from .hdf_command_error_code import CommandErrorCode
28
29
30class HdfGetHandler(HdfCommandHandlerBase):
31    def __init__(self, args):
32        super(HdfGetHandler, self).__init__()
33        self.cmd = 'get'
34        self.handlers = {
35            'vendor_list': self._get_vendor_list_handler,
36            'current_vendor': self._get_current_vendor_handler,
37            'vendor_parent_path': self._get_vendor_parent_path_handler,
38            'individual_vendor_path': self._get_individual_vendor_path_handler,
39            'board_list': self._get_board_list_handler,
40            'driver_list': self._get_driver_list_handler,
41            'driver_file': self._get_driver_file_handler,
42            'drv_config_file': self._get_drv_config_file_handler,
43            'hdf_tool_core_version': self._get_version_handler,
44            'model_device_list': self._get_model_device_list,
45            'model_driver_list': self._get_device_driver_list,
46            'model_list': self._get_model_dict,
47            'model_scan': self._mode_scan,
48            'version': self._get_version,
49        }
50        self.parser.add_argument("--action_type",
51                                 help=' '.join(self.handlers.keys()),
52                                 required=True)
53        self.parser.add_argument("--root_dir")
54        self.parser.add_argument("--vendor_name")
55        self.parser.add_argument("--module_name")
56        self.parser.add_argument("--driver_name")
57        self.parser.add_argument("--kernel_name")
58        self.parser.add_argument("--board_name")
59        self.parser.add_argument("--device_name")
60        self.args = self.parser.parse_args(args)
61
62    def _get_vendor_list_handler(self):
63        self.check_arg_raise_if_not_exist("root_dir")
64        root = self.args.root_dir
65        vendor_root_dir = hdf_utils.get_vendor_root_dir(root)
66        vendors = []
67        if os.path.exists(vendor_root_dir):
68            for vendor in os.listdir(vendor_root_dir):
69                hdf = hdf_utils.get_vendor_hdf_dir(root, vendor)
70                if os.path.exists(hdf):
71                    vendors.append(vendor)
72        return ','.join(vendors)
73
74    def _get_current_vendor_handler(self):
75        self.check_arg_raise_if_not_exist("root_dir")
76        return HdfLiteMkFile(self.args.root_dir).get_current_vendor()
77
78    @staticmethod
79    def _get_board_list_handler():
80        settings = HdfToolSettings()
81        return settings.get_supported_boards()
82
83    def _get_vendor_parent_path_handler(self):
84        self.check_arg_raise_if_not_exist("root_dir")
85        target = hdf_utils.get_vendor_root_dir(self.args.root_dir)
86        return os.path.realpath(target)
87
88    def _get_individual_vendor_path_handler(self):
89        self.check_arg_raise_if_not_exist("root_dir")
90        self.check_arg_raise_if_not_exist("vendor_name")
91        root, vendor, _, _, _ = self.get_args()
92        target = hdf_utils.get_vendor_dir(root, vendor)
93        return os.path.realpath(target)
94
95    @staticmethod
96    def _get_version_handler():
97        return hdf_tool_version.get_version()
98
99    def _get_driver_list_handler(self):
100        self.check_arg_raise_if_not_exist("root_dir")
101        self.check_arg_raise_if_not_exist("vendor_name")
102        root, vendor, _, _, _ = self.get_args()
103        hdf_dir = hdf_utils.get_vendor_hdf_dir(root, vendor)
104        if not os.path.exists(hdf_dir):
105            raise HdfToolException('vendor "%s" not exist' % vendor,
106                                   CommandErrorCode.TARGET_NOT_EXIST)
107        modules = os.listdir(hdf_dir)
108        vendor_k = HdfVendorKconfigFile(root, vendor, kernel=None, path='')
109        module_items = vendor_k.get_module_and_config_path()
110        drivers = {}
111        for item in module_items:
112            module, k_path = item
113            if module in modules:
114                models = \
115                    HdfModuleKconfigFile(root, module,
116                                         k_path).get_models()
117                drivers[module] = models
118        return json.dumps(drivers)
119
120    def _get_driver_file_handler(self):
121        self.check_arg_raise_if_not_exist("root_dir")
122        self.check_arg_raise_if_not_exist("vendor_name")
123        self.check_arg_raise_if_not_exist("module_name")
124        self.check_arg_raise_if_not_exist("driver_name")
125        root = os.path.realpath(self.args.root_dir)
126        _, vendor, module, driver, _ = self.get_args()
127        drv_dir = hdf_utils.get_drv_dir(root, vendor, module, driver)
128        if not os.path.exists(drv_dir):
129            raise HdfToolException(
130                'driver directory: %s not exist' %
131                drv_dir, CommandErrorCode.TARGET_NOT_EXIST)
132        for root_path, dirs, files in os.walk(drv_dir):
133            for file_name in files:
134                if file_name.endswith('.c'):
135                    return os.path.realpath(os.path.join(root_path, file_name))
136        return ''
137
138    def _get_drv_config_file_handler(self):
139        self.check_arg_raise_if_not_exist("root_dir")
140        self.check_arg_raise_if_not_exist("module_name")
141        self.check_arg_raise_if_not_exist("driver_name")
142        self.check_arg_raise_if_not_exist("board_name")
143        root, _, module, driver, board = self.get_args()
144        drv_config = HdfDriverConfigFile(root, board, module, driver, True)
145        return drv_config.get_drv_config_path()
146
147    def _get_model_dict(self):
148        self.check_arg_raise_if_not_exist("root_dir")
149        root, _, _, _, _, _, _ = self.get_args()
150        create_model_file_save_path = hdf_utils.module_save_file_info(root)
151        out_model_list = []
152        data = hdf_utils.read_file(create_model_file_save_path)
153        json_type = json.loads(data)
154        if not json_type:
155            return out_model_list
156        file_key_list = list(list(json_type.items())[0][-1].keys())
157        for k, _ in json_type.items():
158            model_file_path = {}
159            for key in file_key_list:
160                if key.split("_")[-1] == "path":
161                    path_dict = json_type[k][key]
162                    model_file_path = hdf_utils.model_info(
163                        path_dict, root, model_file_path, key)
164            out_model_list.append({k: model_file_path})
165        return json.dumps(out_model_list, indent=4)
166
167    def _get_version(self):
168        version_end = "\nCopyright (c) 2020-2021 Huawei Device Co., Ltd."
169        version_head = "hdf_dev_eco_tool version : "
170        return version_head + GetToolVersion().get_version() + version_end
171
172    def _mode_scan(self):
173        self.check_arg_raise_if_not_exist("root_dir")
174        self.check_arg_raise_if_not_exist("vendor_name")
175        self.check_arg_raise_if_not_exist("board_name")
176        root, vendor, _, _, board, _, _ = self.get_args()
177        if board.split("_")[-1] != "linux":
178            return HdfLiteScan(
179                root=root, vendor=vendor, board=board).get_model_scan()
180        else:
181            return HdfLinuxScan(
182                root=root, vendor=vendor, board=board).get_model_scan()
183
184    def _get_model_device_base(self):
185        self.check_arg_raise_if_not_exist("module_name")
186        model_device_file_path = ""
187        resources_path = HdfToolSettings().get_resources_file_path()
188        for file_name in os.listdir(resources_path):
189            if file_name.endswith("ini"):
190                model_device_file_path = os.path.join(resources_path, file_name)
191                break
192        return model_device_file_path
193
194    def _get_model_device_list(self):
195        model_device_file_path = self._get_model_device_base()
196        if not model_device_file_path:
197            raise HdfToolException(
198                "%s: config file not exit" % CommandErrorCode.TARGET_NOT_EXIST)
199        device_list, _ = hdf_utils.ini_file_read_operation(
200            path=model_device_file_path, section_name=self.args.module_name,
201            node_name="file_dir")
202        return json.dumps(device_list)
203
204    def delete_device_operation(self, device_name, *section):
205        ini_config_handle, temp_value_type, temp_device_list = section
206        device_path = ""
207        if isinstance(temp_value_type, str):
208            device_path = temp_value_type
209        if isinstance(temp_value_type, dict):
210            if self.args.board_name == "rk3568":
211                device_path = temp_value_type.get('rk3568')
212            else:
213                device_path = temp_value_type.get('hi3516')
214        temp_device_path = os.path.join(self.args.root_dir, device_path, device_name)
215        if not os.path.exists(temp_device_path):
216            temp_device_list.remove(device_name)
217            hdf_utils.ini_file_write_operation(
218                self.args.module_name, ini_config_handle, temp_device_list)
219
220    def judgement_device_in_model(self, device_name):
221        model_device_file_path = self._get_model_device_base()
222        if not model_device_file_path:
223            raise HdfToolException(
224                "%s: config file not exit" % CommandErrorCode.TARGET_NOT_EXIST)
225        device_list, ini_config_handle = hdf_utils.ini_file_read_operation(
226            path=model_device_file_path, section_name=self.args.module_name,
227            node_name="")
228        section_info = hdf_utils.list_dict_tool(device_list)
229        temp_value_type = literal_eval(section_info.get("driver_path"))
230        temp_device_list = literal_eval(section_info.get("file_dir"))
231        if device_name not in temp_device_list:
232            raise HdfToolException(
233                "%s device not in the %s module" % (device_name, self.args.module_name))
234        return ini_config_handle, temp_value_type, temp_device_list
235
236    def _get_crate_model_driver_info(self):
237        self.check_arg_raise_if_not_exist("module_name")
238        resources_path = HdfToolSettings().get_resources_file_path()
239        config_setting_dict = HdfToolSettings().get_config_setting_info()
240        temp_file_name = config_setting_dict["create_driver_file"]
241        model_driver_file_path = os.path.join(resources_path, temp_file_name)
242        hdf_utils.judge_file_path_exists(model_driver_file_path)
243        model_driver_info = hdf_utils.read_file(model_driver_file_path)
244        model_driver_json = json.loads(model_driver_info)
245        return model_driver_json, model_driver_file_path
246
247    def _get_model_driver_list(self):
248        model_driver_json, _ = self._get_crate_model_driver_info()
249        board_list = list(model_driver_json.keys())
250        res_format_json = {}
251        for board_name in board_list:
252            board_info = model_driver_json.get(board_name)
253            if board_info and board_info.get(self.args.module_name):
254                res_format_json[board_name] = board_info.get(
255                    self.args.module_name)
256        self.format_model_driver_res(res_format_json)
257        return json.dumps(res_format_json, indent=4)
258
259    def _get_device_driver_list(self):
260        temp_res = json.loads(self._get_model_driver_list())
261        board_list = list(temp_res.keys())
262        res_dict = {}
263        for board_name in board_list:
264            res_dict[board_name] = {
265                "module_level_config": temp_res.get(
266                    board_name).get("module_level_config"),
267                "driver_file_list": {}
268            }
269            board_info = temp_res.get(board_name).get("driver_file_list")
270            for driver_name, value_info in board_info.items():
271                device_driver_name_list = driver_name.split("-")
272                temp_device_name = device_driver_name_list[0]
273                temp_driver_name = device_driver_name_list[-1]
274                temp_device = res_dict.get(board_name).get(
275                    "driver_file_list").get(temp_device_name)
276                if temp_device:
277                    temp_device[temp_driver_name] = value_info
278                else:
279                    res_dict.get(board_name).get("driver_file_list")[temp_device_name] = {
280                        temp_driver_name: value_info
281                    }
282        return json.dumps(res_dict, indent=4)
283
284    def judge_create_driver_exist(self):
285        return self._get_device_driver_list()
286
287    def format_model_driver_res(self, temp_driver_info):
288        type_list_config = []
289        for type_name in temp_driver_info.keys():
290            type_list_config.append(temp_driver_info[type_name])
291        for config_path in type_list_config:
292            for key_name, value in config_path["module_level_config"].items():
293                self.type_judge(value, key_name, config_path, parent_key="module_level_config")
294            for key_name, value in config_path["driver_file_list"].items():
295                self.type_judge(value, key_name, config_path, parent_key="driver_file_list")
296
297    def type_judge(self, value, key_name, config_path, parent_key):
298        if isinstance(value, list):
299            config_path[parent_key][key_name] = \
300                list(filter(lambda elem: os.path.exists(
301                    os.path.join(self.args.root_dir, elem)), value))
302            config_path[parent_key][key_name] = \
303                list(map(lambda element: os.path.join(self.args.root_dir, element),
304                         config_path[parent_key][key_name]))
305        else:
306            temp_path = os.path.join(self.args.root_dir, value)
307            if os.path.exists(temp_path):
308                config_path[parent_key][key_name] = temp_path
309            else:
310                config_path[parent_key][key_name] = ""
311
312    def delete_module_driver_list(self):
313        return self._get_model_driver_list()
314
315    def format_delete_driver_file(self, model_name, board_name, driver_name):
316        driver_json, driver_file_path = self._get_crate_model_driver_info()
317        del driver_json[board_name][model_name]["driver_file_list"][driver_name]
318        if not driver_json[board_name][model_name]["driver_file_list"]:
319            del driver_json[board_name][model_name]
320            if not driver_json[board_name]:
321                del driver_json[board_name]
322        hdf_utils.write_file(file_path=driver_file_path,
323                             content=json.dumps(driver_json, indent=4))
324