You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1590 lines
48 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2017-2021. All rights reserved.
* Description: DiSEqC IAPI interface
* Author: Hisilicon
* Create: 2017-06-30
*/
#include "iapi_diseqc.h"
#include <math.h>
#include "soc_errno.h"
#include "soc_log.h"
#include "securec.h"
#include "mpi_frontend_ext.h"
#include "iapi_frontend.h"
#include "iapi_sat.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
static diseqc_status g_diseqc_status[IAPI_TUNER_NUM] = {
{
.port1_0 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE,
UAPI_FRONTEND_POLARIZATION_H,
UAPI_FRONTEND_LNB_22K_OFF
},
.port1_1 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE
}
},
{
.port1_0 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE,
UAPI_FRONTEND_POLARIZATION_H,
UAPI_FRONTEND_LNB_22K_OFF
},
.port1_1 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE
}
},
{
.port1_0 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE,
UAPI_FRONTEND_POLARIZATION_H,
UAPI_FRONTEND_LNB_22K_OFF
},
.port1_1 = {
UAPI_FRONTEND_DISEQC_LEVEL_1_X,
UAPI_FRONTEND_DISEQC_SWITCH_NONE
}
}
};
static td_s32 diseqc_send_cmd_1_0(td_u32 port, const uapi_frontend_diseqc_switch_4_port_para *para)
{
td_s32 ret;
td_u8 port_group_bits;
td_u8 cmd;
td_u8 framing;
td_u8 polar;
td_u8 lo_freq;
uapi_frontend_diseqc_send_msg send_msg = {0};
/* Polarization */
if ((para->polar == UAPI_FRONTEND_POLARIZATION_V) ||
(para->polar == UAPI_FRONTEND_POLARIZATION_R)) {
polar = POLARISATION_V;
} else {
polar = POLARISATION_H;
}
/* LO, 22K */
lo_freq = (para->lnb_22k == UAPI_FRONTEND_LNB_22K_ON) ? LO_FREQUENCY_H : LO_FREQUENCY_L;
/* Init parameter */
send_msg.level = para->level;
send_msg.tone_burst = diseqc_get_tone_burst_status(port);
send_msg.length = 4; /* 4: DisEqC msg length */
send_msg.repeat_times = 0;
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
/* Send WRITE N0(0x38) command */
port_group_bits = PORT_GROUP_CLR_BITS | (((td_u8)((td_u8)(para->port) - 1)) << 2) | polar | lo_freq; /* 2:for CMD */
cmd = CMD_WRITE_N0;
format_diseqc_cmd_value(send_msg.msg, framing, DEVICE_ANY_LNB_SW_SMATV, cmd, &port_group_bits, 1);
ret = diseqc_send_recv_message(port, &send_msg, NULL); /* &recv_msg */
if (ret != TD_SUCCESS) {
soc_log_err("Send WRITE N0 fail.\n");
return ret;
}
/* If support level 2.x, handle received message here */
return TD_SUCCESS;
}
static td_s32 diseqc_send_cmd_1_1(td_u32 port, const uapi_frontend_diseqc_switch_16_port_para *para)
{
td_s32 ret;
td_u8 port_group_bits;
td_u8 cmd;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
if ((para->port <= UAPI_FRONTEND_DISEQC_SWITCH_NONE) ||
(para->port >= UAPI_FRONTEND_DISEQC_SWITCH_PORT_MAX)) {
soc_log_err("Input parameter(para.port)invalid.\n");
soc_err_print_u32(para->port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
/* Init parameter */
send_msg.level = para->level;
send_msg.tone_burst = diseqc_get_tone_burst_status(port);
send_msg.length = 4; /* 4: DisEqC msg length */
send_msg.repeat_times = 0;
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
/* Send WRITE N1(0x39) command */
port_group_bits = PORT_GROUP_CLR_BITS | ((td_u8)para->port - 1);
cmd = CMD_WRITE_N1;
format_diseqc_cmd_value(send_msg.msg, framing, DEVICE_ANY_LNB_SW_SMATV, cmd, &port_group_bits, 1);
ret = diseqc_send_recv_message(port, &send_msg, NULL); /* &recv_msg */
if (ret != TD_SUCCESS) {
soc_log_err("Send WRITE N1 fail.\n");
return ret;
}
/* If support level 2.x, handle received message here */
return TD_SUCCESS;
}
static td_s32 diseqc_switch_4_port_valid(td_u32 port, const uapi_frontend_diseqc_switch_4_port_para* para)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->port >= UAPI_FRONTEND_DISEQC_SWITCH_PORT_5) {
soc_log_err("Input parameter(Switch port) invalid.\n");
soc_err_print_u32(para->port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
/* Save port parameter */
g_diseqc_status[port].port1_0 = *para;
/* If NONE, only save */
if (para->port == UAPI_FRONTEND_DISEQC_SWITCH_NONE) {
return TD_SUCCESS;
}
/* If use 4port device, other parameter must be valid */
if (para->polar >= UAPI_FRONTEND_POLARIZATION_MAX) {
soc_log_err("Input parameter(Polarization) invalid.\n");
soc_err_print_u32(para->polar);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->lnb_22k >= UAPI_FRONTEND_LNB_22K_MAX) {
soc_log_err("Input parameter(LNB 22K) invalid.\n");
soc_err_print_u32(para->lnb_22k);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_switch_4_port(td_u32 port, const uapi_frontend_diseqc_switch_4_port_para *para)
{
td_s32 ret;
soc_notice_func_enter();
ret = diseqc_switch_4_port_valid(port, para);
if (ret != TD_SUCCESS) {
soc_log_err("tuner_diseqc_switch4port_valid failed. ret: %d\n", ret);
return ret;
}
/* Switch 1.0 */
ret = diseqc_send_cmd_1_0(port, para);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(diseqc_send_cmd_1_0, ret);
return ret;
}
/* If has switch 1.1, set it here
* Support Tuner - DiSEqC1.0 - DiSEqC1.1 - Other switch - LNB cascaded. */
if (g_diseqc_status[port].port1_1.port != UAPI_FRONTEND_DISEQC_SWITCH_NONE) {
fe_usleep(DISEQC_DELAY_BETWEEN_CMD_MS * 1000); /* 1000: unit, us */
ret = diseqc_send_cmd_1_1(port, &(g_diseqc_status[port].port1_1));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(diseqc_send_cmd_1_1, ret);
return ret;
}
}
soc_notice_func_exit();
return TD_SUCCESS;
}
static td_s32 diseqc_switch_16_port_valid(td_u32 port, const uapi_frontend_diseqc_switch_16_port_para *para)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->port >= UAPI_FRONTEND_DISEQC_SWITCH_PORT_MAX) {
soc_log_err("Input parameter(Switch port) invalid.\n");
soc_err_print_u32(para->port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_switch_16_port(td_u32 port, const uapi_frontend_diseqc_switch_16_port_para *para)
{
td_s32 ret;
soc_notice_func_enter();
ret = diseqc_switch_16_port_valid(port, para);
if (ret != TD_SUCCESS) {
soc_log_err("tuner_diseqc_switch4port_valid failed. ret: %d\n", ret);
return ret;
}
/* Save port parameter */
g_diseqc_status[port].port1_1 = *para;
/* If NONE, return */
if (para->port == UAPI_FRONTEND_DISEQC_SWITCH_NONE) {
return TD_SUCCESS;
}
/* If have 1.0 switch, set if first */
if (g_diseqc_status[port].port1_0.port != UAPI_FRONTEND_DISEQC_SWITCH_NONE) {
ret = diseqc_send_cmd_1_0(port, &(g_diseqc_status[port].port1_0));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(diseqc_send_cmd_1_0, ret);
return ret;
}
fe_usleep(DISEQC_DELAY_BETWEEN_CMD_MS * 1000); /* 1000: unit, us */
}
/* Switch 1.1 */
ret = diseqc_send_cmd_1_1(port, para);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(diseqc_send_cmd_1_1, ret);
return ret;
}
/* If have 1.0 switch, repeat
* Support Tuner - DiSEqC1.1 - DiSEqC1.0 - Other switch - LNB cascaded. */
if (g_diseqc_status[port].port1_0.port != UAPI_FRONTEND_DISEQC_SWITCH_NONE) {
fe_usleep(DISEQC_DELAY_BETWEEN_CMD_MS * 1000); /* 1000: unit, us */
ret = diseqc_send_cmd_1_0(port, &(g_diseqc_status[port].port1_0));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(diseqc_send_cmd_1_0, ret);
return ret;
}
}
soc_notice_func_exit();
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_store_pos(td_u32 port, const uapi_frontend_diseqc_position *para)
{
td_s32 ret;
td_u8 framing;
td_u8 pos;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->pos > UAPI_DISEQC_MAX_MOTOR_PISITION) {
soc_log_err("Input parameter(para->u32Pos) invalid.\n");
soc_err_print_u32(para->pos);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
pos = (td_u8)para->pos;
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd_value(send_msg.msg, framing, DEVICE_AZIMUTH_POSITIONER, CMD_STORE_NN, &pos, 1);
send_msg.length = 4; /* 4: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send Store N fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
td_s32 uapi_frontend_diseqc_goto_pos(td_u32 port, const uapi_frontend_diseqc_position *para)
{
td_s32 ret;
td_u8 framing;
td_u8 pos;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(para->level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->pos > UAPI_DISEQC_MAX_MOTOR_PISITION) {
soc_log_err("Input parameter(para->u32Pos) invalid.\n");
soc_err_print_u32(para->pos);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
pos = (td_u8)para->pos;
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd_value(send_msg.msg, framing, DEVICE_AZIMUTH_POSITIONER, CMD_GOTO_NN, &pos, 1);
send_msg.length = 4; /* 4: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send Goto N fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
static td_s32 tuner_diseqc_set_limit_valid(td_u32 port, const uapi_frontend_diseqc_limit_para *para)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(para->level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->limit >= UAPI_FRONTEND_DISEQC_LIMIT_MAX) {
soc_log_err("Input parameter(para->limit) invalid.\n");
soc_err_print_u32(para->limit);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_set_limit(td_u32 port, const uapi_frontend_diseqc_limit_para *para)
{
td_s32 ret;
td_u8 framing;
td_u8 cmd;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (para == TD_NULL) {
soc_log_err("Input parameter(para) is TD_NULL.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
ret = tuner_diseqc_set_limit_valid(port, para);
if (ret != TD_SUCCESS) {
soc_log_err("tuner_diseqc_set_limit_valid failed. ret: %d\n", ret);
return ret;
}
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
switch (para->limit) {
case UAPI_FRONTEND_DISEQC_LIMIT_EAST:
cmd = CMD_LIMIT_E;
break;
case UAPI_FRONTEND_DISEQC_LIMIT_WEST:
cmd = CMD_LIMIT_W;
break;
case UAPI_FRONTEND_DISEQC_LIMIT_OFF:
default:
cmd = CMD_LIMITS_OFF;
break;
}
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd(send_msg.msg, framing, DEVICE_AZIMUTH_POSITIONER, cmd);
send_msg.length = 3; /* 3: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send limit cmd fail.\n");
return ret;
}
soc_notice_func_exit();
return TD_SUCCESS;
}
static td_s32 tuner_diseqc_runstep_valid(td_u32 port, const uapi_frontend_diseqc_run *para)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(para->level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->dir >= UAPI_FRONTEND_DISEQC_MOVE_DIR_MAX) {
soc_log_err("Input parameter(para->dir:%d) invalid.\n", para->dir);
soc_err_print_u32(para->dir);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->running_steps > MOTOR_RUNNING_STEPS_MAX) {
soc_log_err("Input parameter(para->running_steps) invalid.\n");
soc_err_print_u32(para->running_steps);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
static td_void tuner_diseqc_runstep_config(const uapi_frontend_diseqc_run *para,
td_u8 *framing, td_u8 *cmd, td_u8 *value)
{
switch (para->level) {
case UAPI_FRONTEND_DISEQC_LEVEL_1_X:
soc_log_dbg("Level 1_x.\n");
break;
case UAPI_FRONTEND_DISEQC_LEVEL_2_X:
soc_log_dbg("Level 2_x.\n");
break;
case UAPI_FRONTEND_DISEQC_LEVEL_MAX:
default:
soc_log_dbg("Level init err.\n");
break;
}
*framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
/* Direction */
switch (para->dir) {
case UAPI_FRONTEND_DISEQC_MOVE_DIR_EAST:
soc_log_dbg("move east.\n");
*cmd = CMD_DRIVE_EAST;
break;
case UAPI_FRONTEND_DISEQC_MOVE_DIR_WEST:
soc_log_dbg("move west.\n");
*cmd = CMD_DRIVE_WEST;
break;
case UAPI_FRONTEND_DISEQC_MOVE_DIR_MAX:
default:
soc_log_dbg("move err.\n");
break;
}
/* Value */
soc_log_dbg("Running steps:");
soc_dbg_print_u32(para->running_steps);
if (para->running_steps == MOTOR_RUNNING_STEPS_MIN) {
*value = 0;
} else {
/* run 1 step every time,value = 0xff
* run 2 step every time,value = 0xfe
* run 3 step every time,value = 0xfd
* run 4 step every time,value = 0xfc
* run 5 step every time,value = 0xfb
* run 6 step every time,value = 0xfa
* run 7 step every time,value = 0xf9
* run 8 step every time,value = 0xf8
*/
*value = 0xff - (td_u8)(para->running_steps) + 1;
}
}
td_s32 uapi_frontend_diseqc_run_step(td_u32 port, const uapi_frontend_diseqc_run *para)
{
td_s32 ret;
td_u8 framing = 0;
td_u8 cmd = 0;
td_u8 value = 0;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (para == TD_NULL) {
soc_log_err("Input parameter(para) is TD_NULL.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
ret = tuner_diseqc_runstep_valid(port, para);
if (ret != TD_SUCCESS) {
soc_log_err("tuner_diseqc_runstep_valid failed. ret: %d\n", ret);
return ret;
}
tuner_diseqc_runstep_config(para, &framing, &cmd, &value);
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd_value(send_msg.msg, framing, DEVICE_AZIMUTH_POSITIONER, cmd, &value, 1);
send_msg.length = 4; /* 4: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send drive cmd fail.\n");
return ret;
}
soc_notice_func_exit();
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_stop(td_u32 port, const uapi_frontend_diseqc_level level)
{
td_s32 ret;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd(send_msg.msg, framing, DEVICE_AZIMUTH_POSITIONER, CMD_HALT);
send_msg.length = 3; /* 3: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send halt fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
td_s32 uapi_frontend_diseqc_recalculate(td_u32 port, const uapi_frontend_diseqc_recalculation *para)
{
td_s32 ret;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
send_msg.msg[FRAMING_BYTE] = framing;
send_msg.msg[ADDRESS_BYTE] = DEVICE_AZIMUTH_POSITIONER;
send_msg.msg[COMMAND_BYTE] = CMD_SET_POSNS;
send_msg.msg[DATA_BYTE_0] = para->para1;
send_msg.msg[DATA_BYTE_1] = para->para2;
send_msg.msg[DATA_BYTE_2] = para->para3;
if ((para->para2 == 0) && (para->para3 == 0)) {
send_msg.length = 4; /* 4: DisEqC msg length */
} else {
send_msg.length = 6; /* 6: DisEqC msg length */
}
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send Set Posns fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
static td_s32 tuner_diseqc_calc_angular_valid(td_u32 port, const uapi_frontend_diseqc_usals_para *para)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->local_longitude > 2 * MAX_LONGITUDE) { /* 2:size */
soc_log_err("Input parameter(para->local_longitude) invalid.\n");
soc_err_print_u32(para->local_longitude);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->local_latitude > 2 * MAX_LATITUDE) { /* 2:size */
soc_log_err("Input parameter(para->local_latitude) invalid.\n");
soc_err_print_u32(para->local_latitude);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para->sat_longitude > 2 * MAX_LONGITUDE) { /* 2:size */
soc_log_err("Input parameter(para->sat_longitude) invalid.\n");
soc_err_print_u32(para->sat_longitude);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
static td_void tuner_diseqc_calc_angular_rotate_angle(const uapi_frontend_diseqc_usals_para *para,
td_double *rotate_angle)
{
td_u16 longitude;
td_u16 lat;
td_u16 sat_long;
td_double sat_angle, sat_longitude;
td_double latitude;
td_double t1, t2, t3, t4;
/* Convert angle */
longitude = para->local_longitude;
lat = para->local_latitude;
sat_long = para->sat_longitude;
sat_longitude = ((longitude < MAX_LONGITUDE) ?
longitude : -(2 * MAX_LONGITUDE - longitude)) / ANGLE_MULTIPLE; /* 2:size */
latitude = ((lat < MAX_LATITUDE) ? lat : -(2 * MAX_LATITUDE - lat)) / ANGLE_MULTIPLE; /* 2:size */
sat_angle = ((sat_long < MAX_LONGITUDE) ? sat_long : -(2 * MAX_LONGITUDE - sat_long)) / ANGLE_MULTIPLE; /* 2:size */
t1 = (td_double)(USALS_CONST_1 * cosf((td_float)(PI * fabs(sat_angle - sat_longitude) / USALS_CONST_2)));
t1 = (td_double) sqrtf((td_float)(USALS_CONST_1 - t1));
t1 = t1 * t1;
t2 = USALS_CONST_3 * sinf((td_float)(PI * latitude / USALS_CONST_2));
t2 = t2 * t2;
t3 = (td_double) sqrtf((td_float)(USALS_CONST_4 - t2));
t3 = (td_double) t3 * sinf((td_float)(PI * fabs(sat_angle - sat_longitude) / USALS_CONST_2));
t3 = t3 * t3;
t3 = (td_double) sqrtf((td_float)(t2 + t3));
t3 = (asinf((td_float)(t3 / USALS_CONST_3)) * USALS_CONST_2) / PI;
t3 = cosf((td_float)(PI * t3 / USALS_CONST_2));
t3 = (td_double) sqrtf((td_float)(USALS_CONST_5 - (USALS_CONST_6 * t3)));
t4 = cosf((td_float)(PI * latitude / USALS_CONST_2));
t4 = (td_double) sqrtf((td_float)(USALS_CONST_5 - (USALS_CONST_6 * t4)));
t4 = (acosf((td_float)(((t3 * t3) + (t4 * t4) - t1) / (2.0 * t3 * t4))) * USALS_CONST_2) / PI; /* 2.0:size */
/* Handle negative case */
if (((latitude > 0) &&
(((sat_angle < sat_longitude) && (fabs(sat_longitude - sat_angle) < 180.0)) || /* 180.0:Angle */
((sat_angle > sat_longitude) && (fabs(sat_longitude - sat_angle) > 180.0)))) || /* 180.0:Angle */
((latitude <= 0) &&
(((sat_angle > sat_longitude) && (fabs(sat_longitude - sat_angle) < 180.0)) || /* 180.0:Angle */
((sat_angle < sat_longitude) && (fabs(sat_longitude - sat_angle) > 180.0))))) { /* 180.0:Angle */
*rotate_angle = -t4;
} else {
*rotate_angle = t4;
}
}
static td_void tuner_diseqc_calc_angular_rotate_execute(uapi_frontend_diseqc_usals_para *para,
td_u8 rotate_integral, td_u8 rotate_fractional, td_u8 rotate_angle_sign)
{
td_u8 byte1;
td_u8 byte2;
/* Handle the first nibble */
byte1 = rotate_angle_sign | (rotate_integral >> 4); /* 4:shift */
byte2 = (rotate_integral & 0xF) << 4; /* 0xF:reg addr,4:shift */
/* According to section 3.10 of <positioner_appli_notice.pdf> */
switch (rotate_fractional) {
case 0: /* 0:value */
byte2 |= 0x0;
break;
case 1: /* 1:value */
byte2 |= 0x2;
break;
case 2: /* 2:value */
byte2 |= 0x3;
break;
case 3: /* 3:value */
byte2 |= 0x5;
break;
case 4: /* 4:value */
byte2 |= 0x6;
break;
case 5: /* 5:value */
byte2 |= 0x8;
break;
case 6: /* 6:value */
byte2 |= 0xA;
break;
case 7: /* 7:value */
byte2 |= 0xB;
break;
case 8: /* 8:value */
byte2 |= 0xD;
break;
case 9: /* 9:value */
byte2 |= 0xE;
break;
default:
byte2 |= 0x0;
break;
}
para->angular = 0;
para->angular |= (td_u16)byte1 << 8; /* 8:step */
para->angular |= byte2;
}
td_s32 uapi_frontend_diseqc_calc_angular(td_u32 port, uapi_frontend_diseqc_usals_para *para)
{
td_s32 ret;
td_u8 rotate_integral;
td_u8 rotate_fractional;
td_u8 rotate_angle_sign;
td_double rotate_angle;
soc_notice_func_enter();
if (para == TD_NULL) {
soc_log_err("Input parameter(para) is TD_NULL.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
ret = tuner_diseqc_calc_angular_valid(port, para);
if (ret != TD_SUCCESS) {
soc_log_err("tuner_diseqc_calc_angular_valid failed. ret: %d\n", ret);
return ret;
}
tuner_diseqc_calc_angular_rotate_angle(para, &rotate_angle);
rotate_integral = (td_u8)fabs(rotate_angle);
rotate_fractional = (td_u8)((fabs(rotate_angle) - (double)rotate_integral) * ANGLE_MULTIPLE);
rotate_angle_sign = (rotate_angle < 0.0) ? 0xD0u : 0xE0u;
/*
* Generally, mator can't support rotation angle > 85;
* and, if the difference between local longitude and satellite longitude is too large,
* the calculate result may be 0.
*/
if ((rotate_integral > 85) || /* 85:angle max */
((para->sat_longitude != para->local_longitude) &&
(rotate_integral == 0) && (rotate_fractional == 0))) {
soc_log_err("Rotation angle too large!\n");
return SOC_ERR_FRONTEND_INVALID_PARA;
}
tuner_diseqc_calc_angular_rotate_execute(para, rotate_integral, rotate_fractional, rotate_angle_sign);
soc_notice_func_exit();
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_goto_angular(td_u32 port, const uapi_frontend_diseqc_usals_angular *para)
{
td_s32 ret;
td_u8 framing;
td_u8 value[2]; /* 2: size */
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (para == TD_NULL) {
soc_log_err("Input parameter(para) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (para->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(para->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (para->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = para->level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
value[0] = (td_u8)(para->angular >> 8); /* 8:step */
value[1] = (td_u8)(para->angular);
format_diseqc_cmd_value(send_msg.msg,
framing, DEVICE_AZIMUTH_POSITIONER, CMD_GOTO_XX, value, 2); /* 2:step */
send_msg.length = 5; /* 5: DisEqC msg length */
send_msg.repeat_times = 0;
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send Goto XX fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
td_s32 uapi_frontend_diseqc_reset(td_u32 port, uapi_frontend_diseqc_level level)
{
td_s32 ret;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd(send_msg.msg, framing, DEVICE_ANY, CMD_RESET);
send_msg.length = 3; /* 3: DisEqC msg length */
send_msg.repeat_times = 2; /* 2: DisEqC msg repeat time */
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("DiSEqC reset fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
td_s32 uapi_frontend_diseqc_standby(td_u32 port, uapi_frontend_diseqc_level level)
{
td_s32 ret;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd(send_msg.msg, framing, DEVICE_ANY, CMD_STANDBY);
send_msg.length = 3; /* 3: DisEqC msg length */
send_msg.repeat_times = 2; /* 2: DisEqC msg repeat time */
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send standby fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
td_s32 uapi_frontend_diseqc_wakeup(td_u32 port, uapi_frontend_diseqc_level level)
{
td_s32 ret;
td_u8 framing;
uapi_frontend_diseqc_send_msg send_msg = {0};
uapi_frontend_diseqc_recv_msg recv_msg = {0};
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(DiSEqC level) invalid.\n");
soc_err_print_u32(level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
framing = (level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) ? MASTER_REPLY_FIRST : MASTER_NOREPLY_FIRST;
send_msg.level = level;
send_msg.tone_burst = UAPI_FRONTEND_SWITCH_TONEBURST_NONE;
format_diseqc_cmd(send_msg.msg, framing, DEVICE_ANY, CMD_POWER_ON);
send_msg.length = 3; /* 3: DisEqC msg length */
send_msg.repeat_times = 2; /* 2: DisEqC msg repeat time */
ret = diseqc_send_recv_message(port, &send_msg, &recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("Send power on fail.\n");
return ret;
}
soc_notice_func_exit();
return ret;
}
static td_s32 diseqc_send_22k(td_u32 port, td_bool status)
{
td_s32 ret;
fe_ioctrl_continuous_22k fe_tuner22k;
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
fe_tuner22k.port = port;
fe_tuner22k.continuous_22k = (td_u32)(status ? 1u : 0u);
ret = ext_mpi_frontend_send_continuous_22k(fe_tuner22k);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_send_continuous_22k, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 diseqc_stop_22k(td_u32 tuner_id)
{
td_s32 ret;
if (tuner_id >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(tuner_id) invalid.\n");
soc_err_print_u32(tuner_id);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
ret = diseqc_send_22k(tuner_id, TD_FALSE);
if (ret != TD_SUCCESS) {
soc_log_err("Stop 22K fail.\n");
return ret;
}
/* Save status */
return TD_SUCCESS;
}
td_s32 diseqc_resume_22k(td_u32 tuner_id)
{
sat_status *sat_para = NULL;
if (tuner_id >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(tuner_id) invalid.\n");
soc_err_print_u32(tuner_id);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
sat_para = sat_get_status(tuner_id);
if (sat_para == NULL) {
return SOC_ERR_FRONTEND_INVALID_PARA;
}
/* Resume */
if ((sat_para->switch_22k == UAPI_FRONTEND_SWITCH_22K_22) || /* save switch_22k */
(sat_para->lnb_22k == UAPI_FRONTEND_LNB_22K_ON)) { /* save lnb_22k */
return diseqc_send_22k(tuner_id, TD_TRUE);
} else {
return TD_SUCCESS;
}
}
td_s32 uapi_frontend_switch_22k(td_u32 port, uapi_frontend_switch_22k_sta status)
{
sat_status *sat_para = NULL;
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (!frontend_is_open(port)) {
soc_log_err("tuner not opened.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_NOT_OPEN;
}
if (port >= UAPI_FRONTEND_SWITCH_22K_MAX) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
sat_para = sat_get_status(port);
if (sat_para == NULL) {
return SOC_ERR_FRONTEND_INVALID_PARA;
}
/* Save */
sat_para->switch_22k = status;
if (port == UAPI_FRONTEND_SWITCH_22K_0) {
return diseqc_send_22k(port, TD_FALSE);
} else if (port == UAPI_FRONTEND_SWITCH_22K_22) {
return diseqc_send_22k(port, TD_TRUE);
} else {
return TD_SUCCESS;
}
}
td_s32 uapi_frontend_switch_0_12v(td_u32 port, uapi_frontend_switch_0_12v_sta status)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (!frontend_is_open(port)) {
soc_log_err("tuner not opened.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_NOT_OPEN;
}
if (status >= UAPI_FRONTEND_SWITCH_0_12V_MAX) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(status);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
static td_s32 tuner_switch_tone_burst_execute(td_u32 port, uapi_frontend_switch_tone_burst_sta status)
{
td_s32 ret;
fe_ioctrl_tone fe_tone;
sat_status *sat_para = NULL;
/* Save */
sat_para = sat_get_status(port);
if (sat_para == NULL) {
return SOC_ERR_FRONTEND_INVALID_PARA;
}
sat_para->tone_burst = status;
/* Send tone */
fe_tone.port = port;
if ((status == UAPI_FRONTEND_SWITCH_TONEBURST_0) ||
(status == UAPI_FRONTEND_SWITCH_TONEBURST_1)) {
fe_tone.tone = (td_u32)status - 1;
ret = diseqc_stop_22k(port);
if (ret != TD_SUCCESS) {
soc_log_err("Stop 22K fail.\n");
return ret;
}
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
ret = ext_mpi_frontend_send_tone(fe_tone);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_send_tone, ret);
return ret;
}
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
ret = diseqc_resume_22k(port);
if (ret != TD_SUCCESS) {
soc_log_err("Resume 22K fail.\n");
return ret;
}
}
return TD_SUCCESS;
}
td_s32 uapi_frontend_switch_tone_burst(td_u32 port, uapi_frontend_switch_tone_burst_sta status)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (!frontend_is_open(port)) {
soc_log_err("tuner not opened\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_NOT_OPEN;
}
if (status >= UAPI_FRONTEND_SWITCH_TONEBURST_MAX) {
soc_log_err("Input parameter(enStatus) invalid.\n");
soc_err_print_u32(status);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return tuner_switch_tone_burst_execute(port, status);
}
uapi_frontend_switch_tone_burst_sta diseqc_get_tone_burst_status(td_u32 tuner_id)
{
sat_status *sat_para = NULL;
if (tuner_id >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(tuner_id) invalid.\n");
soc_err_print_u32(tuner_id);
return UAPI_FRONTEND_SWITCH_TONEBURST_MAX;
}
sat_para = sat_get_status(tuner_id);
if (sat_para == NULL) {
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return sat_para->tone_burst;
}
static td_s32 diseqc_send_recv_message_valid(td_u32 port,
const uapi_frontend_diseqc_send_msg *send_msg,
uapi_frontend_diseqc_recv_msg *recv_msg)
{
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (!frontend_is_open(port)) {
soc_log_err("tuner not opened.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_NOT_OPEN;
}
if (send_msg == TD_NULL) {
soc_log_err("Input parameter(send_msg) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (recv_msg == TD_NULL) {
soc_log_warn("Input parameter(recv_msg) invalid.\n");
}
if (send_msg->level >= UAPI_FRONTEND_DISEQC_LEVEL_MAX) {
soc_log_err("Input parameter(send_msg->level) invalid.\n");
soc_err_print_u32(send_msg->level);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (send_msg->tone_burst >= UAPI_FRONTEND_SWITCH_TONEBURST_MAX) {
soc_log_err("Input parameter(send_msg->tone_burst) invalid.\n");
soc_err_print_u32(send_msg->tone_burst);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (send_msg->length > UAPI_DISEQC_MSG_MAX_LENGTH) {
soc_log_err("Input parameter(send_msg->length) invalid.\n");
soc_err_print_u32(send_msg->length);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (send_msg->repeat_times > UAPI_DISEQC_MAX_REPEAT_TIMES) {
soc_log_err("Input parameter(send_msg->repeat_times) invalid.\n");
soc_err_print_u32(send_msg->repeat_times);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
static td_s32 diseqc_send_message_config(td_u32 port,
const uapi_frontend_diseqc_send_msg *send_msg, td_bool *send_tone_flag, fe_ioctrl_tone *drv_tone)
{
/* Handle tone burst */
drv_tone->port = port;
switch (send_msg->tone_burst) {
case UAPI_FRONTEND_SWITCH_TONEBURST_NONE:
*send_tone_flag = TD_FALSE;
break;
case UAPI_FRONTEND_SWITCH_TONEBURST_0:
*send_tone_flag = TD_TRUE;
drv_tone->tone = 0;
break;
case UAPI_FRONTEND_SWITCH_TONEBURST_1:
*send_tone_flag = TD_TRUE;
drv_tone->tone = 1;
break;
default:
soc_log_err("Input parameter invalid!\n");
soc_err_print_u32(send_msg->tone_burst);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
return TD_SUCCESS;
}
static td_s32 diseqc_send_message(td_u32 port, const uapi_frontend_diseqc_send_msg *send_msg)
{
td_s32 ret;
td_bool send_tone_flag = TD_FALSE;
td_u32 repeat_times;
td_u32 repeat_time = 0;
fe_ioctrl_tone fe_tone = {0};
fe_ioctrl_diseqc_sendmsg drv_send_msg;
ret = diseqc_send_message_config(port, send_msg, &send_tone_flag, &fe_tone);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_send_message_config failed.\n");
return ret;
}
/* Send command */
drv_send_msg.port = port;
ret = memcpy_s(&drv_send_msg.send_msg, sizeof(ext_drv_frontend_diseqc_send_msg),
send_msg, sizeof(uapi_frontend_diseqc_send_msg));
if (ret != EOK) {
soc_log_err("call memcpy_s func error. sec_ret:%d\n", ret);
return SOC_ERR_FRONTEND_ERR_UNKNOWN;
}
repeat_times = send_msg->repeat_times;
for (;;) {
/* Handle repeat */
if (repeat_time == 1) {
drv_send_msg.send_msg.msg[0] += 1;
}
ret = ext_mpi_frontend_diseqc_send_message(drv_send_msg);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_diseqc_send_message, ret);
return ret;
}
/* After send command, delay 15ms */
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
/* Send tone */
if (send_tone_flag) {
ret = ext_mpi_frontend_send_tone(fe_tone);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_send_tone, ret);
return ret;
}
/* After send tone, delay 15ms */
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
}
if (repeat_times == 0) {
break;
}
repeat_times--;
repeat_time++;
}
return TD_SUCCESS;
}
static td_s32 diseqc_recv_message(td_u32 port,
const uapi_frontend_diseqc_send_msg *send_msg,
uapi_frontend_diseqc_recv_msg *recv_msg)
{
td_s32 ret;
fe_ioctrl_diseqc_recvmsg drv_recv_msg = {0};
drv_recv_msg.port = port;
if (recv_msg != TD_NULL) {
if (send_msg->level == UAPI_FRONTEND_DISEQC_LEVEL_2_X) {
ret = ext_mpi_frontend_diseqc_recv_message(&drv_recv_msg);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_diseqc_recv_message, ret);
return ret;
}
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
*(ext_drv_frontend_diseqc_recv_msg*)recv_msg = drv_recv_msg.recv_msg;
} else {
drv_recv_msg.recv_msg.status = EXT_DRV_FRONTEND_DISEQC_RECV_STATUS_UNSUPPORT;
drv_recv_msg.recv_msg.length = 0;
}
}
return TD_SUCCESS;
}
static td_s32 diseqc_enter_cmd_checking(td_u32 port,
const uapi_frontend_diseqc_send_msg *send_msg,
td_bool *unic_cmd_flag)
{
td_s32 ret;
fe_ioctrl_lnb_out lnb_out;
if ((send_msg->msg[2] == 0x5A) || (send_msg->msg[2] == 0x5B) || /* 2:index,0x5A,0x5B:unic cmd */
(send_msg->msg[2] == 0x5C) || (send_msg->msg[2] == 0x5D)) { /* 2:index,0x5C,0x5D:unic cmd */
/* unicable1 command */
*unic_cmd_flag = TD_TRUE;
} else if ((send_msg->msg[0] & 0xF0) == 0x70) { /* 0xF0:mask 0x70:unic cmd */
/* unicable2 command */
*unic_cmd_flag = TD_TRUE;
} else {
/* general diseqc command */
*unic_cmd_flag = TD_FALSE;
return TD_SUCCESS;
}
lnb_out.port = port;
lnb_out.out = FRONTEND_LNB_OUT_18V;
ret = ext_mpi_frontend_set_lnb_out(lnb_out);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_set_lnb_out, ret);
return SOC_ERR_FRONTEND_FAILED_LNBCTRL;
}
return TD_SUCCESS;
}
static td_s32 diseqc_exit_cmd_checking(td_u32 port, td_bool unic_cmd_flag)
{
td_s32 ret;
fe_ioctrl_lnb_out lnb_out;
if (unic_cmd_flag == TD_FALSE) {
return TD_SUCCESS;
}
lnb_out.port = port;
lnb_out.out = FRONTEND_LNB_OUT_13V;
ret = ext_mpi_frontend_set_lnb_out(lnb_out);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_frontend_set_lnb_out, ret);
return SOC_ERR_FRONTEND_FAILED_LNBCTRL;
}
return TD_SUCCESS;
}
td_s32 diseqc_send_recv_message(td_u32 tuner_id,
const uapi_frontend_diseqc_send_msg *send_msg,
uapi_frontend_diseqc_recv_msg *recv_msg)
{
td_s32 ret;
td_bool unic_cmd_flag;
ret = diseqc_send_recv_message_valid(tuner_id, send_msg, recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_send_recv_message_valid failed. ret: %d\n", ret);
return ret;
}
/* Stop continuous 22K */
ret = diseqc_stop_22k(tuner_id);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_stop_22k failed. ret: %d\n", ret);
return ret;
}
fe_usleep(DISEQC_DELAY_TIME_MS * 1000); /* 1000: unit, us */
ret = diseqc_enter_cmd_checking(tuner_id, send_msg, &unic_cmd_flag);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_enter_cmd_checking failed. ret: %d\n", ret);
return ret;
}
/* Send command */
ret = diseqc_send_message(tuner_id, send_msg);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_send_message failed. ret: %d\n", ret);
return ret;
}
/* Recv msessage */
ret = diseqc_recv_message(tuner_id, send_msg, recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_recv_message failed. ret: %d\n", ret);
return ret;
}
ret = diseqc_exit_cmd_checking(tuner_id, unic_cmd_flag);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_exit_cmd_checking failed. ret: %d\n", ret);
return ret;
}
/* Start continuous 22K */
ret = diseqc_resume_22k(tuner_id);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_resume_22k failed. ret: %d\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 uapi_frontend_diseqc_send_recv_message(td_u32 port,
const uapi_frontend_diseqc_send_msg *send_msg,
uapi_frontend_diseqc_recv_msg *recv_msg)
{
td_s32 ret;
soc_notice_func_enter();
if (port >= IAPI_TUNER_NUM) {
soc_log_err("Input parameter(port) invalid.\n");
soc_err_print_u32(port);
return SOC_ERR_FRONTEND_INVALID_PARA;
}
if (send_msg == TD_NULL) {
soc_log_err("Input parameter(send_msg) invalid.\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
if (recv_msg == TD_NULL) {
soc_log_warn("Input parameter(recv_msg) invalid\n");
}
ret = diseqc_send_recv_message(port, send_msg, recv_msg);
if (ret != TD_SUCCESS) {
soc_log_err("diseqc_send_recv_message fail.\n");
return ret;
}
soc_notice_func_exit();
return TD_SUCCESS;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */