aff95158创建于 2025年12月23日历史提交
/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/types.h>

#include "securec.h"
#include "davinci_interface.h"
#include "rmo.h"

#ifdef EMU_ST
int rmo_file_open(const char *pathname, int flags);
int rmo_file_close(int fd);
int rmo_file_ioctl(int fd, unsigned long cmd, void *para);
#else
#define rmo_file_open open
#define rmo_file_close close
#define rmo_file_ioctl(fd, cmd, ...) ioctl((fd), (cmd), ##__VA_ARGS__)
#endif

static THREAD__ int rmo_fd = -1;
static THREAD__ pid_t rmo_cur_pid = -1;
static pthread_mutex_t rmo_lock = PTHREAD_MUTEX_INITIALIZER;

int rmo_get_fd(void)
{
    return rmo_fd;
}

static void rmo_char_dev_set_close_exe(int fd)
{
    int flags;

    flags = fcntl(fd, F_GETFD);
    flags = (int)((unsigned int)flags | FD_CLOEXEC);
    (void)fcntl(fd, F_SETFD, flags);
}

static int rmo_char_dev_open(void)
{
    struct davinci_intf_open_arg arg;
    int fd = -1, ret;

    ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, RMO_CHAR_DEV_NAME);
    if (ret != EOK) {
        rmo_err("Strcpy fail. (ret=%d; name=%s)\n", ret, RMO_CHAR_DEV_NAME);
        return ret;
    }
    fd = rmo_file_open(davinci_intf_get_dev_path(), O_RDWR);
    if (fd < 0) {
        rmo_err("Open char dev fail. (errno=%d; name=%s)\n", errno, RMO_CHAR_DEV_NAME);
        return DRV_ERROR_INNER_ERR;
    }
    ret = rmo_file_ioctl(fd, DAVINCI_INTF_IOCTL_OPEN, &arg);
    if (ret != 0) {
        rmo_err("Open ioctl fail. (ret=%d; erron=%d)\n", ret, errno);
        rmo_file_close(fd);
        return ret;
    }

    rmo_char_dev_set_close_exe(fd);
    rmo_fd = fd;

    return 0;
}

static void rmo_char_dev_close(void)
{
    struct davinci_intf_open_arg arg;
    int ret;

    ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, RMO_CHAR_DEV_NAME);
    if (ret != EOK) {
        rmo_err("Strcpy fail. (ret=%d; name=%s)\n", ret, RMO_CHAR_DEV_NAME);
    } else {
        ret = rmo_file_ioctl(rmo_fd, DAVINCI_INTF_IOCTL_CLOSE, &arg);
        if (ret != 0) {
#ifndef EMU_ST
            rmo_err("Close ioctl fail. (fd=%d; ret=%d; erron=%d)\n", rmo_fd, ret, errno);
#endif
        }
    }

    rmo_file_close(rmo_fd);
    rmo_fd = -1;
}

int rmo_cmd_ioctl(unsigned long cmd, void *para)
{
    int ret;

    (void)pthread_mutex_lock(&rmo_lock);
    if (rmo_fd < 0 || rmo_cur_pid != getpid()) {
        ret = rmo_char_dev_open();
        if (ret != 0) {
            (void)pthread_mutex_unlock(&rmo_lock);
            return ret;
        }
        rmo_cur_pid = getpid();
    }
    (void)pthread_mutex_unlock(&rmo_lock);

    do {
        ret = rmo_file_ioctl(rmo_fd, cmd, para);
    } while ((ret == -1) && (errno == EINTR));

    if (ret < 0) {
        return errno_to_user_errno(ret);
    }

    return DRV_ERROR_NONE;
}

void rmo_user_uninit(void)
{
    if (rmo_fd != -1) {
        rmo_char_dev_close();
    }
}