* 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 "securec.h"
#include "davinci_interface.h"
#include "apm_ioctl.h"
#ifdef EMU_ST
int apm_file_open(const char *pathname, int flags);
int apm_file_close(int fd);
int apm_file_ioctl(int fd, unsigned long cmd, void *para);
#else
#define apm_file_open open
#define apm_file_close close
static inline int apm_file_ioctl(int fd, unsigned long cmd, void *arg) {
int ret = ioctl(fd, cmd, arg);
if (ret != 0) {
share_log_read_err(HAL_MODULE_TYPE_APM);
}
return ret;
}
#endif
static THREAD__ int apm_fd = -1;
static THREAD__ pid_t apm_cur_pid = -1;
static pthread_mutex_t apm_lock = PTHREAD_MUTEX_INITIALIZER;
void apm_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);
}
int apm_char_dev_open(void)
{
struct davinci_intf_open_arg arg;
int fd = -1, ret;
ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, APM_CHAR_DEV_NAME);
if (ret != EOK) {
apm_err("Strcpy fail. (ret=%d; name=%s)\n", ret, APM_CHAR_DEV_NAME);
return ret;
}
fd = apm_file_open(davinci_intf_get_dev_path(), O_RDWR);
share_log_read_run_info(HAL_MODULE_TYPE_APM);
if (fd < 0) {
apm_err("Open char dev fail. (errno=%d; name=%s)\n", errno, APM_CHAR_DEV_NAME);
return DRV_ERROR_INNER_ERR;
}
ret = apm_file_ioctl(fd, DAVINCI_INTF_IOCTL_OPEN, &arg);
if (ret != 0) {
apm_err("Open ioctl fail. (ret=%d; erron=%d)\n", ret, errno);
apm_file_close(fd);
return ret;
}
apm_char_dev_set_close_exe(fd);
apm_fd = fd;
return 0;
}
void apm_char_dev_close(void)
{
struct davinci_intf_open_arg arg;
int ret;
ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, APM_CHAR_DEV_NAME);
if (ret != EOK) {
apm_err("Strcpy fail. (ret=%d; name=%s)\n", ret, APM_CHAR_DEV_NAME);
} else {
ret = apm_file_ioctl(apm_fd, DAVINCI_INTF_IOCTL_CLOSE, &arg);
if (ret != 0) {
#ifndef EMU_ST
apm_err("Close ioctl fail. (fd=%d; ret=%d; erron=%d)\n", apm_fd, ret, errno);
#endif
}
}
apm_file_close(apm_fd);
apm_fd = -1;
}
int apm_cmd_ioctl(unsigned long cmd, void *para)
{
int ret;
(void)pthread_mutex_lock(&apm_lock);
if (apm_fd < 0 || apm_cur_pid != getpid()) {
share_log_create(HAL_MODULE_TYPE_APM, SHARE_LOG_MAX_SIZE);
ret = apm_char_dev_open();
if (ret != 0) {
share_log_destroy(HAL_MODULE_TYPE_APM);
(void)pthread_mutex_unlock(&apm_lock);
return ret;
}
apm_cur_pid = getpid();
}
(void)pthread_mutex_unlock(&apm_lock);
do {
ret = apm_file_ioctl(apm_fd, cmd, para);
} while ((ret == -1) && (errno == EINTR));
if (ret < 0) {
if (errno == ENODEV) {
return DRV_ERROR_NO_DEVICE;
} else if (errno == ENOMEM) {
return DRV_ERROR_OUT_OF_MEMORY;
} else if (errno == ESRCH) {
return DRV_ERROR_NO_PROCESS;
} else if (errno == EFAULT) {
return DRV_ERROR_INNER_ERR;
} else if (errno == EPERM) {
return DRV_ERROR_OPER_NOT_PERMITTED;
} else if (errno == ENXIO) {
return DRV_ERROR_NOT_EXIST;
} else if (errno == ERANGE) {
return DRV_ERROR_PARA_ERROR;
} else if (errno == EEXIST) {
return DRV_ERROR_REPEATED_INIT;
} else if (errno == EOPNOTSUPP) {
return DRV_ERROR_NOT_SUPPORT;
} else {
return DRV_ERROR_IOCRL_FAIL;
}
}
return DRV_ERROR_NONE;
}
void apm_user_uninit(void)
{
if (apm_fd != -1) {
apm_char_dev_close();
}
}