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,
};

注意

  1. 对于卫星数字电视标准(DVB-S、DVB-S2、ISDB-S),频率以kHz为单位指定,而对于地面和有线标准,频率以Hz为单位指定。因此,如果同一前端支持这两种类型,则需要有两个单独的dvb_frontend_ops结构,每种标准一个。

  2. 仅当硬件允许控制I2C门(直接或通过某些GPIO引脚)时,才存在.i2c_gate_ctrl字段,以便在调整频道后从I2C总线上移除调谐器。

  3. 所有新驱动程序都应通过.read_status实现DVBv5统计信息。然而,有许多回调旨在获取信号强度、S/N和UCB的统计信息。它们的存在是为了提供与不支持DVBv5 API的旧版应用程序的向后兼容性。实现这些回调是可选的。在我们让所有现有驱动程序都支持DVBv5统计信息之后,这些回调可能会在将来被删除。

  4. 为了控制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]

  • 驱动程序应尝试始终使其可用,因为这些统计信息可用于调整天线位置并检查布线问题。

载波信号噪声比(DTV_STAT_CNR
  • 主载波的信号噪声比。

  • 信号噪声测量取决于设备。在某些硬件上,当检测到主载波时,它可以可用。在这些硬件上,CNR测量通常来自调谐器(例如,在FE_HAS_CARRIER之后,请参阅fe_status)。

    在其他设备上,它需要内部FEC解码,因为前端从其他参数间接测量它(例如,在FE_HAS_VITERBI之后,请参阅fe_status)。

    在内部FEC之后可用更为常见。

FEC后的比特计数(DTV_STAT_POST_ERROR_BIT_COUNTDTV_STAT_POST_TOTAL_BIT_COUNT
  • 这些计数器测量内部编码块(在Viterbi、LDPC或其他内部代码之后)上的前向纠错(FEC)之后的比特数和比特错误数。

  • 由于其性质,这些统计信息取决于完全编码锁定(例如,在FE_HAS_SYNC之后或在FE_HAS_LOCK之后,请参阅fe_status)。

FEC前的比特计数(DTV_STAT_PRE_ERROR_BIT_COUNTDTV_STAT_PRE_TOTAL_BIT_COUNT
  • 这些计数器测量内部编码块(在Viterbi、LDPC或其他内部代码之前)上的前向纠错(FEC)之前的比特数和比特错误数。

  • 并非所有前端都提供此类统计信息。

  • 由于其性质,这些统计信息取决于内部编码锁定(例如,在FE_HAS_VITERBI之后,请参阅fe_status)。

块计数(DTV_STAT_ERROR_BLOCK_COUNTDTV-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

恢复算法 - 这些设备具有从锁定失败中自动恢复的能力

搜索回调可能返回的状态

常量

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_frequencyset_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_LOCKEDTUNER_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

嵌入的 struct dvb_frontend_ops

dvb

指向 struct dvb_adapter 的指针

demodulator_priv

解调器私有数据

tuner_priv

调谐器私有数据

frontend_priv

前端私有数据

sec_priv

SEC 私有数据

analog_demod_priv

模拟解调私有数据

dtv_property_cache

嵌入的 struct dtv_frontend_properties

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() 并直接调用此函数。