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 有一个内核线程,负责调谐设备。它支持多种算法来检测频道,如枚举 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]

  • 驱动程序应尝试始终使其可用,因为这些统计数据可用于调整天线位置和检查电缆故障。

载波信噪比 (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_SYNCFE_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_SYNCFE_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

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

搜索回调可能的返回状态

常量

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 中,并更新统计信息。 请注意,如果统计信息不可用(因为解调器未锁定),则不应返回错误代码。

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

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