/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2012-2019. All rights reserved. * Description: supply the api for userspace application */ #include #include #include #include #include #include #include #include #include "soc_errno.h" #include "soc_module.h" #include "uapi_pwm.h" #include "drv_ioctl_pwm.h" #include "soc_log.h" #define SOC_DEV_PWM_NAME "soc_pwm" #undef LOG_MODULE_ID #define LOG_MODULE_ID SOC_ID_PWM static td_s32 g_pwm_dev_fd = -1; static const td_char g_pwm_dev_name[] = "/dev/"SOC_DEV_PWM_NAME; static pthread_mutex_t g_pwm_mutex = PTHREAD_MUTEX_INITIALIZER; #define PWM_PATH_MAX_LEN 256 #define ext_pwm_lock() (td_void)pthread_mutex_lock(&g_pwm_mutex) #define ext_pwm_unlock() (td_void)pthread_mutex_unlock(&g_pwm_mutex) #define pwm_check_init(ret) do { \ ext_pwm_lock(); \ if (g_pwm_dev_fd < 0) { \ soc_log_err("pwm is not init!\n"); \ (ret) = SOC_ERR_PWM_NOT_INIT; \ } \ ext_pwm_unlock(); \ } while (0) td_s32 uapi_pwm_init(td_void) { ext_pwm_lock(); td_char *presolved_path = TD_NULL; if (g_pwm_dev_fd > 0) { ext_pwm_unlock(); return TD_SUCCESS; } if (strlen(g_pwm_dev_name) > PWM_PATH_MAX_LEN - 1) { soc_log_err("The g_pwm_dev_name is too long! \n"); ext_pwm_unlock(); return SOC_ERR_PWM_OPEN_ERR; } presolved_path = realpath(g_pwm_dev_name, TD_NULL); if (presolved_path == TD_NULL) { soc_log_err("pwm dev path is invalid!\n"); ext_pwm_unlock(); return SOC_ERR_PWM_OPEN_ERR; } g_pwm_dev_fd = open(presolved_path, O_RDWR | O_NONBLOCK, 0); if (g_pwm_dev_fd < 0) { soc_log_err("pwm device open err!\n"); free(presolved_path); presolved_path = TD_NULL; ext_pwm_unlock(); return SOC_ERR_PWM_OPEN_ERR; } free(presolved_path); presolved_path = TD_NULL; ext_pwm_unlock(); return TD_SUCCESS; } td_s32 uapi_pwm_deinit(td_void) { td_s32 ret; ext_pwm_lock(); if (g_pwm_dev_fd < 0) { ext_pwm_unlock(); return TD_SUCCESS; } ret = close(g_pwm_dev_fd); if (ret != TD_SUCCESS) { soc_log_err("pwm device close err!\n"); ext_pwm_unlock(); return SOC_ERR_PWM_CLOSE_ERR; } g_pwm_dev_fd = -1; ext_pwm_unlock(); return TD_SUCCESS; } td_s32 uapi_pwm_get_attr(td_u32 pwm_id, uapi_pwm_attr *pwm_attr) { td_s32 ret = 0; pwm_attr_cmd_para st_cmd_para = {0}; if (pwm_attr == TD_NULL) { soc_log_err("[get_attr] ERR: invalid param!\n"); return SOC_ERR_PWM_INVALID_PARA; } pwm_check_init(ret); if (ret == SOC_ERR_PWM_NOT_INIT) { return ret; } st_cmd_para.pwm_no = pwm_id; st_cmd_para.pwm_attr = *(ext_drv_pwm_attr *)(td_void *)pwm_attr; ret = ioctl(g_pwm_dev_fd, CMD_PWM_GETATTR, &st_cmd_para); pwm_attr->pwm_frequency = st_cmd_para.pwm_attr.freq; pwm_attr->pwm_duty_ratio = st_cmd_para.pwm_attr.duty_ratio; if (ret != TD_SUCCESS) { soc_log_err("ERR: get pwm_attr err, ret=%#x!\n", ret); return SOC_ERR_PWM_INVALID_OPT; } return TD_SUCCESS; } td_s32 uapi_pwm_set_attr(td_u32 pwm_id, const uapi_pwm_attr *pwm_attr) { td_s32 ret = 0; pwm_attr_cmd_para st_cmd_para = {0}; if (pwm_attr == TD_NULL) { soc_log_err("[set_attr] ERR: invalid param!\n"); return SOC_ERR_PWM_INVALID_PARA; } pwm_check_init(ret); if (ret == SOC_ERR_PWM_NOT_INIT) { return ret; } st_cmd_para.pwm_no = pwm_id; st_cmd_para.pwm_attr = *(ext_drv_pwm_attr *)(td_void *)pwm_attr; ret = ioctl(g_pwm_dev_fd, CMD_PWM_SETATTR, &st_cmd_para); if (ret != TD_SUCCESS) { soc_log_err("ERR: set pwm_attr err, ret=%#x!\n", ret); return SOC_ERR_PWM_INVALID_OPT; } return TD_SUCCESS; } td_s32 uapi_pwm_send_signal(td_u32 pwm_id, td_u32 carrier_time, td_u32 low_level_time) { td_s32 ret = 0; pwm_signal_cmd_para st_cmd_para = {0}; pwm_check_init(ret); if (ret == SOC_ERR_PWM_NOT_INIT) { return ret; } st_cmd_para.pwm_no = pwm_id; st_cmd_para.carrier_sig_duration_us = carrier_time; st_cmd_para.low_level_sig_duration_us = low_level_time; ret = ioctl(g_pwm_dev_fd, CMD_PWM_SENDSIGNAL, &st_cmd_para); if (ret != TD_SUCCESS) { soc_log_err("ERR: send signal err, ret=%#x!\n", ret); return SOC_ERR_PWM_INVALID_OPT; } return TD_SUCCESS; } td_s32 uapi_pwm_set_enable(td_u32 pwm_id, td_bool enable) { td_s32 ret = 0; pwm_enable_cmd_para st_cmd_para = {0}; pwm_check_init(ret); if (ret == SOC_ERR_PWM_NOT_INIT) { return ret; } if ((enable != TD_TRUE) && (enable != TD_FALSE)) { soc_log_err("ERR: invalid param!\n"); return SOC_ERR_PWM_INVALID_PARA; } st_cmd_para.pwm_no = pwm_id; st_cmd_para.enable = enable; ret = ioctl(g_pwm_dev_fd, CMD_PWM_SETENABLE, &st_cmd_para); if (ret != TD_SUCCESS) { soc_log_err("ERR: set pwm enable err, ret=%#x!\n", ret); return SOC_ERR_PWM_INVALID_OPT; } return TD_SUCCESS; } td_s32 uapi_pwm_moto_trigger(td_u32 pwm_id, const uapi_pwm_attr *pwm_attr, td_u32 time_us) { td_s32 ret = 0; pmw_moto_cmd_para moto_pwm_cmd = {0}; pwm_check_init(ret); if (ret == SOC_ERR_PWM_NOT_INIT) { return ret; } if (pwm_attr == TD_NULL) { soc_log_err("ERR: invalid param!\n"); return SOC_ERR_PWM_INVALID_PARA; } moto_pwm_cmd.pwm_no = pwm_id; moto_pwm_cmd.pwm_attr = *(ext_drv_pwm_attr *)(td_void *)pwm_attr; moto_pwm_cmd.time_us = time_us; ret = ioctl(g_pwm_dev_fd, CMD_PWM_MOTOPWM, &moto_pwm_cmd); if (ret != TD_SUCCESS) { soc_log_err("ERR: pwm-moto trigger err, ret=%#x!\n", ret); return SOC_ERR_PWM_INVALID_OPT; } return TD_SUCCESS; }