3.2. 数字电视前端 kABI¶
3.2.1. 数字电视前端¶
数字电视前端 kABI 定义了一个驱动程序内部接口,用于将低级、硬件特定的驱动程序注册到与硬件无关的前端层。它仅对数字电视设备驱动程序编写者感兴趣。此 API 的头文件名为 dvb_frontend.h
,位于 include/media/
中。
3.2.1.1. 解调器驱动程序¶
解调器驱动程序负责与硬件的解码部分进行通信。此类驱动程序应实现 dvb_frontend_ops
,该结构体定义了支持的数字电视标准类型,并指向一系列函数,允许 DVB 核心通过 include/media/dvb_frontend.c
下的代码来命令硬件。
驱动程序 foo
中此类结构体的典型示例是
static struct dvb_frontend_ops foo_ops = {
.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
.info = {
.name = "foo DVB-T/T2/C driver",
.caps = FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 |
FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 |
FE_CAN_FEC_7_8 |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_QAM_16 |
FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO |
FE_CAN_MUTE_TS |
FE_CAN_2G_MODULATION,
.frequency_min = 42000000, /* Hz */
.frequency_max = 1002000000, /* Hz */
.symbol_rate_min = 870000,
.symbol_rate_max = 11700000
},
.init = foo_init,
.sleep = foo_sleep,
.release = foo_release,
.set_frontend = foo_set_frontend,
.get_frontend = foo_get_frontend,
.read_status = foo_get_status_and_stats,
.tune = foo_tune,
.i2c_gate_ctrl = foo_i2c_gate_ctrl,
.get_frontend_algo = foo_get_algo,
};
驱动程序 bar
中此类结构体的典型示例(旨在用于卫星电视接收)是
static const struct dvb_frontend_ops bar_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2 },
.info = {
.name = "Bar DVB-S/S2 demodulator",
.frequency_min = 500000, /* KHz */
.frequency_max = 2500000, /* KHz */
.frequency_stepsize = 0,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.symbol_rate_tolerance = 500,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK,
},
.init = bar_init,
.sleep = bar_sleep,
.release = bar_release,
.set_frontend = bar_set_frontend,
.get_frontend = bar_get_frontend,
.read_status = bar_get_status_and_stats,
.i2c_gate_ctrl = bar_i2c_gate_ctrl,
.get_frontend_algo = bar_get_algo,
.tune = bar_tune,
/* Satellite-specific */
.diseqc_send_master_cmd = bar_send_diseqc_msg,
.diseqc_send_burst = bar_send_burst,
.set_tone = bar_set_tone,
.set_voltage = bar_set_voltage,
};
注意
对于卫星数字电视标准(DVB-S、DVB-S2、ISDB-S),频率以 kHz 为单位指定,而对于地面和有线标准,频率以 Hz 为单位指定。因此,如果同一个前端支持这两种类型,则需要有两个单独的
dvb_frontend_ops
结构,每种标准一个。仅当硬件允许控制 I2C 门(直接或通过某些 GPIO 引脚)时才存在
.i2c_gate_ctrl
字段,以便在调谐频道后从 I2C 总线上移除调谐器。所有新驱动程序都应通过
.read_status
实现 DVBv5 统计信息。但是,有许多回调函数用于获取信号强度、S/N 和 UCB 的统计信息。这些回调函数用于提供与不支持 DVBv5 API 的旧应用程序的向后兼容性。实现这些回调是可选的。在所有现有驱动程序都支持 DVBv5 统计信息后,这些回调可能会在将来被删除。为了控制 LNBf 和 DiSEqC,卫星电视标准需要其他回调函数:
.diseqc_send_master_cmd
、.diseqc_send_burst
、.set_tone
、.set_voltage
。
include/media/dvb_frontend.c
有一个内核线程,负责调谐设备。它支持多种算法来检测频道,如枚举 dvbfe_algo()
中定义的那样。
要使用的算法通过 .get_frontend_algo
获取。如果驱动程序没有在 struct dvb_frontend_ops
中填写该字段,则默认使用 DVBFE_ALGO_SW
,这意味着 dvb-core 在调谐时会进行之字形扫描,例如,它会首先尝试使用指定的中心频率 f
,然后,它会进行 f
+ Δ、f
- Δ、f
+ 2 x Δ、f
- 2 x Δ 等等。
如果硬件内部有某种之字形算法,则应定义一个 .get_frontend_algo
函数,该函数将返回 DVBFE_ALGO_HW
。
注意
核心前端支持还支持第三种类型 (DVBFE_ALGO_CUSTOM
),以便允许驱动程序定义其自己的硬件辅助算法。现在很少有硬件需要使用它。使用 DVBFE_ALGO_CUSTOM
需要在 struct dvb_frontend_ops
中提供其他函数回调。
3.2.1.2. 将前端驱动程序附加到桥接驱动程序¶
在使用数字电视前端核心之前,桥接驱动程序应附加前端解调器、调谐器和 SEC 设备,并调用 dvb_register_frontend()
,以便在子系统注册新的前端。在设备分离/移除时,桥接驱动程序应调用 dvb_unregister_frontend()
以从核心中移除前端,然后调用 dvb_frontend_detach()
以释放前端驱动程序分配的内存。
驱动程序还应在其 device_driver
.suspend()
的处理程序中调用 dvb_frontend_suspend()
,并在其 device_driver
.resume()
的处理程序中调用 dvb_frontend_resume()
。
还提供了一些其他可选函数来处理一些特殊情况。
3.2.2. 数字电视前端统计信息¶
3.2.2.1. 简介¶
数字电视前端提供了一系列 统计信息,旨在帮助调谐设备并测量服务质量。
对于每个统计测量,驱动程序应设置所用标度的类型,或者如果给定时间统计数据不可用,则设置为 FE_SCALE_NOT_AVAILABLE
。驱动程序还应提供每种类型的统计数据数量。对于大多数视频标准,通常为 1 [1]。
驱动程序应在其初始化代码中初始化每个统计计数器的长度和标度。例如,如果前端提供信号强度,则其初始化代码应如下:
struct dtv_frontend_properties *c = &state->fe.dtv_property_cache;
c->strength.len = 1;
c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
并且,当统计数据更新时,设置标度:
c->strength.stat[0].scale = FE_SCALE_DECIBEL;
c->strength.stat[0].uvalue = strength;
注意
对于信号强度和 CNR 测量,请优先使用 FE_SCALE_DECIBEL
而不是 FE_SCALE_RELATIVE
。
3.2.2.2. 统计数据组¶
目前支持以下几个统计数据组:
- 信号强度 (DTV_STAT_SIGNAL_STRENGTH)
测量调谐器或解调器模拟部分的信号强度级别。
通常从应用于调谐器和/或前端的增益中获得,以检测载波。当未检测到载波时,增益处于最大值(因此,强度处于最小值)。
由于增益可通过调整增益的寄存器集看到,因此通常情况下,此统计数据始终可用 [2]。
驱动程序应尝试始终使其可用,因为这些统计数据可用于调整天线位置和检查电缆故障。
[2] 在少数设备上,如果没有载波,增益会持续浮动。在这些设备上,强度报告应首先检查是否在调谐器上检测到载波(
FE_HAS_CARRIER
,请参阅fe_status
),否则返回可能的最低值。- 载波信噪比 (DTV_STAT_CNR)
- 后 FEC 的比特计数 (DTV_STAT_POST_ERROR_BIT_COUNT 和 DTV_STAT_POST_TOTAL_BIT_COUNT)
这些计数器测量内部编码块(在 Viterbi、LDPC 或其他内部代码之后)前向纠错 (FEC) 之后的比特数和比特错误数。
由于其性质,这些统计数据取决于完全编码锁定(例如,在
FE_HAS_SYNC
或FE_HAS_LOCK
之后,请参阅fe_status
)。
- 前 FEC 的比特计数 (DTV_STAT_PRE_ERROR_BIT_COUNT 和 DTV_STAT_PRE_TOTAL_BIT_COUNT)
这些计数器测量内部编码块(在 Viterbi、LDPC 或其他内部代码之前)前向纠错 (FEC) 之前的比特数和比特错误数。
并非所有前端都提供此类统计数据。
由于其性质,这些统计数据取决于内部编码锁定(例如,在
FE_HAS_VITERBI
之后,请参阅fe_status
)。
- 块计数 (DTV_STAT_ERROR_BLOCK_COUNT 和 DTV-STAT_TOTAL_BLOCK_COUNT)
这些计数器测量内部编码块(在 Viterbi、LDPC 或其他内部代码之前)前向纠错 (FEC) 之后的块数和块错误数。
由于其性质,这些统计数据取决于完全编码锁定(例如,在
FE_HAS_SYNC
或FE_HAS_LOCK
之后,请参阅fe_status
)。
注意
所有计数器都应从硬件收集时单调递增。
处理状态和统计数据的典型逻辑示例是:
static int foo_get_status_and_stats(struct dvb_frontend *fe)
{
struct foo_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc;
enum fe_status *status;
/* Both status and strength are always available */
rc = foo_read_status(fe, &status);
if (rc < 0)
return rc;
rc = foo_read_strength(fe);
if (rc < 0)
return rc;
/* Check if CNR is available */
if (!(fe->status & FE_HAS_CARRIER))
return 0;
rc = foo_read_cnr(fe);
if (rc < 0)
return rc;
/* Check if pre-BER stats are available */
if (!(fe->status & FE_HAS_VITERBI))
return 0;
rc = foo_get_pre_ber(fe);
if (rc < 0)
return rc;
/* Check if post-BER stats are available */
if (!(fe->status & FE_HAS_SYNC))
return 0;
rc = foo_get_post_ber(fe);
if (rc < 0)
return rc;
}
static const struct dvb_frontend_ops ops = {
/* ... */
.read_status = foo_get_status_and_stats,
};
3.2.2.3. 统计数据收集¶
在几乎所有前端硬件上,比特计数和字节计数都由硬件存储,经过一定时间或在总比特/块计数器达到某个值(通常是可编程的)之后,例如,每 1000 毫秒或在接收到 1,000,000 个比特之后。
因此,如果您过早读取寄存器,您最终会读取与上次读取相同的值,导致单调值增加过于频繁。
驱动程序应负责避免过于频繁的读取。这可以通过两种方法完成:
3.2.2.3.1. 如果驱动程序有一个指示何时准备好收集数据的比特¶
驱动程序应在使统计数据可用之前检查该比特。
此行为的一个示例可以在此代码片段中找到(改编自 mb86a20s 驱动程序的逻辑):
static int foo_get_pre_ber(struct dvb_frontend *fe)
{
struct foo_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc, bit_error;
/* Check if the BER measures are already available */
rc = foo_read_u8(state, 0x54);
if (rc < 0)
return rc;
if (!rc)
return 0;
/* Read Bit Error Count */
bit_error = foo_read_u32(state, 0x55);
if (bit_error < 0)
return bit_error;
/* Read Total Bit Count */
rc = foo_read_u32(state, 0x51);
if (rc < 0)
return rc;
c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[0].uvalue += bit_error;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[0].uvalue += rc;
return 0;
}
3.2.2.3.2. 如果驱动程序不提供统计数据可用性检查比特¶
但是,少数设备可能不提供检查统计数据是否可用的方法(或检查方式未知)。它们甚至可能不提供直接读取比特或块总数的方法。
在这些设备上,驱动程序需要确保它不会过于频繁地从寄存器读取和/或估计比特/块的总数。
在这样的驱动程序上,获取统计数据的典型例程将如下所示(改编自 dib8000 驱动程序的逻辑):
struct foo_state {
/* ... */
unsigned long per_jiffies_stats;
}
static int foo_get_pre_ber(struct dvb_frontend *fe)
{
struct foo_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc, bit_error;
u64 bits;
/* Check if time for stats was elapsed */
if (!time_after(jiffies, state->per_jiffies_stats))
return 0;
/* Next stat should be collected in 1000 ms */
state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
/* Read Bit Error Count */
bit_error = foo_read_u32(state, 0x55);
if (bit_error < 0)
return bit_error;
/*
* On this particular frontend, there's no register that
* would provide the number of bits per 1000ms sample. So,
* some function would calculate it based on DTV properties
*/
bits = get_number_of_bits_per_1000ms(fe);
c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[0].uvalue += bit_error;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[0].uvalue += bits;
return 0;
}
请注意,在这两种情况下,我们都使用 dvb_frontend_ops
.read_status
回调来获取统计数据。理由是前端核心将自动定期调用此函数(通常,当前端锁定时,每秒 3 次)。
这保证了我们不会错过收集计数器并在正确的时间增加单调统计数据。
3.2.3. 数字电视前端函数和类型¶
-
struct dvb_frontend_tune_settings¶
用于调整前端调谐的参数
定义:
struct dvb_frontend_tune_settings {
int min_delay_ms;
int step_size;
int max_drift;
};
成员
min_delay_ms
调谐的最小延迟,以毫秒为单位
step_size
两个连续频率之间的步长
max_drift
最大漂移
注意
step_size 以赫兹 (Hz) 为单位(用于地面/有线电视),或者以千赫 (kHz) 为单位(用于卫星电视)
-
struct dvb_tuner_info¶
前端名称和最小/最大范围/带宽
定义:
struct dvb_tuner_info {
char name[128];
u32 frequency_min_hz;
u32 frequency_max_hz;
u32 frequency_step_hz;
u32 bandwidth_min;
u32 bandwidth_max;
u32 bandwidth_step;
};
成员
name
前端的名称
frequency_min_hz
支持的最小频率,以赫兹为单位
frequency_max_hz
支持的最大频率,以赫兹为单位
frequency_step_hz
频率步长,以赫兹为单位
bandwidth_min
支持的最小前端带宽
bandwidth_max
支持的最大前端带宽
bandwidth_step
前端带宽步长
-
struct analog_parameters¶
用于调谐到模拟/无线电信道的参数
定义:
struct analog_parameters {
unsigned int frequency;
unsigned int mode;
unsigned int audmode;
u64 std;
};
成员
frequency
模拟电视调谐器使用的频率(对于电视,以 62.5 kHz 为步长;对于无线电,以 62.5 Hz 为步长)
mode
调谐器模式,如枚举 v4l2_tuner_type 中定义
audmode
音频模式,如 videodev2.h 中的 rxsubchans 字段所定义,例如 V4L2_TUNER_MODE_*
std
电视标准位图,如 videodev2.h 中定义,例如 V4L2_STD_*
描述
混合调谐器应同时受 V4L2 和 DVB API 支持。此结构包含 V4L2 端使用的数据。为了避免依赖 V4L2 头文件,此处所有枚举都声明为整数。
-
enum dvbfe_algo¶
定义用于调谐到频道的算法
常量
DVBFE_ALGO_HW
硬件算法 - 支持此算法的设备完全在硬件中完成所有操作,无需软件支持来处理它们。 仅需要请求这些设备进行锁定,设备应该在硬件中完成所有操作。
DVBFE_ALGO_SW
软件算法 - 这些是简单的设备,需要软件来完成所有操作
DVBFE_ALGO_CUSTOM
可定制算法 - 具有此算法的设备可以在前端驱动程序中自定义特定的算法,而不是简单地进行软件之字形处理。 在这种情况下,之字形可能是硬件辅助的,也可能完全在硬件中完成。 在所有情况下,使用此算法与搜索和跟踪回调结合使用,都会利用驱动程序特定的算法。
DVBFE_ALGO_RECOVERY
恢复算法 - 这些设备具有从锁定失败中自动恢复的能力
-
enum dvbfe_search¶
搜索回调可能的返回状态
常量
DVBFE_ALGO_SEARCH_SUCCESS
前端搜索算法已完成并成功返回
DVBFE_ALGO_SEARCH_ASLEEP
前端搜索算法正在休眠
DVBFE_ALGO_SEARCH_FAILED
前端信号搜索失败
DVBFE_ALGO_SEARCH_INVALID
前端搜索算法可能提供了无效参数,并且搜索无效
DVBFE_ALGO_SEARCH_AGAIN
前端搜索算法被请求再次搜索
DVBFE_ALGO_SEARCH_ERROR
前端搜索算法因某些错误而失败
-
struct dvb_tuner_ops¶
调谐器信息和回调
定义:
struct dvb_tuner_ops {
struct dvb_tuner_info info;
void (*release)(struct dvb_frontend *fe);
int (*init)(struct dvb_frontend *fe);
int (*sleep)(struct dvb_frontend *fe);
int (*suspend)(struct dvb_frontend *fe);
int (*resume)(struct dvb_frontend *fe);
int (*set_params)(struct dvb_frontend *fe);
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
#define TUNER_STATUS_LOCKED 1;
#define TUNER_STATUS_STEREO 2;
int (*get_status)(struct dvb_frontend *fe, u32 *status);
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
};
成员
info
嵌入式
struct dvb_tuner_info
,包含调谐器属性release
当前端分离时调用的回调函数。驱动程序应释放任何已分配的内存。
init
用于初始化调谐器设备的回调函数。
sleep
用于使调谐器进入睡眠状态的回调函数。
suspend
用于通知内核即将挂起的回调函数。
resume
用于通知内核正在从挂起状态恢复的回调函数。
set_params
用于通知调谐器调谐到数字电视频道的回调函数。 要使用的属性存储在
struct dvb_frontend
.dtv_property_cache 中。 调谐器解调器可以更改参数以反映调谐频道所需的更改,并更新统计信息。 这是设置调谐器参数的推荐方法,应在较新的驱动程序中使用。set_analog_params
用于在混合调谐器上调谐到模拟电视频道的回调函数。 它将 analog_parameters 传递给驱动程序。
set_config
用于发送某些特定于调谐器的参数的回调函数。
get_frequency
获取实际调谐的频率
get_bandwidth
获取低通滤波器使用的带宽
get_if_frequency
获取中频,单位为 Hz。 对于基带,应返回 0。
get_status
返回前端锁定状态
get_rf_strength
返回 RF 信号强度。 主要用于支持模拟电视和广播。 数字电视应改为通过 DVBv5 API 报告(
struct dvb_frontend
.dtv_property_cache)。get_afc
仅由模拟电视核心使用。 报告由于 AFC 引起的频率漂移。
calc_regs
用于传递简单调谐器的寄存器数据设置的回调函数。 不应在较新的驱动程序中使用。
set_frequency
设置新频率。 不应在较新的驱动程序中使用。
set_bandwidth
设置新频率。 不应在较新的驱动程序中使用。
注意
在 get_frequency 和 set_frequency 中使用的频率对于地面/有线为 Hz,对于卫星为 kHz。
-
struct analog_demod_info¶
解调器模拟电视部分的信息结构
定义:
struct analog_demod_info {
char *name;
};
成员
name
模拟电视解调器的名称
-
struct analog_demod_ops¶
模拟电视和广播的解调信息和回调
定义:
struct analog_demod_ops {
struct analog_demod_info info;
void (*set_params)(struct dvb_frontend *fe, struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);
int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
};
成员
info
指向
struct analog_demod_info
的指针set_params
用于通知解调器设置解码模拟或广播频道所需的解调器参数的回调函数。 这些属性通过
struct analog_params
传递。has_signal
如果有信号则返回 0xffff,如果没有则返回 0。
get_afc
仅由模拟电视核心使用。 报告由于 AFC 引起的频率漂移。
tuner_status
返回调谐器状态位的回调函数,例如
TUNER_STATUS_LOCKED
和TUNER_STATUS_STEREO
。standby
将调谐器设置为待机模式。
release
当前端分离时调用的回调函数。驱动程序应释放任何已分配的内存。
i2c_gate_ctrl
控制 I2C 门。 较新的驱动程序应改为使用 I2C 多路复用器支持。
set_config
用于发送某些特定于调谐器的参数的回调函数。
-
struct dvb_frontend_internal_info¶
前端属性和功能
定义:
struct dvb_frontend_internal_info {
char name[128];
u32 frequency_min_hz;
u32 frequency_max_hz;
u32 frequency_stepsize_hz;
u32 frequency_tolerance_hz;
u32 symbol_rate_min;
u32 symbol_rate_max;
u32 symbol_rate_tolerance;
enum fe_caps caps;
};
成员
name
前端的名称
frequency_min_hz
前端支持的最小频率。
frequency_max_hz
前端支持的最小频率。
frequency_stepsize_hz
所有频率都是此值的倍数。
frequency_tolerance_hz
频率容差。
symbol_rate_min
最小符号率,单位为波特(用于有线/卫星系统)。
symbol_rate_max
最大符号率,单位为波特(用于有线/卫星系统)。
symbol_rate_tolerance
最大符号率容差,单位为 ppm(用于有线/卫星系统)。
caps
前端支持的功能,如
enum fe_caps
中指定。
-
struct dvb_frontend_ops¶
数字电视的解调信息和回调
定义:
struct dvb_frontend_ops {
struct dvb_frontend_internal_info info;
u8 delsys[MAX_DELSYS];
void (*detach)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend* fe);
void (*release_sec)(struct dvb_frontend* fe);
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
int (*suspend)(struct dvb_frontend *fe);
int (*resume)(struct dvb_frontend *fe);
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
int (*tune)(struct dvb_frontend* fe,bool re_tune,unsigned int mode_flags,unsigned int *delay, enum fe_status *status);
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
int (*set_frontend)(struct dvb_frontend *fe);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
int (*get_frontend)(struct dvb_frontend *fe, struct dtv_frontend_properties *props);
int (*read_status)(struct dvb_frontend *fe, enum fe_status *status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
int (*read_snr)(struct dvb_frontend* fe, u16* snr);
int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
int (*diseqc_reset_overload)(struct dvb_frontend* fe);
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
int (*diseqc_send_burst)(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd);
int (*set_tone)(struct dvb_frontend *fe, enum fe_sec_tone_mode tone);
int (*set_voltage)(struct dvb_frontend *fe, enum fe_sec_voltage voltage);
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
int (*set_lna)(struct dvb_frontend *);
enum dvbfe_search (*search)(struct dvb_frontend *fe);
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
};
成员
info
嵌入式
struct dvb_tuner_info
,包含调谐器属性delsys
前端支持的传输系统
detach
当前端分离时调用的回调函数。 驱动程序应进行清理,但不要释放
struct dvb_frontend
分配。release
当前端准备好释放时调用的回调函数。 驱动程序应释放任何已分配的内存。
release_sec
请求卫星设备控制 (SEC) 驱动程序释放并释放驱动程序分配的任何内存的回调函数。
init
用于初始化调谐器设备的回调函数。
sleep
用于使调谐器进入睡眠状态的回调函数。
suspend
用于通知内核即将挂起的回调函数。
resume
用于通知内核正在从挂起状态恢复的回调函数。
write
一些解调器旧版驱动程序使用的回调函数,允许其他驱动程序将数据写入其寄存器。 不应在新驱动程序中使用。
tune
使用 DVBFE_ALGO_HW 的解调器驱动程序用来调谐到某个频率的回调函数。
get_frontend_algo
返回所需的硬件算法。
set_frontend
用于通知解调器设置解调数字电视频道的参数的回调函数。 要使用的属性存储在
struct dvb_frontend
.dtv_property_cache 中。 解调器可以更改参数以反映解码频道所需的更改,并更新统计信息。get_tune_settings
回调函数
get_frontend
用于通知实际使用的参数的回调函数。 要使用的属性存储在
struct dvb_frontend
.dtv_property_cache 中,并更新统计信息。 请注意,如果统计信息不可用(因为解调器未锁定),则不应返回错误代码。read_status
返回前端的锁定状态。
read_ber
返回误码率的旧版回调函数。 较新的驱动程序应通过 DVBv5 API(例如,set_frontend;/get_frontend)提供此类信息,仅当需要 DVBv3 API 兼容性时才实现此回调。
read_signal_strength
返回信号强度的旧版回调函数。 较新的驱动程序应通过 DVBv5 API(例如,set_frontend/get_frontend)提供此类信息,仅当需要 DVBv3 API 兼容性时才实现此回调。
read_snr
返回信噪比的旧版回调函数。 较新的驱动程序应通过 DVBv5 API(例如,set_frontend/get_frontend)提供此类信息,仅当需要 DVBv3 API 兼容性时才实现此回调。
read_ucblocks
返回未纠正的错误块的旧版回调函数。 较新的驱动程序应通过 DVBv5 API(例如,set_frontend/get_frontend)提供此类信息,仅当需要 DVBv3 API 兼容性时才实现此回调。
diseqc_reset_overload
用于实现 FE_DISEQC_RESET_OVERLOAD() ioctl 的回调函数(仅限卫星)
diseqc_send_master_cmd
用于实现 FE_DISEQC_SEND_MASTER_CMD() ioctl 的回调函数(仅限卫星)。
diseqc_recv_slave_reply
用于实现 FE_DISEQC_RECV_SLAVE_REPLY() ioctl 的回调函数(仅限卫星)
diseqc_send_burst
用于实现 FE_DISEQC_SEND_BURST() ioctl 的回调函数(仅限卫星)。
set_tone
用于实现 FE_SET_TONE() ioctl 的回调函数(仅限卫星)。
set_voltage
用于实现 FE_SET_VOLTAGE() ioctl 的回调函数(仅限卫星)。
enable_high_lnb_voltage
用于实现 FE_ENABLE_HIGH_LNB_VOLTAGE() ioctl 的回调函数(仅限卫星)。
dishnetwork_send_legacy_command
用于实现 FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl 的回调函数(仅限卫星)。 除非 DVB 核心仿真无法提供适当的支持(例如,如果 set_voltage 需要超过 8 毫秒才能工作),并且需要与此旧版 API 向后兼容,否则驱动程序不应使用此功能。
i2c_gate_ctrl
控制 I2C 门。 较新的驱动程序应改为使用 I2C 多路复用器支持。
ts_bus_ctrl
用于控制 TS 总线的回调函数。
set_lna
用于打开/关闭/自动 LNA 的回调函数。
search
在某些自定义算法搜索算法上使用的回调函数。
tuner_ops
指向
struct dvb_tuner_ops
的指针analog_ops
指向
struct analog_demod_ops
的指针
-
struct dtv_frontend_properties¶
包含特定于数字电视标准的属性列表。
定义:
struct dtv_frontend_properties {
u32 frequency;
enum fe_modulation modulation;
enum fe_sec_voltage voltage;
enum fe_sec_tone_mode sectone;
enum fe_spectral_inversion inversion;
enum fe_code_rate fec_inner;
enum fe_transmit_mode transmission_mode;
u32 bandwidth_hz;
enum fe_guard_interval guard_interval;
enum fe_hierarchy hierarchy;
u32 symbol_rate;
enum fe_code_rate code_rate_HP;
enum fe_code_rate code_rate_LP;
enum fe_pilot pilot;
enum fe_rolloff rolloff;
enum fe_delivery_system delivery_system;
enum fe_interleaving interleaving;
u8 isdbt_partial_reception;
u8 isdbt_sb_mode;
u8 isdbt_sb_subchannel;
u32 isdbt_sb_segment_idx;
u32 isdbt_sb_segment_count;
u8 isdbt_layer_enabled;
struct {
u8 segment_count;
enum fe_code_rate fec;
enum fe_modulation modulation;
u8 interleaving;
} layer[3];
u32 stream_id;
u32 scrambling_sequence_index;
u8 atscmh_fic_ver;
u8 atscmh_parade_id;
u8 atscmh_nog;
u8 atscmh_tnog;
u8 atscmh_sgn;
u8 atscmh_prc;
u8 atscmh_rs_frame_mode;
u8 atscmh_rs_frame_ensemble;
u8 atscmh_rs_code_mode_pri;
u8 atscmh_rs_code_mode_sec;
u8 atscmh_sccc_block_mode;
u8 atscmh_sccc_code_mode_a;
u8 atscmh_sccc_code_mode_b;
u8 atscmh_sccc_code_mode_c;
u8 atscmh_sccc_code_mode_d;
u32 lna;
struct dtv_fe_stats strength;
struct dtv_fe_stats cnr;
struct dtv_fe_stats pre_bit_error;
struct dtv_fe_stats pre_bit_count;
struct dtv_fe_stats post_bit_error;
struct dtv_fe_stats post_bit_count;
struct dtv_fe_stats block_error;
struct dtv_fe_stats block_count;
};
成员
frequency
对于地面/有线,频率单位为 Hz,对于卫星,频率单位为 kHz
modulation
前端调制类型
voltage
SEC 电压(仅限卫星)
sectone
SEC 音调模式(仅限卫星)
inversion
频谱反转
fec_inner
前向纠错内部码率
transmission_mode
传输模式
bandwidth_hz
带宽,单位为 Hz。 值为零表示用户空间想要自动检测。
guard_interval
保护间隔
hierarchy
层次结构
symbol_rate
符号率
code_rate_HP
高优先级流码率
code_rate_LP
低优先级流码率
pilot
启用/禁用/自动检测导频音
rolloff
滚降系数 (alpha)
delivery_system
FE传输系统 (例如,数字电视标准)
交织
交织
isdbt_partial_reception
ISDB-T 部分接收 (仅限 ISDB 标准)
isdbt_sb_mode
ISDB-T 声音广播 (SB) 模式 (仅限 ISDB 标准)
isdbt_sb_subchannel
ISDB-T SB 子频道 (仅限 ISDB 标准)
isdbt_sb_segment_idx
ISDB-T SB 段索引 (仅限 ISDB 标准)
isdbt_sb_segment_count
ISDB-T SB 段计数 (仅限 ISDB 标准)
isdbt_layer_enabled
ISDB 层启用 (仅限 ISDB 标准)
layer
ISDB 每层数据 (仅限 ISDB 标准)
layer.segment_count
段计数;
layer.fec
每层码率;
layer.modulation
每层调制;
layer.interleaving
每层交织。
stream_id
如果非零,则启用子流过滤,如果硬件支持 (DVB-S2 和 DVB-T2)。
scrambling_sequence_index
携带 DVB-S2 物理层加扰序列的索引。
atscmh_fic_ver
FIC (快速信息信道) 信令数据的版本号 (仅限 ATSC-M/H)
atscmh_parade_id
队列识别号 (仅限 ATSC-M/H)
atscmh_nog
每个 MH 子帧中指定队列的 MH 组数 (仅限 ATSC-M/H)
atscmh_tnog
包括一个 MH 子帧中所有 MH 队列的所有 MH 组在内的 MH 组总数 (仅限 ATSC-M/H)
atscmh_sgn
起始组号 (仅限 ATSC-M/H)
atscmh_prc
队列重复周期 (仅限 ATSC-M/H)
atscmh_rs_frame_mode
里德-所罗门 (RS) 帧模式 (仅限 ATSC-M/H)
atscmh_rs_frame_ensemble
RS 帧集成 (仅限 ATSC-M/H)
atscmh_rs_code_mode_pri
RS 代码模式 pri (仅限 ATSC-M/H)
atscmh_rs_code_mode_sec
RS 代码模式 sec (仅限 ATSC-M/H)
atscmh_sccc_block_mode
串联卷积码 (SCCC) 块模式 (仅限 ATSC-M/H)
atscmh_sccc_code_mode_a
SCCC 代码模式 A (仅限 ATSC-M/H)
atscmh_sccc_code_mode_b
SCCC 代码模式 B (仅限 ATSC-M/H)
atscmh_sccc_code_mode_c
SCCC 代码模式 C (仅限 ATSC-M/H)
atscmh_sccc_code_mode_d
SCCC 代码模式 D (仅限 ATSC-M/H)
lna
开启/关闭/自动线性低噪声放大器 (LNA)
strength
DVBv5 API 统计信息: 信号强度
cnr
DVBv5 API 统计信息: (主) 载波的信噪比
pre_bit_error
DVBv5 API 统计信息: 维特比前误码计数
pre_bit_count
DVBv5 API 统计信息: 维特比前比特计数
post_bit_error
DVBv5 API 统计信息: 维特比后误码计数
post_bit_count
DVBv5 API 统计信息: 维特比后比特计数
block_error
DVBv5 API 统计信息: 块错误计数
block_count
DVBv5 API 统计信息: 块计数
注意
像未纠正的错误块 (UCE) 这样的派生统计信息是在用户空间计算的。
描述
对于给定的传输系统,只需要属性的子集。有关更多信息,请查阅 media_api.html 和 Userspace API 的文档。
-
struct dvb_frontend¶
驱动程序中要使用的前端结构。
定义:
struct dvb_frontend {
struct kref refcount;
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
void *demodulator_priv;
void *tuner_priv;
void *frontend_priv;
void *sec_priv;
void *analog_demod_priv;
struct dtv_frontend_properties dtv_property_cache;
#define DVB_FRONTEND_COMPONENT_TUNER 0;
#define DVB_FRONTEND_COMPONENT_DEMOD 1;
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
unsigned int exit;
};
成员
refcount
用于跟踪
struct dvb_frontend
引用的引用计数ops
dvb
指向
struct dvb_adapter
的指针demodulator_priv
解调器私有数据
tuner_priv
调谐器私有数据
frontend_priv
前端私有数据
sec_priv
SEC 私有数据
analog_demod_priv
模拟解调私有数据
dtv_property_cache
callback
某些驱动程序上用于调用调谐器或解调器的回调函数。
id
前端 ID
exit
用于通知 DVB 核心前端线程应该退出(通常意味着硬件已断开连接)。
-
int dvb_register_frontend(struct dvb_adapter *dvb, struct dvb_frontend *fe)¶
在适配器上注册 DVB 前端
参数
struct dvb_adapter *dvb
指向
struct dvb_adapter
的指针struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
分配并初始化前端核心管理前端所需的私有数据,并调用 dvb_register_device()
来注册新的前端。它还会清除存储前端参数的属性缓存,并选择第一个可用的传输系统。
-
int dvb_unregister_frontend(struct dvb_frontend *fe)¶
注销 DVB 前端
参数
struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
停止前端 kthread,调用 dvb_unregister_device()
并释放由 dvb_register_frontend()
分配的私有前端数据。
注意
此函数不会释放解调器、SEC 驱动程序和调谐器分配的内存。为了释放它,在调用此函数后,需要显式调用 dvb_frontend_detach()
。
-
void dvb_frontend_detach(struct dvb_frontend *fe)¶
分离并释放前端特定数据
参数
struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
此函数应在 dvb_unregister_frontend()
之后调用。它调用 SEC、调谐器和解调器释放函数:dvb_frontend_ops.release_sec
、dvb_frontend_ops.tuner_ops
.release、dvb_frontend_ops.analog_ops
.release 和 dvb_frontend_ops.release
。
如果驱动程序使用 CONFIG_MEDIA_ATTACH
编译,它还会减少模块引用计数,这对于允许用户空间删除先前使用的 DVB 前端模块是必需的。
-
int dvb_frontend_suspend(struct dvb_frontend *fe)¶
挂起数字电视前端
参数
struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
此函数准备挂起数字电视前端。
为了准备挂起调谐器,如果 dvb_frontend_ops.tuner_ops
.suspend() 可用,它会调用它。否则,如果可用,它将调用 dvb_frontend_ops.tuner_ops
.sleep()。
它还会调用 dvb_frontend_ops.suspend
() 以使解调器挂起(如果可用)。否则,它将调用 dvb_frontend_ops.sleep
()。
驱动程序还应调用 dvb_frontend_suspend()
作为其 device_driver.suspend
() 处理程序的一部分。
-
int dvb_frontend_resume(struct dvb_frontend *fe)¶
恢复数字电视前端
参数
struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
此函数恢复恢复后调谐器的正常运行。
为了恢复前端,如果可用,它会调用解调器的 dvb_frontend_ops.resume
()。否则,它会调用解调器的 dvb_frontend_ops.init
()。
如果 dvb_frontend_ops.tuner_ops
.resume() 可用,则会调用它。否则,如果可用,它会调用 dvb_frontend_ops.tuner_ops
.init()。
一旦调谐器和解调器恢复,它将强制 SEC 电压和音调恢复到它们之前的值,并唤醒前端的 kthread 以重新调谐前端。
驱动程序还应调用 dvb_frontend_resume()
作为其 device_driver.resume
() 处理程序的一部分。
-
void dvb_frontend_reinitialise(struct dvb_frontend *fe)¶
强制在前端重新初始化
参数
struct dvb_frontend *fe
指向
struct dvb_frontend
的指针
描述
调用 dvb_frontend_ops.init
() 和 dvb_frontend_ops.tuner_ops
.init(),并重置 SEC 音调和电压(用于卫星系统)。
注意
目前,此函数仅被一个驱动程序(budget-av)使用。这似乎是为了解决该特定前端的一些特殊问题。
-
void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec)¶
休眠由 add_usec 参数给定的时间量
参数
ktime_t *waketime
指向
struct ktime_t
的指针u32 add_usec
休眠时间,以微秒为单位
描述
此函数用于测量 FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl 工作所需的时间。它需要尽可能精确,因为它会影响卫星子系统上碟形音调命令的检测。
它在 DVB 前端核心内部使用,以便使用 dvb_frontend_ops.set_voltage
() 回调来模拟 FE_DISHNETWORK_SEND_LEGACY_CMD()。
注意
它不应在驱动程序中使用,因为内核提供了对旧版回调的模拟。只有在硬件存在一些会阻止核心模拟工作的问题时,才应该在驱动程序中使用。在这种情况下,驱动程序将编写 dvb_frontend_ops.dishnetwork_send_legacy_command
() 并直接调用此函数。