2.3. 属性类型

要调谐到数字电视的物理频道并开始解码,需要更改一组参数,以控制调谐器、解调器、线性低噪声放大器 (LNA) 以及通过卫星设备控制 - SEC(在卫星系统上)设置天线子系统。实际参数特定于每个特定的数字电视标准,并且可能会随着数字电视规范的发展而变化。

在过去(直到 DVB API 版本 3 - DVBv3),使用的策略是使用一个联合体,其中包含调谐 DVB-S、DVB-C、DVB-T 和 ATSC 传输系统所需的参数。问题在于,随着第二代标准的出现,该联合体的大小不足以组合这些新标准所需的结构体。此外,扩展它会破坏用户空间。

因此,传统的基于联合体/结构体的方法被弃用,转而采用属性集方法。在这种方法中,FE_GET_PROPERTY 和 FE_SET_PROPERTY 用于设置前端并读取其状态。

实际操作由一组 dtv_property cmd/data 对确定。通过一个 ioctl,可以获取/设置多达 64 个属性。

本节介绍设置前端的新推荐方法,它支持所有数字电视传输系统。

注意

  1. 在 Linux DVB API 版本 3 中,设置前端是通过 struct dvb_frontend_parameters 完成的。

  2. 请勿在支持较新标准的硬件上使用 DVB API 版本 3 的调用。此类 API 不提供或仅提供对新标准和/或新硬件的非常有限的支持。

  3. 如今,大多数前端都支持多种传输系统。只有通过 DVB API 版本 5 的调用,才可以在前端支持的多种传输系统之间切换。

  4. DVB API 版本 5 也称为 *S2API*,因为添加到它的第一个新标准是 DVB-S2。

示例:为了将硬件设置为调谐到 651 kHz 的 DVB-C 频道,使用 256-QAM 调制,FEC 3/4 和 5.217 Mbauds 的符号率,应将这些属性发送到 FE_SET_PROPERTY ioctl

DTV_DELIVERY_SYSTEM = SYS_DVBC_ANNEX_A

DTV_FREQUENCY = 651000000

DTV_MODULATION = QAM_256

DTV_INVERSION = INVERSION_AUTO

DTV_SYMBOL_RATE = 5217000

DTV_INNER_FEC = FEC_3_4

DTV_TUNE

完成上述操作的代码在 示例:设置数字电视前端属性 中显示。

示例:设置数字电视前端属性
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/frontend.h>

static struct dtv_property props[] = {
    { .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_DVBC_ANNEX_A },
    { .cmd = DTV_FREQUENCY,       .u.data = 651000000 },
    { .cmd = DTV_MODULATION,      .u.data = QAM_256 },
    { .cmd = DTV_INVERSION,       .u.data = INVERSION_AUTO },
    { .cmd = DTV_SYMBOL_RATE,     .u.data = 5217000 },
    { .cmd = DTV_INNER_FEC,       .u.data = FEC_3_4 },
    { .cmd = DTV_TUNE }
};

static struct dtv_properties dtv_prop = {
    .num = 6, .props = props
};

int main(void)
{
    int fd = open("/dev/dvb/adapter0/frontend0", O_RDWR);

    if (!fd) {
        perror ("open");
        return -1;
    }
    if (ioctl(fd, FE_SET_PROPERTY, &dtv_prop) == -1) {
        perror("ioctl");
        return -1;
    }
    printf("Frontend set\\n");
    return 0;
}

注意

虽然可以直接像上面的示例一样调用内核代码,但强烈建议使用 libdvbv5,因为它提供了抽象来处理支持的数字电视标准,并为诸如程序扫描和读/写频道描述符文件之类的常用操作提供方法。