/* * 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 #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 */ 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 */