/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2009-2021. All rights reserved. * Description : Frontend IAPI interface * Author : Hisilicon * Create : 2009/01/23 */ #include "iapi_frontend.h" #include "mpi_frontend_ext.h" #include "mpi_frontend.h" #include "securec.h" #include "soc_log.h" #include "soc_errno.h" #include "iapi_atv.h" #include "iapi_cab.h" #include "iapi_ter.h" #include "iapi_sat.h" static td_bool g_tuner_inited = TD_FALSE; static uapi_frontend_attr g_deft_tuner_attr[IAPI_TUNER_NUM]; td_bool g_tuner_opened[IAPI_TUNER_NUM] = {TD_FALSE}; td_bool frontend_is_open(td_u32 port) { if (port >= IAPI_TUNER_NUM) { return TD_FALSE; } return g_tuner_opened[port]; } inline static td_u8 frontend_highest_one_bit_position(td_u32 value) { td_u8 max_bit = 0; while (value != 0) { value >>= 1; ++max_bit; } return max_bit; } inline static td_bool frontend_u32_multiplication_is_safe(td_u32 multi_a, td_u32 multi_b) { td_u32 a_bits, b_bits; a_bits = frontend_highest_one_bit_position(multi_a); b_bits = frontend_highest_one_bit_position(multi_b); return (a_bits + b_bits <= 32); /* 32:sizeof(td_u32) */ } td_u32 frontend_u32_multiplication(td_u32 multi_a, td_u32 multi_b) { if (frontend_u32_multiplication_is_safe(multi_a, multi_b) == TD_TRUE) { return multi_a * multi_b; } else { soc_log_err("multiplication_overflow %u * %u.\n", multi_a, multi_b); return 0xffffffff; } } td_s32 uapi_frontend_init(td_void) { td_s32 ret; soc_notice_func_enter(); if (g_tuner_inited) { return TD_SUCCESS; } ret = ext_mpi_frontend_init(); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_init, ret); return ret; } g_deft_tuner_attr[0].sig_type = UAPI_FRONTEND_SIG_TYPE_DVB_C; /* 0:index */ g_deft_tuner_attr[1].sig_type = UAPI_FRONTEND_SIG_TYPE_DVB_C; /* 1:index */ g_deft_tuner_attr[2].sig_type = UAPI_FRONTEND_SIG_TYPE_DVB_C; /* 2:index */ ret = sat_init(); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(sat_init, ret); return ret; } g_tuner_inited = TD_TRUE; soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_deinit(td_void) { td_s32 ret; soc_notice_func_enter(); if (!g_tuner_inited) { return TD_SUCCESS; } ret = ext_mpi_frontend_deinit(); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_deinit, ret); return ret; } g_tuner_inited = TD_FALSE; soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_open(td_u32 port) { soc_notice_func_enter(); if (!g_tuner_inited) { soc_log_err("FRONTEND IAPI hasn't been Inited\n"); return SOC_ERR_FRONTEND_NOT_INIT; } 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 (g_tuner_opened[port]) { return TD_SUCCESS; } g_tuner_opened[port] = TD_TRUE; soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_close(td_u32 port) { soc_notice_func_enter(); if (!g_tuner_inited) { soc_log_err("FRONTEND IAPI hasn't been Inited\n"); return SOC_ERR_FRONTEND_NOT_INIT; } 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 (!g_tuner_opened[port]) { return TD_SUCCESS; } g_tuner_opened[port] = TD_FALSE; soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_get_def_attr(td_u32 port, uapi_frontend_attr *frontend_attr) { soc_notice_func_enter(); if (!g_tuner_inited) { soc_log_err("FRONTEND IAPI hasn't been Inited.\n"); return SOC_ERR_FRONTEND_NOT_INIT; } 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_attr == TD_NULL) { soc_log_err("Input parameter(tuner_attr) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } *frontend_attr = g_deft_tuner_attr[port]; soc_notice_func_exit(); return TD_SUCCESS; } td_s32 iapi_frontend_get_cfg(td_u32 tuner_id, iapi_frontend_cfg *fe_cfg) { td_s32 ret; fe_ioctrl_config tmp_fe_cfg = {0}; if (fe_cfg == TD_NULL) { soc_log_err("Input parameter(fe_cfg) is TD_NULL.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } tmp_fe_cfg.port = tuner_id; ret = mpi_frontend_get_cfg(&tmp_fe_cfg); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(mpi_frontend_get_cfg, ret); return ret; } fe_cfg->demod_type = (iapi_demod_dev_type)tmp_fe_cfg.demod_type; fe_cfg->tuner_type = (iapi_tuner_dev_type)tmp_fe_cfg.tuner_type; fe_cfg->lnb_type = (iapi_lnb_ctrl_dev_type)tmp_fe_cfg.lnb_type; return TD_SUCCESS; } static td_s32 tuner_set_attr_valid(td_u32 tuner_id, const uapi_frontend_attr *iapi_tuner_attr) { if (tuner_id >= IAPI_TUNER_NUM) { soc_log_err("Input parameter(tuner_id:%d) invalid.\n", tuner_id); return SOC_ERR_FRONTEND_INVALID_PARA; } switch (iapi_tuner_attr->sig_type) { case UAPI_FRONTEND_SIG_TYPE_DVB_C: case UAPI_FRONTEND_SIG_TYPE_DVB_C2: case UAPI_FRONTEND_SIG_TYPE_ISDB_C: case UAPI_FRONTEND_SIG_TYPE_J83B: case UAPI_FRONTEND_SIG_TYPE_DVB_S: case UAPI_FRONTEND_SIG_TYPE_DVB_S2: case UAPI_FRONTEND_SIG_TYPE_DVB_S2X: case UAPI_FRONTEND_SIG_TYPE_ISDB_S: case UAPI_FRONTEND_SIG_TYPE_ISDB_S3: case UAPI_FRONTEND_SIG_TYPE_DVB_T: case UAPI_FRONTEND_SIG_TYPE_DVB_T2: case UAPI_FRONTEND_SIG_TYPE_ISDB_T: case UAPI_FRONTEND_SIG_TYPE_ATSC_T: case UAPI_FRONTEND_SIG_TYPE_ATSC_T3: case UAPI_FRONTEND_SIG_TYPE_DTMB: case UAPI_FRONTEND_SIG_TYPE_ATV: { break; } default: { soc_log_err("Input parameter(tuner_attr) invalid.\n"); soc_err_print_u32(iapi_tuner_attr->sig_type); return SOC_ERR_FRONTEND_INVALID_PARA; } } return TD_SUCCESS; } td_s32 uapi_frontend_set_attr(td_u32 port, const uapi_frontend_attr *frontend_attr) { td_s32 ret; fe_ioctrl_attr tmp_tuner_attr; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (frontend_attr == TD_NULL) { soc_log_err("Input parameter(tuner_attr)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } ret = tuner_set_attr_valid(port, frontend_attr); if (ret != TD_SUCCESS) { soc_log_err("tuner_set_attr_valid failed.\n"); return ret; } tmp_tuner_attr.port = port; tmp_tuner_attr.sig_type = (ext_drv_frontend_sig_type)frontend_attr->sig_type; ret = ext_mpi_frontend_set_attr(tmp_tuner_attr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_set_attr, ret); return ret; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_clear_attr(td_u32 port) { td_s32 ret; soc_notice_func_enter(); if (port >= IAPI_TUNER_NUM) { soc_log_err("Input parameter(port:%d) invalid.\n", port); return SOC_ERR_FRONTEND_INVALID_PARA; } ret = ext_mpi_frontend_close(port); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_close, ret); return ret; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 tuner_get_attr_execute(td_u32 tuner_id, uapi_frontend_attr *iapi_tuner_attr) { td_s32 ret; fe_ioctrl_attr fe_attr = {0}; if (iapi_tuner_attr == TD_NULL) { soc_log_err("Input parameter(tuner_attr)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_attr.port = tuner_id; ret = ext_mpi_frontend_get_attr(&fe_attr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_attr, ret); return ret; } iapi_tuner_attr->sig_type = (uapi_frontend_sig_type)fe_attr.sig_type; soc_dbg_print_u32(iapi_tuner_attr->sig_type); return TD_SUCCESS; } td_s32 uapi_frontend_get_attr(td_u32 port, uapi_frontend_attr *frontend_attr) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (frontend_attr == TD_NULL) { soc_log_err("Input parameter(tuner_attr)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } ret = tuner_get_attr_execute(port, frontend_attr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_get_attr_execute, ret); } soc_dbg_print_u32(frontend_attr->sig_type); soc_notice_func_exit(); return ret; } td_s32 uapi_frontend_get_capability(uapi_frontend_capability *cap) { td_s32 ret; fe_ioctrl_capability capability = {0}; soc_notice_func_enter(); if (!g_tuner_inited) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (cap == TD_NULL) { soc_log_err("Input parameter(cap)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } ret = ext_mpi_frontend_get_capability(&capability); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_capability, ret); return ret; } ret = memcpy_s(cap, sizeof(uapi_frontend_capability), &capability, sizeof(fe_ioctrl_capability)); if (ret != TD_SUCCESS) { soc_log_err("memcpy_s fail.\n"); return SOC_ERR_FRONTEND_SECURE_CHECK; } soc_notice_func_exit(); return TD_SUCCESS; } static td_s32 tuner_get_get_default_timeout_execute(td_u32 tuner_id, const uapi_frontend_connect_para *iapi_connect_para, td_u32 *time_out) { td_s32 ret; if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_C) { *time_out = 1000; /* 1000: time out */ } else if ((iapi_connect_para->sig_type >= UAPI_FRONTEND_SIG_TYPE_DVB_S) && (iapi_connect_para->sig_type <= UAPI_FRONTEND_SIG_TYPE_DVB_S2X)) { ret = sat_get_default_timeout(tuner_id, iapi_connect_para, time_out); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(sat_get_default_timeout, ret); return ret; } } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_T) { *time_out = 500; /* 500: time out */ } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_T2) { *time_out = 1500; /* 1500: time out */ } else if (iapi_connect_para->sig_type == (UAPI_FRONTEND_SIG_TYPE_DVB_T | UAPI_FRONTEND_SIG_TYPE_DVB_T2)) { *time_out = 2000; /* 2000: time out */ } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_ISDB_T) { *time_out = 3000; /* 3000: time out */ } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_ATSC_T) { *time_out = 1500; /* 1500: time out */ } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_DTMB) { *time_out = 2000; /* 2000: time out */ } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_J83B || iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_ISDB_C) { *time_out = 500; /* 500: time out */ } else { *time_out = 2000; /* 2000: time out */ } return TD_SUCCESS; } td_s32 uapi_frontend_get_default_time_out(td_u32 port, const uapi_frontend_connect_para *connect_para, td_u32 *time_out_ms) { 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 (connect_para == TD_NULL) { soc_log_err("Input parameter(connect_para) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } if (time_out_ms == TD_NULL) { soc_log_err("Input parameter(time_out) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } ret = tuner_get_get_default_timeout_execute(port, connect_para, time_out_ms); if (ret != TD_SUCCESS) { soc_log_err("tuner_get_get_default_timeout_execute failed. ret = %d\n", ret); return TD_FAILURE; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 tuner_connect_sig_type(td_u32 port, const uapi_frontend_connect_para *iapi_connect_para, td_u32 time_out) { td_s32 ret; if (iapi_connect_para == TD_NULL) { soc_log_err("Input parameter(iapi_connect_para) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } if ((iapi_connect_para->sig_type >= UAPI_FRONTEND_SIG_TYPE_DVB_C) && (iapi_connect_para->sig_type <= UAPI_FRONTEND_SIG_TYPE_J83B)) { /* Cable */ ret = cab_connect(port, iapi_connect_para, time_out); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(cab_connect, ret); return ret; } } else if ((iapi_connect_para->sig_type >= UAPI_FRONTEND_SIG_TYPE_DVB_S) && (iapi_connect_para->sig_type <= UAPI_FRONTEND_SIG_TYPE_ABSS)) { /* Satellite */ ret = sat_connect(port, iapi_connect_para, time_out); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(sat_connect, ret); return ret; } } else if (iapi_connect_para->sig_type == (UAPI_FRONTEND_SIG_TYPE_DVB_T | UAPI_FRONTEND_SIG_TYPE_DVB_T2)) { ret = ter_connect_t_t2_auto(port, iapi_connect_para, time_out); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ter_connect_t_t2_auto, ret); return ret; } } else if (iapi_connect_para->sig_type == UAPI_FRONTEND_SIG_TYPE_ATV) { ret = atv_connect(port, iapi_connect_para); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(atv_connect, ret); return ret; } } else if (iapi_connect_para->sig_type < UAPI_FRONTEND_SIG_TYPE_MAX) { /* Terrestrial, Other */ ret = ter_connect(port, iapi_connect_para, time_out); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ter_connect, ret); return ret; } } else { soc_log_err("Error signal type!\n"); soc_err_print_u32(iapi_connect_para->sig_type); return SOC_ERR_FRONTEND_INVALID_PARA; } return TD_SUCCESS; } td_s32 uapi_frontend_connect(td_u32 port, const uapi_frontend_connect_para *connect_para, td_u32 timeout) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (connect_para == TD_NULL) { soc_log_err("Input parameter(connect_para) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } ret = tuner_connect_sig_type(port, connect_para, timeout); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_connect_sig_type, ret); return ret; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_disconnect(td_u32 port) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } ret = ext_mpi_frontend_disconnect(port); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_disconnect, ret); return ret; } soc_notice_func_exit(); return ret; } td_s32 uapi_frontend_quick_switch_signal(td_u32 port, uapi_frontend_sig_type sig_type) { if (port >= IAPI_TUNER_NUM) { soc_log_err("Input parameter(port:%u) invalid.\n", port); return SOC_ERR_FRONTEND_INVALID_PARA; } if (sig_type >= UAPI_FRONTEND_SIG_TYPE_MAX) { soc_log_err("sig_type:%u is out of bound:%u\n", sig_type, UAPI_FRONTEND_SIG_TYPE_MAX); return SOC_ERR_FRONTEND_INVALID_PARA; } return TD_SUCCESS; } td_s32 uapi_frontend_get_status(td_u32 port, uapi_frontend_lock_status *lock_status) { td_s32 ret; fe_ioctrl_status fe_status = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (lock_status == TD_NULL) { soc_log_err("Input parameter(tuner_status) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_status.port = port; fe_status.lock_status = EXT_DRV_FRONTEND_LOCK_STATUS_DROPPED; ret = ext_mpi_frontend_get_status(&fe_status); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_status, ret); return ret; } *lock_status = (uapi_frontend_lock_status)fe_status.lock_status; soc_log_trace("lock_status:%u\n", *lock_status); return TD_SUCCESS; } td_s32 uapi_frontend_get_ber(td_u32 port, uapi_frontend_scientific_num *ber) { td_s32 ret; fe_ioctrl_ber_per fe_ber = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (ber == TD_NULL) { soc_log_err("Input parameter(ber)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_ber.port = port; ret = ext_mpi_frontend_get_ber(&fe_ber); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_ber, ret); return ret; } ber->integer_val = fe_ber.num.integer_val; ber->decimal_val = fe_ber.num.decimal_val; ber->power = fe_ber.num.power; soc_log_info("ber:%u.%u*10^%u\n", ber->integer_val, ber->decimal_val, ber->power); return TD_SUCCESS; } td_s32 uapi_frontend_get_per(td_u32 port, uapi_frontend_scientific_num *per) { td_s32 ret; fe_ioctrl_ber_per fe_per = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (per == TD_NULL) { soc_log_err("Input parameter(per)invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_per.port = port; ret = ext_mpi_frontend_get_per(&fe_per); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_per, ret); return ret; } per->integer_val = fe_per.num.integer_val; per->decimal_val = fe_per.num.decimal_val; per->power = fe_per.num.power; soc_log_info("per:%u.%u*10^%u\n", per->integer_val, per->decimal_val, per->power); return TD_SUCCESS; } td_s32 uapi_frontend_get_snr(td_u32 port, uapi_frontend_integer_decimal *snr) /* range : 0-255 */ { td_s32 ret; fe_ioctrl_snr fe_snr; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (snr == TD_NULL) { soc_log_err("Input parameter(snr) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_snr.port = port; fe_snr.snr = 0; ret = ext_mpi_frontend_get_snr(&fe_snr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_snr, ret); return ret; } snr->integer_val = (td_s16)fe_snr.snr / 100; /* 100:for integer value */ snr->decimal_val = (td_s16)fe_snr.snr % 100; /* 100:for decimal value */ soc_log_info("snr:%u.%u\n", snr->integer_val, snr->decimal_val); return TD_SUCCESS; } td_s32 uapi_frontend_get_signal_strength(td_u32 port, td_u32 *signal_strength) { td_s32 ret; fe_ioctrl_data_buf fe_strength = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (signal_strength == TD_NULL) { soc_log_err("Input parameter(signal_strength) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_strength.port = port; ret = ext_mpi_frontend_get_signal_strength(&fe_strength); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_signal_strength, ret); return ret; } *signal_strength = fe_strength.data_buf[1]; soc_log_info("signal_strength:%u\n", *signal_strength); return TD_SUCCESS; } static td_s32 tuner_get_signal_quality_snr_ber(td_u32 tuner_id, td_double *snr, td_double *ber) { td_s32 ret, i; td_double ber_tmp; fe_ioctrl_snr fe_snr = {0}; fe_ioctrl_ber_per fe_ber = {0}; fe_snr.port = tuner_id; fe_snr.snr = 0; ret = ext_mpi_frontend_get_snr(&fe_snr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_snr, ret); return ret; } *snr = fe_snr.snr / 100.0; /* 100.0:uint dB */ fe_ber.port = tuner_id; ret = ext_mpi_frontend_get_ber(&fe_ber); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_ber, ret); return ret; } ber_tmp = fe_ber.num.integer_val + fe_ber.num.decimal_val / 1000.0; /* 1000.0:ber decimal */ for (i = 0; i < -fe_ber.num.power; i++) { ber_tmp /= 10; /* 10:power */ } *ber = ber_tmp; return TD_SUCCESS; } static td_s32 tuner_get_signal_quality_execute(td_u32 tuner_id, td_u32 *signal_quality) { td_s32 ret; td_double snr = 0; td_double ber = 0; uapi_frontend_attr iapi_tuner_attr = {0}; ret = tuner_get_signal_quality_snr_ber(tuner_id, &snr, &ber); if (ret == SOC_ERR_FRONTEND_CONNECT_FAIL) { soc_log_info("Signal not connect.\n"); return ret; } else if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_get_signal_quality_snr_ber, ret); return ret; } ret = tuner_get_attr_execute(tuner_id, &iapi_tuner_attr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_get_attr_execute, ret); return ret; } if ((iapi_tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_S) || (iapi_tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_S2)) { /* For SAT */ ret = sat_get_signal_quality(tuner_id, snr, signal_quality); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(sat_get_signal_quality, ret); return ret; } } else if ((iapi_tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_DVB_C) || (iapi_tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_J83B) || (iapi_tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_ISDB_C)) { /* For CAB */ ret = cab_get_signal_quality(tuner_id, snr, ber, signal_quality); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(cab_get_signal_quality, ret); return ret; } } else if ((iapi_tuner_attr.sig_type >= UAPI_FRONTEND_SIG_TYPE_DVB_T) && (iapi_tuner_attr.sig_type <= UAPI_FRONTEND_SIG_TYPE_DTMB)) { /* For TER */ ret = ter_get_signal_quality(tuner_id, snr, ber, signal_quality); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ter_get_signal_quality, ret); return ret; } } else { *signal_quality = 0; return SOC_ERR_FRONTEND_INVALID_PARA; } return TD_SUCCESS; } td_s32 uapi_frontend_get_signal_quality(td_u32 port, td_u32 *signal_quality) { td_s32 ret; fe_ioctrl_data fe_strength = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (signal_quality == TD_NULL) { soc_log_err("Input parameter(signal_quality) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_strength.port = port; ret = ext_mpi_frontend_get_signal_quality(&fe_strength); if (ret == SOC_ERR_FRONTEND_INVALID_FUNCTION) { ret = tuner_get_signal_quality_execute(port, signal_quality); if (ret == SOC_ERR_FRONTEND_CONNECT_FAIL) { soc_log_warn("Signal not connect.\n"); *signal_quality = 0; return ret; } else if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_get_signal_quality_execute, ret); *signal_quality = 0; return ret; } } else if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_signal_quality, ret); *signal_quality = 0; return ret; } else { *signal_quality = fe_strength.data; } soc_info_print_u32(*signal_quality); return TD_SUCCESS; } td_s32 uapi_frontend_get_real_freq_symb(td_u32 port, td_u32 *freq, td_u32 *symb) { td_s32 ret; fe_ioctrl_data_buf fe_freq_symb = {0}; uapi_frontend_attr tuner_attr = {0}; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (freq == TD_NULL) { soc_log_err("Input parameter(freq) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } if (symb == TD_NULL) { soc_log_err("Input parameter(symb) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_freq_symb.port = port; ret = ext_mpi_frontend_get_real_freq_symb(&fe_freq_symb); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_real_freq_symb, ret); return ret; } ret = tuner_get_attr_execute(port, &tuner_attr); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(tuner_get_attr_execute, ret); return TD_FAILURE; } if (tuner_attr.sig_type == UAPI_FRONTEND_SIG_TYPE_ATV) { *freq = 0; *symb = 0; } else { *freq = fe_freq_symb.data_buf[0]; *symb = fe_freq_symb.data_buf[1]; } return TD_SUCCESS; } /* Obtains current signal information of the TUNER, used in satellite and terrestrial, not necessary for cable */ td_s32 uapi_frontend_get_signal_info(td_u32 port, uapi_frontend_signal_info *signal_info) { td_s32 ret; fe_ioctrl_signal_info fe_signal_info; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (signal_info == TD_NULL) { soc_log_err("Input parameter(signal_info) invalid.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } fe_signal_info.port = port; ret = ext_mpi_frontend_get_signal_info(&fe_signal_info); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_get_signal_info, ret); return ret; } *(ext_drv_frontend_signal_info*)signal_info = fe_signal_info.info; return TD_SUCCESS; } td_s32 uapi_frontend_set_antenna_power(td_u32 port, uapi_frontend_ter_antenna_power power) { td_s32 ret = TD_SUCCESS; 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (power >= UAPI_FRONTEND_TER_ANTENNA_POWER_MAX) { soc_log_err("power:%u is out of bound:%u\n", power, UAPI_FRONTEND_TER_ANTENNA_POWER_MAX); return SOC_ERR_FRONTEND_INVALID_PARA; } return ret; } td_s32 uapi_frontend_standby(td_u32 port) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } ret = ext_mpi_frontend_standby(port); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_standby, ret); return ret; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_wake_up(td_u32 port) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } ret = ext_mpi_frontend_wake_up(port); if (ret != TD_SUCCESS) { soc_err_print_call_fun_err(ext_mpi_frontend_wake_up, ret); return ret; } soc_notice_func_exit(); return TD_SUCCESS; } td_s32 uapi_frontend_get_constellation_data(td_u32 port, uapi_frontend_sample_data_len data_len, uapi_frontend_sample_data *data) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (data == TD_NULL) { soc_log_err("ps32Data is NULL.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } if (data_len >= UAPI_FRONTEND_SAMPLE_DATA_LEN_MAX) { soc_log_err("Input parameter(sample_data_len) invalid.\n"); soc_err_print_u32(data_len); return SOC_ERR_FRONTEND_INVALID_PARA; } return TD_SUCCESS; } td_s32 uapi_frontend_get_spectrum_data(td_u32 port, uapi_frontend_sample_data_len data_len, td_u32 *data) { 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 (!g_tuner_opened[port]) { soc_log_err("tuner not opened.\n"); return SOC_ERR_FRONTEND_NOT_OPEN; } if (data == TD_NULL) { soc_log_err("data is NULL.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } if (data_len >= UAPI_FRONTEND_SAMPLE_DATA_LEN_MAX) { soc_log_err("Input parameter(sample_data_len) invalid.\n"); soc_err_print_u32(data_len); return SOC_ERR_FRONTEND_INVALID_PARA; } return TD_SUCCESS; } td_s32 uapi_frontend_get_tuner_power_spectrum(td_u32 port, const uapi_tuner_spectrum_para *para) { if (port >= IAPI_TUNER_NUM) { soc_log_err("Input parameter(port:%d) invalid.\n", port); return SOC_ERR_FRONTEND_INVALID_PARA; } if (para == TD_NULL) { soc_log_err("Input parameter(para) is TD_NULL.\n"); return SOC_ERR_FRONTEND_INVALID_POINT; } return TD_SUCCESS; }