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
有一个内核线程,负责调谐设备。它支持多种算法来检测频道,如enum 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()
以释放前端驱动程序分配的内存。
驱动程序还应调用dvb_frontend_suspend()
作为其处理程序device_driver
.suspend()
的一部分,并调用dvb_frontend_resume()
作为其处理程序device_driver
.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
支持的最小频率,以Hz为单位
frequency_max_hz
支持的最大频率,以Hz为单位
frequency_step_hz
频率步长,以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
调谐器模式,如enum 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
可定制算法 - 具有此算法的设备可以进行定制,以便在前端驱动程序中具有特定的算法,而不是简单地进行软件 Z 字形搜索。在这种情况下,Z 字形搜索可能是硬件辅助的,或者完全在硬件中完成。在所有情况下,使用此算法,结合搜索和跟踪回调,将利用驱动程序特定的算法。
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 中,并更新统计信息。请注意,如果由于 demog 未锁定而导致统计信息不可用,则不应返回错误代码。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 传输系统(例如,数字电视标准)
interleaving
interleaving
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 统计信息:Viterbi 之前的误码计数
pre_bit_count
DVBv5 API 统计信息:Viterbi 之前的比特计数
post_bit_error
DVBv5 API 统计信息:Viterbi 之后的误码计数
post_bit_count
DVBv5 API 统计信息:Viterbi 之后的比特计数
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 工作所需的时间。 它需要尽可能精确,因为它会影响卫星子系统中 dish 音调命令的检测。
它在 DVB 前端核心内部使用,以便使用 dvb_frontend_ops.set_voltage
() 回调来模拟 FE_DISHNETWORK_SEND_LEGACY_CMD()。
注意
它不应在驱动程序中使用,因为传统回调的模拟由内核提供。 这种情况应该只在驱动程序中出现,即当硬件存在一些错误,会阻止核心模拟工作时。 在这种情况下,驱动程序将编写一个 dvb_frontend_ops.dishnetwork_send_legacy_command
() 并直接调用此函数。