--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <hal-common.h>
+#include <halcc/hal-compatibility-checker.h>
+
+#define DEFAULT_PLATFORM_MANIFEST_DIR "/etc/hal"
+#define DEFAULT_HAL_INFO_INI "/hal/etc/hal-info.ini"
+
+#define HCC_BUF_MAX (256)
+#define BOLD(STR) "\e[1m"STR"\e[m"
+
+enum {
+ OPT_START = 0,
+ OPT_HELP = OPT_START,
+ OPT_PLATFORM,
+ OPT_SKIP_IF_RESULT_EXIST,
+ OPT_REDIRECT_ALL,
+ OPT_REDIRECT_STDOUT,
+ OPT_REDIRECT_STDERR,
+ OPT_END,
+};
+
+static const struct option long_option[] = {
+ [OPT_HELP]
+ = { "help", no_argument, NULL, 'h' },
+
+ [OPT_PLATFORM]
+ = { "platform", required_argument, NULL, 'p' },
+
+ [OPT_SKIP_IF_RESULT_EXIST]
+ = { "skip-if-result-exist", optional_argument, NULL, 0 },
+
+ [OPT_REDIRECT_ALL]
+ = { "redirect-all", required_argument, NULL, 0 },
+
+ [OPT_REDIRECT_STDOUT]
+ = { "redirect-stdout", required_argument, NULL, 0 },
+
+ [OPT_REDIRECT_STDERR]
+ = { "redirect-stderr", required_argument, NULL, 0 },
+
+ { 0, },
+};
+
+static int get_tizen_hal_version(int *major, int *minor)
+{
+ FILE *fp = NULL;
+ char *line = NULL;
+ size_t len = 0;
+ int found = 0;
+ int ret;
+
+ assert(major);
+ assert(minor);
+
+ fp = fopen(DEFAULT_HAL_INFO_INI, "r");
+ if (!fp)
+ return -errno;
+
+ while (getline(&line, &len, fp) != EOF) {
+ if (fscanf(fp, "Model=Tizen%d.%d", major, minor) == 2) {
+ found = 1;
+ break;
+ }
+ }
+
+ fclose(fp);
+ fp = NULL;
+ free(line);
+ line = NULL;
+
+ return found ? 0 : -EINVAL;
+}
+
+static const char* default_platform_manifest_dir(void)
+{
+ static char dirpath[HCC_BUF_MAX] = { 0 , };
+ int major;
+ int minor;
+ int ret;
+
+ ret = get_tizen_hal_version(&major, &minor);
+ if (ret != 0)
+ return NULL;
+
+ snprintf(dirpath, sizeof(dirpath), DEFAULT_PLATFORM_MANIFEST_DIR"/%d.%d", major, minor);
+
+ return dirpath;
+}
+
+// check result is exist, return true on exist.
+static bool result_exist(const char *dir)
+{
+ // check result exists based on the directory 'dir'.
+ return false;
+}
+
+static int redirect_output(const char *file, int stdfd)
+{
+ int fd = open(file, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ int newfd;
+
+ if (fd == -1) {
+ printf("hal-compatibility-checker: Failed to redirect output: %m\n");
+ return -1;
+ }
+
+ newfd = dup2(fd, stdfd);
+ close(fd);
+
+ return newfd;
+}
+
+static void show_help(void)
+{
+ printf(
+ "hal-compatibility-checker - check compatibility between hal-api and hal-backend\n"
+ "\n"
+ BOLD("USAGE\n")
+ "\thal-compatibility-checker [OPTION]...\n"
+ "\n"
+ BOLD("OPTION\n")
+ "\t-h, --help\n"
+ "\t\tshow this help.\n"
+ "\n"
+ "\t-p, --platform=DIRECTORY\n"
+ "\t\tspecify directory that holds platform manifest xml\n"
+ "\t\twhen it is not specified, use default path: %s\n"
+ "\n"
+ "\t--skip-if-result-exist[=DIRECTORY]\n"
+ "\t\tskip compatibility check if there exists a result of compatibility.\n"
+ "\t\tif DIRECTORY is given, locate a result based on the given DIRECTORY.\n"
+ "\n"
+ "\t--redirect-all=FILE\n"
+ "\t\tredirect stdout/stderr to FILE.\n"
+ "\n"
+ "\t--redirect-stdout=FILE\n"
+ "\t\tredirect stdout to FILE.\n"
+ "\n"
+ "\t--redirect-stderr=FILE\n"
+ "\t\tredirect stderr to FILE.\n"
+ , default_platform_manifest_dir()
+ );
+}
+
+static void compatibility_cb(enum hal_module module,
+ halcc_compatibility_e is_compatible, void *user_data)
+{
+ // do something
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ int help = 0;
+ int index;
+ bool skip_if_result_exist = false;
+ const char *skip_if_result_exist_dir = NULL;
+ const char *platform_manifest_dir = NULL;
+ const char *outfile = NULL;
+ const char *errfile = NULL;
+
+ for (;;) {
+ opt = getopt_long(argc, argv, "hp:", long_option, &index);
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'h':
+ help = 1;
+ break;
+ case 'p':
+ platform_manifest_dir = optarg;
+ break;
+ case 0: // long-only options
+ {
+ switch (index) {
+ case OPT_SKIP_IF_RESULT_EXIST:
+ skip_if_result_exist = true;
+ skip_if_result_exist_dir = optarg;
+ break;
+ case OPT_REDIRECT_ALL:
+ outfile = optarg;
+ errfile = optarg;
+ break;
+ case OPT_REDIRECT_STDOUT:
+ outfile = optarg;
+ break;
+ case OPT_REDIRECT_STDERR:
+ errfile = optarg;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (help) {
+ show_help();
+ return 0;
+ }
+
+ if (outfile)
+ redirect_output(outfile, STDOUT_FILENO);
+
+ if (errfile)
+ redirect_output(errfile, STDERR_FILENO);
+
+ if (skip_if_result_exist && result_exist(skip_if_result_exist_dir)) {
+ printf("hal-compatibility-checker: skip checking\n");
+ return 0;
+ }
+
+ if (!platform_manifest_dir)
+ platform_manifest_dir = default_platform_manifest_dir();
+
+ halcc_check_compatibility(platform_manifest_dir, compatibility_cb, NULL);
+
+ return 0;
+}