From ab959d7b4194715870128e616b8e29d4a101e488 Mon Sep 17 00:00:00 2001 From: etobi Date: Tue, 3 Sep 2013 09:48:41 +0200 Subject: Imported Upstream version 1.1.1+rev1207 --- lib/libdvbapi/Makefile | 25 +++ lib/libdvbapi/dvbaudio.c | 50 +++++ lib/libdvbapi/dvbaudio.h | 55 +++++ lib/libdvbapi/dvbca.c | 159 +++++++++++++ lib/libdvbapi/dvbca.h | 135 +++++++++++ lib/libdvbapi/dvbdemux.c | 255 +++++++++++++++++++++ lib/libdvbapi/dvbdemux.h | 204 +++++++++++++++++ lib/libdvbapi/dvbfe.c | 574 +++++++++++++++++++++++++++++++++++++++++++++++ lib/libdvbapi/dvbfe.h | 333 +++++++++++++++++++++++++++ lib/libdvbapi/dvbnet.c | 104 +++++++++ lib/libdvbapi/dvbnet.h | 87 +++++++ lib/libdvbapi/dvbvideo.c | 46 ++++ lib/libdvbapi/dvbvideo.h | 46 ++++ 13 files changed, 2073 insertions(+) create mode 100644 lib/libdvbapi/Makefile create mode 100644 lib/libdvbapi/dvbaudio.c create mode 100644 lib/libdvbapi/dvbaudio.h create mode 100644 lib/libdvbapi/dvbca.c create mode 100644 lib/libdvbapi/dvbca.h create mode 100644 lib/libdvbapi/dvbdemux.c create mode 100644 lib/libdvbapi/dvbdemux.h create mode 100644 lib/libdvbapi/dvbfe.c create mode 100644 lib/libdvbapi/dvbfe.h create mode 100644 lib/libdvbapi/dvbnet.c create mode 100644 lib/libdvbapi/dvbnet.h create mode 100644 lib/libdvbapi/dvbvideo.c create mode 100644 lib/libdvbapi/dvbvideo.h (limited to 'lib/libdvbapi') diff --git a/lib/libdvbapi/Makefile b/lib/libdvbapi/Makefile new file mode 100644 index 0000000..0ed96ec --- /dev/null +++ b/lib/libdvbapi/Makefile @@ -0,0 +1,25 @@ +# Makefile for linuxtv.org dvb-apps/lib/libdvbapi + +includes = dvbaudio.h \ + dvbca.h \ + dvbdemux.h \ + dvbfe.h \ + dvbnet.h \ + dvbvideo.h + +objects = dvbaudio.o \ + dvbca.o \ + dvbdemux.o \ + dvbfe.o \ + dvbnet.o \ + dvbvideo.o + +lib_name = libdvbapi + +CPPFLAGS += -I../../lib + +.PHONY: all + +all: library + +include ../../Make.rules diff --git a/lib/libdvbapi/dvbaudio.c b/lib/libdvbapi/dvbaudio.c new file mode 100644 index 0000000..72b4d70 --- /dev/null +++ b/lib/libdvbapi/dvbaudio.c @@ -0,0 +1,50 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbaudio.h" + +int dvbaudio_open(int adapter, int audiodeviceid) +{ + char filename[PATH_MAX+1]; + int fd; + + sprintf(filename, "/dev/dvb/adapter%i/audio%i", adapter, audiodeviceid); + if ((fd = open(filename, O_RDWR)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.audio%i", adapter, audiodeviceid); + fd = open(filename, O_RDWR); + } + + return fd; +} + +int dvbaudio_set_bypass(int fd, int bypass) +{ + return ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass); +} diff --git a/lib/libdvbapi/dvbaudio.h b/lib/libdvbapi/dvbaudio.h new file mode 100644 index 0000000..36f6a55 --- /dev/null +++ b/lib/libdvbapi/dvbaudio.h @@ -0,0 +1,55 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBAUDIO_H +#define LIBDVBAUDIO_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * Open a DVB audio device. + * + * @param adapter DVB adapter ID. + * @param audiodeviceid Id of audio device of that adapter to open. + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbaudio_open(int adapter, int audiodeviceid); + +/** + * Control audio bypass - i.e. output decoded audio, or the raw bitstream (e.g. AC3). + * + * @param fd Audio device opened with dvbaudio_open(). + * @param bypass 1=> enable bypass, 0=> disable. + * @return 0 on success, nonzero on failure. + */ +extern int dvbaudio_set_bypass(int fd, int bypass); + +// FIXME: this is a stub library + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBAUDIO_H diff --git a/lib/libdvbapi/dvbca.c b/lib/libdvbapi/dvbca.c new file mode 100644 index 0000000..8261cd2 --- /dev/null +++ b/lib/libdvbapi/dvbca.c @@ -0,0 +1,159 @@ +/* + * libdvbca - interface onto raw CA devices + * + * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbca.h" + + +int dvbca_open(int adapter, int cadevice) +{ + char filename[PATH_MAX+1]; + int fd; + + sprintf(filename, "/dev/dvb/adapter%i/ca%i", adapter, cadevice); + if ((fd = open(filename, O_RDWR)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.ca%i", adapter, cadevice); + fd = open(filename, O_RDWR); + } + + return fd; +} + +int dvbca_reset(int fd, uint8_t slot) +{ + return ioctl(fd, CA_RESET, (1 << slot)); +} + +int dvbca_get_interface_type(int fd, uint8_t slot) +{ + ca_slot_info_t info; + + info.num = slot; + if (ioctl(fd, CA_GET_SLOT_INFO, &info)) + return -1; + + if (info.type & CA_CI_LINK) + return DVBCA_INTERFACE_LINK; + if (info.type & CA_CI) + return DVBCA_INTERFACE_HLCI; + + return -1; +} + +int dvbca_get_cam_state(int fd, uint8_t slot) +{ + ca_slot_info_t info; + + info.num = slot; + if (ioctl(fd, CA_GET_SLOT_INFO, &info)) + return -1; + + if (info.flags == 0) + return DVBCA_CAMSTATE_MISSING; + if (info.flags & CA_CI_MODULE_READY) + return DVBCA_CAMSTATE_READY; + if (info.flags & CA_CI_MODULE_PRESENT) + return DVBCA_CAMSTATE_INITIALISING; + + return -1; +} + +int dvbca_link_write(int fd, uint8_t slot, uint8_t connection_id, + uint8_t *data, uint16_t data_length) +{ + uint8_t *buf = malloc(data_length + 2); + if (buf == NULL) + return -1; + + buf[0] = slot; + buf[1] = connection_id; + memcpy(buf+2, data, data_length); + + int result = write(fd, buf, data_length+2); + free(buf); + return result; +} + +int dvbca_link_read(int fd, uint8_t *slot, uint8_t *connection_id, + uint8_t *data, uint16_t data_length) +{ + int size; + + uint8_t *buf = malloc(data_length + 2); + if (buf == NULL) + return -1; + + if ((size = read(fd, buf, data_length+2)) < 2) + return -1; + + *slot = buf[0]; + *connection_id = buf[1]; + memcpy(data, buf+2, size-2); + free(buf); + + return size - 2; +} + +int dvbca_hlci_write(int fd, uint8_t *data, uint16_t data_length) +{ + struct ca_msg msg; + + if (data_length > 256) { + return -1; + } + memset(&msg, 0, sizeof(msg)); + msg.length = data_length; + + memcpy(msg.msg, data, data_length); + + return ioctl(fd, CA_SEND_MSG, &msg); +} + +int dvbca_hlci_read(int fd, uint32_t app_tag, uint8_t *data, + uint16_t data_length) +{ + struct ca_msg msg; + + if (data_length > 256) { + data_length = 256; + } + memset(&msg, 0, sizeof(msg)); + msg.length = data_length; + msg.msg[0] = app_tag >> 16; + msg.msg[1] = app_tag >> 8; + msg.msg[2] = app_tag; + + int status = ioctl(fd, CA_GET_MSG, &msg); + if (status < 0) return status; + + if (msg.length > data_length) msg.length = data_length; + memcpy(data, msg.msg, msg.length); + return msg.length; +} diff --git a/lib/libdvbapi/dvbca.h b/lib/libdvbapi/dvbca.h new file mode 100644 index 0000000..c65423b --- /dev/null +++ b/lib/libdvbapi/dvbca.h @@ -0,0 +1,135 @@ +/* + * libdvbca - interface onto raw CA devices + * + * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBCA_H +#define LIBDVBCA_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * The types of CA interface we support. + */ +#define DVBCA_INTERFACE_LINK 0 +#define DVBCA_INTERFACE_HLCI 1 + +/** + * States a CAM in a slot can be in. + */ +#define DVBCA_CAMSTATE_MISSING 0 +#define DVBCA_CAMSTATE_INITIALISING 1 +#define DVBCA_CAMSTATE_READY 2 + + +/** + * Open a CA device. Multiple CAMs can be accessed through a CA device. + * + * @param adapter Index of the DVB adapter. + * @param cadevice Index of the CA device on that adapter (usually 0). + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbca_open(int adapter, int cadevice); + +/** + * Reset a CAM. + * + * @param fd File handle opened with dvbca_open. + * @param slot Slot where the requested CAM is in. + * @return 0 on success, -1 on failure. + */ +extern int dvbca_reset(int fd, uint8_t slot); + +/** + * Get the interface type of a CAM. + * + * @param fd File handle opened with dvbca_open. + * @param slot Slot where the requested CAM is in. + * @return One of the DVBCA_INTERFACE_* values, or -1 on failure. + */ +extern int dvbca_get_interface_type(int fd, uint8_t slot); + +/** + * Get the state of a CAM. + * + * @param fd File handle opened with dvbca_open. + * @param slot Slot where the requested CAM is in. + * @return One of the DVBCA_CAMSTATE_* values, or -1 on failure. + */ +extern int dvbca_get_cam_state(int fd, uint8_t slot); + +/** + * Write a message to a CAM using a link-layer interface. + * + * @param fd File handle opened with dvbca_open. + * @param slot Slot where the requested CAM is in. + * @param connection_id Connection ID of the message. + * @param data Data to write. + * @param data_length Number of bytes to write. + * @return 0 on success, or -1 on failure. + */ +extern int dvbca_link_write(int fd, uint8_t slot, uint8_t connection_id, + uint8_t *data, uint16_t data_length); + +/** + * Read a message from a CAM using a link-layer interface. + * + * @param fd File handle opened with dvbca_open. + * @param slot Slot where the responding CAM is in. + * @param connection_id Destination for the connection ID the message came from. + * @param data Data that was read. + * @param data_length Max number of bytes to read. + * @return Number of bytes read on success, or -1 on failure. + */ +extern int dvbca_link_read(int fd, uint8_t *slot, uint8_t *connection_id, + uint8_t *data, uint16_t data_length); + +// FIXME how do we determine which CAM slot of a CA is meant? +/** + * Write a message to a CAM using an HLCI interface. + * + * @param fd File handle opened with dvbca_open. + * @param data Data to write. + * @param data_length Number of bytes to write. + * @return 0 on success, or -1 on failure. + */ +extern int dvbca_hlci_write(int fd, uint8_t *data, uint16_t data_length); + +// FIXME how do we determine which CAM slot of a CA is meant? +/** + * Read a message from a CAM using an HLCI interface. + * + * @param fd File handle opened with dvbca_open. + * @param app_tag Application layer tag giving the message type to read. + * @param data Data that was read. + * @param data_length Max number of bytes to read. + * @return Number of bytes read on success, or -1 on failure. + */ +extern int dvbca_hlci_read(int fd, uint32_t app_tag, uint8_t *data, + uint16_t data_length); + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBCA_H diff --git a/lib/libdvbapi/dvbdemux.c b/lib/libdvbapi/dvbdemux.c new file mode 100644 index 0000000..a882af6 --- /dev/null +++ b/lib/libdvbapi/dvbdemux.c @@ -0,0 +1,255 @@ +/* + * libdvbdemux - a DVB demux library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbdemux.h" + + +int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking) +{ + char filename[PATH_MAX+1]; + int flags = O_RDWR; + int fd; + + if (nonblocking) + flags |= O_NONBLOCK; + + sprintf(filename, "/dev/dvb/adapter%i/demux%i", adapter, demuxdevice); + if ((fd = open(filename, flags)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.demux%i", adapter, demuxdevice); + fd = open(filename, flags); + } + + return fd; +} + +int dvbdemux_open_dvr(int adapter, int dvrdevice, int readonly, int nonblocking) +{ + char filename[PATH_MAX+1]; + int flags = O_RDWR; + int fd; + + if (readonly) + flags = O_RDONLY; + if (nonblocking) + flags |= O_NONBLOCK; + + sprintf(filename, "/dev/dvb/adapter%i/dvr%i", adapter, dvrdevice); + if ((fd = open(filename, flags)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.dvr%i", adapter, dvrdevice); + fd = open(filename, flags); + } + + return fd; +} + +int dvbdemux_set_section_filter(int fd, int pid, + uint8_t filter[18], uint8_t mask[18], + int start, int checkcrc) +{ + struct dmx_sct_filter_params sctfilter; + + memset(&sctfilter, 0, sizeof(sctfilter)); + sctfilter.pid = pid; + memcpy(sctfilter.filter.filter, filter, 1); + memcpy(sctfilter.filter.filter+1, filter+3, 15); + memcpy(sctfilter.filter.mask, mask, 1); + memcpy(sctfilter.filter.mask+1, mask+3, 15); + memset(sctfilter.filter.mode, 0, 16); + if (start) + sctfilter.flags |= DMX_IMMEDIATE_START; + if (checkcrc) + sctfilter.flags |= DMX_CHECK_CRC; + + return ioctl(fd, DMX_SET_FILTER, &sctfilter); +} + +int dvbdemux_set_pes_filter(int fd, int pid, + int input, int output, + int pestype, + int start) +{ + struct dmx_pes_filter_params filter; + + memset(&filter, 0, sizeof(filter)); + filter.pid = pid; + + switch(input) { + case DVBDEMUX_INPUT_FRONTEND: + filter.input = DMX_IN_FRONTEND; + break; + + case DVBDEMUX_INPUT_DVR: + filter.input = DMX_IN_DVR; + break; + + default: + return -EINVAL; + } + + switch(output) { + case DVBDEMUX_OUTPUT_DECODER: + filter.output = DMX_OUT_DECODER; + break; + + case DVBDEMUX_OUTPUT_DEMUX: + filter.output = DMX_OUT_TAP; + break; + + case DVBDEMUX_OUTPUT_DVR: + filter.output = DMX_OUT_TS_TAP; + break; + +#ifdef DMX_OUT_TSDEMUX_TAP + case DVBDEMUX_OUTPUT_TS_DEMUX: + filter.output = DMX_OUT_TSDEMUX_TAP; + break; +#endif + + default: + return -EINVAL; + } + + switch(pestype) { + case DVBDEMUX_PESTYPE_AUDIO: + filter.pes_type = DMX_PES_AUDIO; + break; + + case DVBDEMUX_PESTYPE_VIDEO: + filter.pes_type = DMX_PES_VIDEO; + break; + + case DVBDEMUX_PESTYPE_TELETEXT: + filter.pes_type = DMX_PES_TELETEXT; + break; + + case DVBDEMUX_PESTYPE_SUBTITLE: + filter.pes_type = DMX_PES_SUBTITLE; + break; + + case DVBDEMUX_PESTYPE_PCR: + filter.pes_type = DMX_PES_PCR; + break; + + default: + return -EINVAL; + } + + if (start) + filter.flags |= DMX_IMMEDIATE_START; + + return ioctl(fd, DMX_SET_PES_FILTER, &filter); +} + +int dvbdemux_set_pid_filter(int fd, int pid, + int input, int output, + int start) +{ + struct dmx_pes_filter_params filter; + + memset(&filter, 0, sizeof(filter)); + if (pid == -1) + filter.pid = 0x2000; + else + filter.pid = pid; + + switch(input) { + case DVBDEMUX_INPUT_FRONTEND: + filter.input = DMX_IN_FRONTEND; + break; + + case DVBDEMUX_INPUT_DVR: + filter.input = DMX_IN_DVR; + break; + + default: + return -EINVAL; + } + + switch(output) { + case DVBDEMUX_OUTPUT_DECODER: + filter.output = DMX_OUT_DECODER; + break; + + case DVBDEMUX_OUTPUT_DEMUX: + filter.output = DMX_OUT_TAP; + break; + + case DVBDEMUX_OUTPUT_DVR: + filter.output = DMX_OUT_TS_TAP; + break; + +#ifdef DMX_OUT_TSDEMUX_TAP + case DVBDEMUX_OUTPUT_TS_DEMUX: + filter.output = DMX_OUT_TSDEMUX_TAP; + break; +#endif + + default: + return -EINVAL; + } + + filter.pes_type = DMX_PES_OTHER; + + if (start) + filter.flags |= DMX_IMMEDIATE_START; + + return ioctl(fd, DMX_SET_PES_FILTER, &filter); +} + +int dvbdemux_start(int fd) +{ + return ioctl(fd, DMX_START); +} + +int dvbdemux_stop(int fd) +{ + return ioctl(fd, DMX_STOP); +} + +int dvbdemux_get_stc(int fd, uint64_t *stc) +{ + struct dmx_stc _stc; + int result; + + memset(stc, 0, sizeof(_stc)); + if ((result = ioctl(fd, DMX_GET_STC, &_stc)) != 0) { + return result; + } + + *stc = _stc.stc / _stc.base; + return 0; +} + +int dvbdemux_set_buffer(int fd, int bufsize) +{ + return ioctl(fd, DMX_SET_BUFFER_SIZE, bufsize); +} diff --git a/lib/libdvbapi/dvbdemux.h b/lib/libdvbapi/dvbdemux.h new file mode 100644 index 0000000..808ee80 --- /dev/null +++ b/lib/libdvbapi/dvbdemux.h @@ -0,0 +1,204 @@ +/* + * libdvbdemux - a DVB demux library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBDEMUX_H +#define LIBDVBDEMUX_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * Source of the data to be demuxed. + * + * FRONTEND. The data will be read from the frontend on the adapter. + * + * DVR. The data will be read from the DVR device of the adapter (of course, + * you need to write data TO the DVR device as well). + */ +#define DVBDEMUX_INPUT_FRONTEND 0 +#define DVBDEMUX_INPUT_DVR 1 + +/** + * Destination of the demuxed data. + * + * DECODER. Sends the data directly to a hardware decoder (if present). + * + * DEMUX. Sends the PID stream to the current demux file descriptor. HOWEVER, the + * data will be the payload *only* - transport stream headers will be stripped. + * + * DVR sends the data to the DVR device. The data will be the complete transport + * stream packets with headers intact. Note: if multiple filters specify + * DVBDEMUX_OUTPUT_DVR, the individual PID streams will be re-multiplexed + * together. + */ +#define DVBDEMUX_OUTPUT_DECODER 0 +#define DVBDEMUX_OUTPUT_DEMUX 1 +#define DVBDEMUX_OUTPUT_DVR 2 +#define DVBDEMUX_OUTPUT_TS_DEMUX 3 + +/** + * PES types. + */ +#define DVBDEMUX_PESTYPE_AUDIO 0 +#define DVBDEMUX_PESTYPE_VIDEO 1 +#define DVBDEMUX_PESTYPE_TELETEXT 2 +#define DVBDEMUX_PESTYPE_SUBTITLE 3 +#define DVBDEMUX_PESTYPE_PCR 4 + + +/** + * Open a demux device. Can be called multiple times. These let you setup a + * single filter per FD. It can can also be read() from if you use a section + * filter, or create a pes_filter or raw_filter with output DVBDEMUX_OUTPUT_DEMUX. + * + * @param adapter Index of the DVB adapter. + * @param demuxdevice Index of the demux device on that adapter (usually 0). + * @param nonblocking If 1, frontend will be opened in nonblocking mode. + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking); + +/** + * Open a DVR device. May be opened for writing or reading once. + * It is used to either write() transport stream data to be demuxed + * (if input == DVBDEMUX_INPUT_DVR), or to read() a stream of demuxed data + * (if output == DVBDEMUX_OUTPUT_DVR). + * + * Note, all demux filters with output set to DVBDEMUX_OUTPUT_DVR will be + * multiplexed together and output their data on this device. + * + * @param adapter Index of the DVB adapter. + * @param dvrdevice Index of the dvr device on that adapter (usually 0) + * @param readonly If 1, frontend will be opened in readonly mode only. + * @param nonblocking If 1, frontend will be opened in nonblocking mode. + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbdemux_open_dvr(int adapter, int dvrdevice, int readonly, int nonblocking); + +/** + * Set filter for the first 18 bytes of decoded SI table sections. Note that + * bytes 1 and 2 are _not_ filtered since they contain the length field. + * + * Conceptually, the driver computes the following for each filtered bit. + * + * (filter[X].bit[Y] & mask[X].bit[Y]) == (header[X].bit[Y] & mask[X].bit[Y]) + * + * Any sections which do not match this criteria for every bit will be discarded. + * + * The SI data is always read from the frontend, and is always returned by + * read()ing the demux fd. FIXME: check this statement! + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @param pid PID of the stream. + * @param filter The filter values of the first 18 bytes of the desired sections. + * @param mask Bitmask indicating which bits in the filter array should be tested + * (if a bit is 1, it will be tested). + * @param start If 1, the filter will be started immediately. Otherwise you must + * call dvbdemux_start() manually. + * @param checkcrc If 1, the driver will check the CRC on the table sections. + * Any bad sections will be dropped. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_set_section_filter(int fd, int pid, + uint8_t filter[18], uint8_t mask[18], + int start, int checkcrc); + +/** + * Set filter for a stream of PES data. This call can only used for cards + * equipped with a hardware decoder. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @param pid PID of the stream. + * @param input One of DVBDEMUX_INPUT_*. + * @param output One of DVBDEMUX_OUTPUT_*. + * @param pestype One of DVBDEMUX_PESTYPE_* - this tells the decoder the type + * of data in this stream. + * @param start If 1, the filter will be started immediately. Otherwise you must + * call dvbdemux_start() manually. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_set_pes_filter(int fd, int pid, + int input, int output, + int pestype, + int start); + +/** + * Create a pid filter - this will extract transport stream packets for a + * specified PID. + * + * Note: The wildcard PID can only be used on "budget" cards. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @param pid PID to retrieve, or use -1 as a wildcard for ALL PIDs. + * @param input One of DVBDEMUX_INPUT_*. + * @param output One of DVBDEMUX_OUTPUT_*. + * @param start If 1, the filter will be started immediately. Otherwise you must + * call dvbdemux_start() manually. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_set_pid_filter(int fd, int pid, + int input, int output, + int start); + +/** + * Start a demux going. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_start(int fd); + +/** + * Stop a demux. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_stop(int fd); + +/** + * Retrieve the current STC from the demux. This call can only used for cards + * equipped with a hardware decoder. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @param stc Where to put the retrieved STC value (in 90kHz clock). + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_get_stc(int fd, uint64_t *stc); + +/** + * Change the internal buffer size used by the demuxer. The default buffer size + * is 8192 bytes. Can only be used if the demux in question is stopped. + * + * @param fd FD as opened with dvbdemux_open_demux() above. + * @param bufsize New buffer size to use. + * @return 0 on success, nonzero on failure. + */ +extern int dvbdemux_set_buffer(int fd, int bufsize); + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBDEMUX_H diff --git a/lib/libdvbapi/dvbfe.c b/lib/libdvbapi/dvbfe.c new file mode 100644 index 0000000..98104c9 --- /dev/null +++ b/lib/libdvbapi/dvbfe.c @@ -0,0 +1,574 @@ +/* + * libdvbfe - a DVB frontend library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2005 Manu Abraham + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbfe.h" + +int verbose = 0; + +static int dvbfe_spectral_inversion_to_kapi[][2] = +{ + { DVBFE_INVERSION_OFF, INVERSION_OFF }, + { DVBFE_INVERSION_ON, INVERSION_ON }, + { DVBFE_INVERSION_AUTO, INVERSION_AUTO }, + { -1, -1 } +}; + +static int dvbfe_code_rate_to_kapi[][2] = +{ + { DVBFE_FEC_NONE, FEC_NONE }, + { DVBFE_FEC_1_2, FEC_1_2 }, + { DVBFE_FEC_2_3, FEC_2_3 }, + { DVBFE_FEC_3_4, FEC_3_4 }, + { DVBFE_FEC_4_5, FEC_4_5 }, + { DVBFE_FEC_5_6, FEC_5_6 }, + { DVBFE_FEC_6_7, FEC_6_7 }, + { DVBFE_FEC_7_8, FEC_7_8 }, + { DVBFE_FEC_8_9, FEC_8_9 }, + { DVBFE_FEC_AUTO, FEC_AUTO }, + { -1, -1 } +}; + +static int dvbfe_dvbt_const_to_kapi[][2] = +{ + { DVBFE_DVBT_CONST_QPSK, FE_QPSK }, + { DVBFE_DVBT_CONST_QAM_16, QAM_16 }, + { DVBFE_DVBT_CONST_QAM_32, QAM_32 }, + { DVBFE_DVBT_CONST_QAM_64, QAM_64 }, + { DVBFE_DVBT_CONST_QAM_128, QAM_128 }, + { DVBFE_DVBT_CONST_QAM_256, QAM_256 }, + { DVBFE_DVBT_CONST_AUTO, QAM_AUTO }, + { -1, -1 } +}; + +static int dvbfe_dvbc_mod_to_kapi[][2] = +{ + { DVBFE_DVBC_MOD_QAM_16, QAM_16 }, + { DVBFE_DVBC_MOD_QAM_32, QAM_32 }, + { DVBFE_DVBC_MOD_QAM_64, QAM_64 }, + { DVBFE_DVBC_MOD_QAM_128, QAM_128 }, + { DVBFE_DVBC_MOD_QAM_256, QAM_256 }, + { DVBFE_DVBC_MOD_AUTO, QAM_AUTO }, + { -1, -1 } +}; + +static int dvbfe_atsc_mod_to_kapi[][2] = +{ + { DVBFE_ATSC_MOD_QAM_64, QAM_64 }, + { DVBFE_ATSC_MOD_QAM_256, QAM_256 }, + { DVBFE_ATSC_MOD_VSB_8, VSB_8 }, + { DVBFE_ATSC_MOD_VSB_16, VSB_16 }, + { DVBFE_ATSC_MOD_AUTO, QAM_AUTO }, + { -1, -1 } +}; + +static int dvbfe_dvbt_transmit_mode_to_kapi[][2] = +{ + { DVBFE_DVBT_TRANSMISSION_MODE_2K, TRANSMISSION_MODE_2K }, + { DVBFE_DVBT_TRANSMISSION_MODE_8K, TRANSMISSION_MODE_8K }, + { DVBFE_DVBT_TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO }, + { -1, -1 } +}; + +static int dvbfe_dvbt_bandwidth_to_kapi[][2] = +{ + { DVBFE_DVBT_BANDWIDTH_8_MHZ, BANDWIDTH_8_MHZ }, + { DVBFE_DVBT_BANDWIDTH_7_MHZ, BANDWIDTH_7_MHZ }, + { DVBFE_DVBT_BANDWIDTH_6_MHZ, BANDWIDTH_6_MHZ }, + { DVBFE_DVBT_BANDWIDTH_AUTO, BANDWIDTH_AUTO }, + { -1, -1 } +}; + +static int dvbfe_dvbt_guard_interval_to_kapi[][2] = +{ + { DVBFE_DVBT_GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_32}, + { DVBFE_DVBT_GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_16}, + { DVBFE_DVBT_GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_8}, + { DVBFE_DVBT_GUARD_INTERVAL_1_4, GUARD_INTERVAL_1_4}, + { DVBFE_DVBT_GUARD_INTERVAL_AUTO, GUARD_INTERVAL_AUTO}, + { -1, -1 } +}; + +static int dvbfe_dvbt_hierarchy_to_kapi[][2] = +{ + { DVBFE_DVBT_HIERARCHY_NONE, HIERARCHY_NONE }, + { DVBFE_DVBT_HIERARCHY_1, HIERARCHY_1 }, + { DVBFE_DVBT_HIERARCHY_2, HIERARCHY_2 }, + { DVBFE_DVBT_HIERARCHY_4, HIERARCHY_4 }, + { DVBFE_DVBT_HIERARCHY_AUTO, HIERARCHY_AUTO }, + { -1, -1 } +}; + + +static int lookupval(int val, int reverse, int table[][2]) +{ + int i =0; + + while(table[i][0] != -1) { + if (!reverse) { + if (val == table[i][0]) { + return table[i][1]; + } + } else { + if (val == table[i][1]) { + return table[i][0]; + } + } + i++; + } + + return -1; +} + + +struct dvbfe_handle { + int fd; + enum dvbfe_type type; + char *name; +}; + +struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly) +{ + char filename[PATH_MAX+1]; + struct dvbfe_handle *fehandle; + int fd; + struct dvb_frontend_info info; + + // flags + int flags = O_RDWR; + if (readonly) { + flags = O_RDONLY; + } + + // open it (try normal /dev structure first) + sprintf(filename, "/dev/dvb/adapter%i/frontend%i", adapter, frontend); + if ((fd = open(filename, flags)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.frontend%i", adapter, frontend); + if ((fd = open(filename, flags)) < 0) { + return NULL; + } + } + + // determine fe type + if (ioctl(fd, FE_GET_INFO, &info)) { + close(fd); + return NULL; + } + + // setup structure + fehandle = (struct dvbfe_handle*) malloc(sizeof(struct dvbfe_handle)); + memset(fehandle, 0, sizeof(struct dvbfe_handle)); + fehandle->fd = fd; + switch(info.type) { + case FE_QPSK: + fehandle->type = DVBFE_TYPE_DVBS; + break; + + case FE_QAM: + fehandle->type = DVBFE_TYPE_DVBC; + break; + + case FE_OFDM: + fehandle->type = DVBFE_TYPE_DVBT; + break; + + case FE_ATSC: + fehandle->type = DVBFE_TYPE_ATSC; + break; + } + fehandle->name = strndup(info.name, sizeof(info.name)); + + // done + return fehandle; +} + +void dvbfe_close(struct dvbfe_handle *fehandle) +{ + close(fehandle->fd); + free(fehandle->name); + free(fehandle); +} + +extern int dvbfe_get_info(struct dvbfe_handle *fehandle, + enum dvbfe_info_mask querymask, + struct dvbfe_info *result, + enum dvbfe_info_querytype querytype, + int timeout) +{ + int returnval = 0; + struct dvb_frontend_event kevent; + int ok = 0; + + result->name = fehandle->name; + result->type = fehandle->type; + + switch(querytype) { + case DVBFE_INFO_QUERYTYPE_IMMEDIATE: + if (querymask & DVBFE_INFO_LOCKSTATUS) { + if (!ioctl(fehandle->fd, FE_READ_STATUS, &kevent.status)) { + returnval |= DVBFE_INFO_LOCKSTATUS; + } + } + if (querymask & DVBFE_INFO_FEPARAMS) { + if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kevent.parameters)) { + returnval |= DVBFE_INFO_FEPARAMS; + } + } + break; + + case DVBFE_INFO_QUERYTYPE_LOCKCHANGE: + { + struct pollfd pollfd; + pollfd.fd = fehandle->fd; + pollfd.events = POLLIN | POLLERR; + + ok = 1; + if (poll(&pollfd, 1, timeout) < 0) + ok = 0; + if (pollfd.revents & POLLERR) + ok = 0; + if (!(pollfd.revents & POLLIN)) + ok = 0; + } + + if (ok && + ((querymask & DVBFE_INFO_LOCKSTATUS) || + (querymask & DVBFE_INFO_FEPARAMS))) { + if (!ioctl(fehandle->fd, FE_GET_EVENT, &kevent)) { + if (querymask & DVBFE_INFO_LOCKSTATUS) + returnval |= DVBFE_INFO_LOCKSTATUS; + if (querymask & DVBFE_INFO_FEPARAMS) + returnval |= DVBFE_INFO_FEPARAMS; + } + } + break; + } + + if (returnval & DVBFE_INFO_LOCKSTATUS) { + result->signal = kevent.status & FE_HAS_SIGNAL ? 1 : 0; + result->carrier = kevent.status & FE_HAS_CARRIER ? 1 : 0; + result->viterbi = kevent.status & FE_HAS_VITERBI ? 1 : 0; + result->sync = kevent.status & FE_HAS_SYNC ? 1 : 0; + result->lock = kevent.status & FE_HAS_LOCK ? 1 : 0; + } + + if (returnval & DVBFE_INFO_FEPARAMS) { + result->feparams.frequency = kevent.parameters.frequency; + result->feparams.inversion = lookupval(kevent.parameters.inversion, 1, dvbfe_spectral_inversion_to_kapi); + switch(fehandle->type) { + case FE_QPSK: + result->feparams.u.dvbs.symbol_rate = kevent.parameters.u.qpsk.symbol_rate; + result->feparams.u.dvbs.fec_inner = + lookupval(kevent.parameters.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi); + break; + + case FE_QAM: + result->feparams.u.dvbc.symbol_rate = kevent.parameters.u.qam.symbol_rate; + result->feparams.u.dvbc.fec_inner = + lookupval(kevent.parameters.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbc.modulation = + lookupval(kevent.parameters.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi); + break; + + case FE_OFDM: + result->feparams.u.dvbt.bandwidth = + lookupval(kevent.parameters.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi); + result->feparams.u.dvbt.code_rate_HP = + lookupval(kevent.parameters.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbt.code_rate_LP = + lookupval(kevent.parameters.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbt.constellation = + lookupval(kevent.parameters.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi); + result->feparams.u.dvbt.transmission_mode = + lookupval(kevent.parameters.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi); + result->feparams.u.dvbt.guard_interval = + lookupval(kevent.parameters.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi); + result->feparams.u.dvbt.hierarchy_information = + lookupval(kevent.parameters.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi); + break; + + case FE_ATSC: + result->feparams.u.atsc.modulation = + lookupval(kevent.parameters.u.vsb.modulation, 1, dvbfe_atsc_mod_to_kapi); + break; + } + } + + if (querymask & DVBFE_INFO_BER) { + if (!ioctl(fehandle->fd, FE_READ_BER, &result->ber)) + returnval |= DVBFE_INFO_BER; + } + if (querymask & DVBFE_INFO_SIGNAL_STRENGTH) { + if (!ioctl(fehandle->fd, FE_READ_SIGNAL_STRENGTH, &result->signal_strength)) + returnval |= DVBFE_INFO_SIGNAL_STRENGTH; + } + if (querymask & DVBFE_INFO_SNR) { + if (!ioctl(fehandle->fd, FE_READ_SNR, &result->snr)) + returnval |= DVBFE_INFO_SNR; + } + if (querymask & DVBFE_INFO_UNCORRECTED_BLOCKS) { + if (!ioctl(fehandle->fd, FE_READ_UNCORRECTED_BLOCKS, &result->ucblocks)) + returnval |= DVBFE_INFO_UNCORRECTED_BLOCKS; + } + + // done + return returnval; +} + +int dvbfe_set(struct dvbfe_handle *fehandle, + struct dvbfe_parameters *params, + int timeout) +{ + struct dvb_frontend_parameters kparams; + int res; + struct timeval endtime; + fe_status_t status; + + kparams.frequency = params->frequency; + kparams.inversion = lookupval(params->inversion, 0, dvbfe_spectral_inversion_to_kapi); + switch(fehandle->type) { + case FE_QPSK: + kparams.u.qpsk.symbol_rate = params->u.dvbs.symbol_rate; + kparams.u.qpsk.fec_inner = lookupval(params->u.dvbs.fec_inner, 0, dvbfe_code_rate_to_kapi); + break; + + case FE_QAM: + kparams.u.qam.symbol_rate = params->u.dvbc.symbol_rate; + kparams.u.qam.fec_inner = lookupval(params->u.dvbc.fec_inner, 0, dvbfe_code_rate_to_kapi); + kparams.u.qam.modulation = lookupval(params->u.dvbc.modulation, 0, dvbfe_dvbc_mod_to_kapi); + break; + + case FE_OFDM: + kparams.u.ofdm.bandwidth = lookupval(params->u.dvbt.bandwidth, 0, dvbfe_dvbt_bandwidth_to_kapi); + kparams.u.ofdm.code_rate_HP = lookupval(params->u.dvbt.code_rate_HP, 0, dvbfe_code_rate_to_kapi); + kparams.u.ofdm.code_rate_LP = lookupval(params->u.dvbt.code_rate_LP, 0, dvbfe_code_rate_to_kapi); + kparams.u.ofdm.constellation = lookupval(params->u.dvbt.constellation, 0, dvbfe_dvbt_const_to_kapi); + kparams.u.ofdm.transmission_mode = + lookupval(params->u.dvbt.transmission_mode, 0, dvbfe_dvbt_transmit_mode_to_kapi); + kparams.u.ofdm.guard_interval = + lookupval(params->u.dvbt.guard_interval, 0, dvbfe_dvbt_guard_interval_to_kapi); + kparams.u.ofdm.hierarchy_information = + lookupval(params->u.dvbt.hierarchy_information, 0, dvbfe_dvbt_hierarchy_to_kapi); + break; + + case FE_ATSC: + kparams.u.vsb.modulation = lookupval(params->u.atsc.modulation, 0, dvbfe_atsc_mod_to_kapi); + break; + + default: + return -EINVAL; + } + + // set it and check for error + res = ioctl(fehandle->fd, FE_SET_FRONTEND, &kparams); + if (res) + return res; + + // 0 => return immediately + if (timeout == 0) { + return 0; + } + + /* calculate timeout */ + if (timeout > 0) { + gettimeofday(&endtime, NULL); + timeout *= 1000; + endtime.tv_sec += timeout / 1000000; + endtime.tv_usec += timeout % 1000000; + } + + /* wait for a lock */ + while(1) { + /* has it locked? */ + if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) { + if (status & FE_HAS_LOCK) { + break; + } + } + + /* check for timeout */ + if (timeout > 0) { + struct timeval curtime; + gettimeofday(&curtime, NULL); + if ((curtime.tv_sec > endtime.tv_sec) || + ((curtime.tv_sec == endtime.tv_sec) && (curtime.tv_usec >= endtime.tv_usec))) { + break; + } + } + + /* delay for a bit */ + usleep(100000); + } + + /* exit */ + if (status & FE_HAS_LOCK) + return 0; + return -ETIMEDOUT; +} + +int dvbfe_get_pollfd(struct dvbfe_handle *handle) +{ + return handle->fd; +} + +int dvbfe_set_22k_tone(struct dvbfe_handle *fehandle, enum dvbfe_sec_tone_mode tone) +{ + int ret = 0; + + switch (tone) { + case DVBFE_SEC_TONE_OFF: + ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF); + break; + case DVBFE_SEC_TONE_ON: + ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON); + break; + default: + print(verbose, ERROR, 1, "Invalid command !"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed !"); + + return ret; +} + +int dvbfe_set_tone_data_burst(struct dvbfe_handle *fehandle, enum dvbfe_sec_mini_cmd minicmd) +{ + int ret = 0; + + switch (minicmd) { + case DVBFE_SEC_MINI_A: + ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A); + break; + case DVBFE_SEC_MINI_B: + ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B); + break; + default: + print(verbose, ERROR, 1, "Invalid command"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + + return ret; +} + +int dvbfe_set_voltage(struct dvbfe_handle *fehandle, enum dvbfe_sec_voltage voltage) +{ + int ret = 0; + + switch (voltage) { + case DVBFE_SEC_VOLTAGE_OFF: + ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF); + break; + case DVBFE_SEC_VOLTAGE_13: + ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13); + break; + case DVBFE_SEC_VOLTAGE_18: + ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18); + break; + default: + print(verbose, ERROR, 1, "Invalid command"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + + return ret; +} + +int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on) +{ + switch (on) { + case 0: + ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0); + break; + default: + ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1); + break; + } + return 0; +} + +int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *fehandle, unsigned int cmd) +{ + int ret = 0; + + ret = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd); + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + + return ret; +} + +int dvbfe_do_diseqc_command(struct dvbfe_handle *fehandle, uint8_t *data, uint8_t len) +{ + int ret = 0; + struct dvb_diseqc_master_cmd diseqc_message; + + if (len > 6) + return -EINVAL; + + diseqc_message.msg_len = len; + memcpy(diseqc_message.msg, data, len); + + ret = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &diseqc_message); + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + + return ret; +} + +int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len) +{ + struct dvb_diseqc_slave_reply reply; + int result; + + if (len > 4) + len = 4; + + reply.timeout = timeout; + reply.msg_len = len; + + if ((result = ioctl(fehandle->fd, FE_DISEQC_RECV_SLAVE_REPLY, reply)) != 0) + return result; + + if (reply.msg_len < len) + len = reply.msg_len; + memcpy(buf, reply.msg, len); + + return len; +} diff --git a/lib/libdvbapi/dvbfe.h b/lib/libdvbapi/dvbfe.h new file mode 100644 index 0000000..69cb05b --- /dev/null +++ b/lib/libdvbapi/dvbfe.h @@ -0,0 +1,333 @@ +/* + * libdvbfe - a DVB frontend library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2005 Manu Abraham + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBFE_H +#define LIBDVBFE_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * The types of frontend we support. + */ +enum dvbfe_type { + DVBFE_TYPE_DVBS, + DVBFE_TYPE_DVBC, + DVBFE_TYPE_DVBT, + DVBFE_TYPE_ATSC, +}; + +enum dvbfe_spectral_inversion { + DVBFE_INVERSION_OFF, + DVBFE_INVERSION_ON, + DVBFE_INVERSION_AUTO +}; + +enum dvbfe_code_rate { + DVBFE_FEC_NONE, + DVBFE_FEC_1_2, + DVBFE_FEC_2_3, + DVBFE_FEC_3_4, + DVBFE_FEC_4_5, + DVBFE_FEC_5_6, + DVBFE_FEC_6_7, + DVBFE_FEC_7_8, + DVBFE_FEC_8_9, + DVBFE_FEC_AUTO +}; + +enum dvbfe_dvbt_const { + DVBFE_DVBT_CONST_QPSK, + DVBFE_DVBT_CONST_QAM_16, + DVBFE_DVBT_CONST_QAM_32, + DVBFE_DVBT_CONST_QAM_64, + DVBFE_DVBT_CONST_QAM_128, + DVBFE_DVBT_CONST_QAM_256, + DVBFE_DVBT_CONST_AUTO +}; + +enum dvbfe_dvbc_mod { + DVBFE_DVBC_MOD_QAM_16, + DVBFE_DVBC_MOD_QAM_32, + DVBFE_DVBC_MOD_QAM_64, + DVBFE_DVBC_MOD_QAM_128, + DVBFE_DVBC_MOD_QAM_256, + DVBFE_DVBC_MOD_AUTO, +}; + +enum dvbfe_atsc_mod { + DVBFE_ATSC_MOD_QAM_64, + DVBFE_ATSC_MOD_QAM_256, + DVBFE_ATSC_MOD_VSB_8, + DVBFE_ATSC_MOD_VSB_16, + DVBFE_ATSC_MOD_AUTO +}; + +enum dvbfe_dvbt_transmit_mode { + DVBFE_DVBT_TRANSMISSION_MODE_2K, + DVBFE_DVBT_TRANSMISSION_MODE_8K, + DVBFE_DVBT_TRANSMISSION_MODE_AUTO +}; + +enum dvbfe_dvbt_bandwidth { + DVBFE_DVBT_BANDWIDTH_8_MHZ, + DVBFE_DVBT_BANDWIDTH_7_MHZ, + DVBFE_DVBT_BANDWIDTH_6_MHZ, + DVBFE_DVBT_BANDWIDTH_AUTO +}; + +enum dvbfe_dvbt_guard_interval { + DVBFE_DVBT_GUARD_INTERVAL_1_32, + DVBFE_DVBT_GUARD_INTERVAL_1_16, + DVBFE_DVBT_GUARD_INTERVAL_1_8, + DVBFE_DVBT_GUARD_INTERVAL_1_4, + DVBFE_DVBT_GUARD_INTERVAL_AUTO +}; + +enum dvbfe_dvbt_hierarchy { + DVBFE_DVBT_HIERARCHY_NONE, + DVBFE_DVBT_HIERARCHY_1, + DVBFE_DVBT_HIERARCHY_2, + DVBFE_DVBT_HIERARCHY_4, + DVBFE_DVBT_HIERARCHY_AUTO +}; + +/** + * Structure used to store and communicate frontend parameters. + */ +struct dvbfe_parameters { + uint32_t frequency; + enum dvbfe_spectral_inversion inversion; + union { + struct { + uint32_t symbol_rate; + enum dvbfe_code_rate fec_inner; + } dvbs; + + struct { + uint32_t symbol_rate; + enum dvbfe_code_rate fec_inner; + enum dvbfe_dvbc_mod modulation; + } dvbc; + + struct { + enum dvbfe_dvbt_bandwidth bandwidth; + enum dvbfe_code_rate code_rate_HP; + enum dvbfe_code_rate code_rate_LP; + enum dvbfe_dvbt_const constellation; + enum dvbfe_dvbt_transmit_mode transmission_mode; + enum dvbfe_dvbt_guard_interval guard_interval; + enum dvbfe_dvbt_hierarchy hierarchy_information; + } dvbt; + + struct { + enum dvbfe_atsc_mod modulation; + } atsc; + } u; +}; + +enum dvbfe_sec_voltage { + DVBFE_SEC_VOLTAGE_13, + DVBFE_SEC_VOLTAGE_18, + DVBFE_SEC_VOLTAGE_OFF +}; + +enum dvbfe_sec_tone_mode { + DVBFE_SEC_TONE_ON, + DVBFE_SEC_TONE_OFF +}; + +enum dvbfe_sec_mini_cmd { + DVBFE_SEC_MINI_A, + DVBFE_SEC_MINI_B +}; + +/** + * Mask of values used in the dvbfe_get_info() call. + */ +enum dvbfe_info_mask { + DVBFE_INFO_LOCKSTATUS = 0x01, + DVBFE_INFO_FEPARAMS = 0x02, + DVBFE_INFO_BER = 0x04, + DVBFE_INFO_SIGNAL_STRENGTH = 0x08, + DVBFE_INFO_SNR = 0x10, + DVBFE_INFO_UNCORRECTED_BLOCKS = 0x20, +}; + +/** + * Structure containing values used by the dvbfe_get_info() call. + */ +struct dvbfe_info { + enum dvbfe_type type; /* always retrieved */ + const char *name; /* always retrieved */ + unsigned int signal : 1; /* } DVBFE_INFO_LOCKSTATUS */ + unsigned int carrier : 1; /* } */ + unsigned int viterbi : 1; /* } */ + unsigned int sync : 1; /* } */ + unsigned int lock : 1; /* } */ + struct dvbfe_parameters feparams; /* DVBFE_INFO_FEPARAMS */ + uint32_t ber; /* DVBFE_INFO_BER */ + uint16_t signal_strength; /* DVBFE_INFO_SIGNAL_STRENGTH */ + uint16_t snr; /* DVBFE_INFO_SNR */ + uint32_t ucblocks; /* DVBFE_INFO_UNCORRECTED_BLOCKS */ +}; + +/** + * Possible types of query used in dvbfe_get_info. + * + * DVBFE_INFO_QUERYTYPE_IMMEDIATE - interrogate frontend for most up to date values. + * DVBFE_INFO_QUERYTYPE_LOCKCHANGE - return details from queued lock status + * change events, or wait for one to occur + * if none are queued. + */ +enum dvbfe_info_querytype { + DVBFE_INFO_QUERYTYPE_IMMEDIATE, + DVBFE_INFO_QUERYTYPE_LOCKCHANGE, +}; + + +/** + * Frontend handle datatype. + */ +struct dvbfe_handle; + +/** + * Open a DVB frontend. + * + * @param adapter DVB adapter ID. + * @param frontend Frontend ID of that adapter to open. + * @param readonly If 1, frontend will be opened in readonly mode only. + * @return A handle on success, or NULL on failure. + */ +extern struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly); + +/** + * Close a DVB frontend. + * + * @param fehandle Handle opened with dvbfe_open(). + */ +extern void dvbfe_close(struct dvbfe_handle *handle); + +/** + * Set the frontend tuning parameters. + * + * Note: this function provides only the basic tuning operation; you might want to + * investigate dvbfe_set_sec() in sec.h for a unified device tuning operation. + * + * @param fehandle Handle opened with dvbfe_open(). + * @param params Params to set. + * @param timeout <0 => wait forever for lock. 0=>return immediately, >0=> + * number of milliseconds to wait for a lock. + * @return 0 on locked (or if timeout==0 and everything else worked), or + * nonzero on failure (including no lock). + */ +extern int dvbfe_set(struct dvbfe_handle *fehandle, + struct dvbfe_parameters *params, + int timeout); + +/** + * Retrieve information about the frontend. + * + * @param fehandle Handle opened with dvbfe_open(). + * @param querymask ORed bitmask of desired DVBFE_INFO_* values. + * @param result Where to put the retrieved results. + * @param querytype Type of query requested. + * @param timeout Timeout in ms to use if querytype==lockchange (0=>no timeout, <0=> wait forever). + * @return ORed bitmask of DVBFE_INFO_* indicating which values were read successfully. + */ +extern int dvbfe_get_info(struct dvbfe_handle *fehandle, + enum dvbfe_info_mask querymask, + struct dvbfe_info *result, + enum dvbfe_info_querytype querytype, + int timeout); + +/** + * Get a file descriptor for polling for lock status changes. + * + * @param fehandle Handle opened with dvbfe_open(). + * @return FD for polling. + */ +extern int dvbfe_get_pollfd(struct dvbfe_handle *handle); + +/** + * Tone/Data Burst control + * @param fehandle Handle opened with dvbfe_open(). + * @param tone, SEC_TONE_ON/SEC_TONE_OFF + */ +extern int dvbfe_set_22k_tone(struct dvbfe_handle *handle, enum dvbfe_sec_tone_mode tone); + +/** + * 22khz Tone control + * @param fehandle Handle opened with dvbfe_open(). + * @param adapter, minicmd, SEC_MINI_A/SEC_MINI_B + */ +extern int dvbfe_set_tone_data_burst(struct dvbfe_handle *handle, enum dvbfe_sec_mini_cmd minicmd); + +/** + * Voltage control + * @param fehandle Handle opened with dvbfe_open(). + * @param polarization, SEC_VOLTAGE_13/SEC_VOLTAGE_18/SEC_VOLTAGE_OFF + */ +extern int dvbfe_set_voltage(struct dvbfe_handle *handle, enum dvbfe_sec_voltage voltage); + +/** + * High LNB voltage control (increases voltage by 1v to compensate for long cables) + * @param fehandle Handle opened with dvbfe_open(). + * @param on 1 to enable, 0 to disable. + */ +extern int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on); + +/** + * Send a legacy Dish Networks command + * @param fehandle Handle opened with dvbfe_open(). + * @param cmd, the command to send + */ +extern int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *handle, unsigned int cmd); + +/** + * Send a DiSEqC Command + * @param fehandle Handle opened with dvbfe_open(). + * @param data, a pointer to am array containing the data to be sent. + * @param len Length of data in bytes, max 6 bytes. + */ +extern int dvbfe_do_diseqc_command(struct dvbfe_handle *handle, uint8_t *data, uint8_t len); + +/** + * Read a DISEQC response from the frontend. + * + * @param fehandle Handle opened with dvbfe_open(). + * @param timeout Timeout for DISEQC response. + * @param buf Buffer to store response in. + * @param len Number of bytes in buffer. + * @return >= 0 on success (number of received bytes), <0 on failure. + */ +extern int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBFE_H diff --git a/lib/libdvbapi/dvbnet.c b/lib/libdvbapi/dvbnet.c new file mode 100644 index 0000000..f0f08f9 --- /dev/null +++ b/lib/libdvbapi/dvbnet.c @@ -0,0 +1,104 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbnet.h" + +int dvbnet_open(int adapter, int netdeviceid) +{ + char filename[PATH_MAX+1]; + int fd; + + sprintf(filename, "/dev/dvb/adapter%i/net%i", adapter, netdeviceid); + if ((fd = open(filename, O_RDWR)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.net%i", adapter, netdeviceid); + fd = open(filename, O_RDWR); + } + + return fd; +} + +int dvbnet_add_interface(int fd, uint16_t pid, enum dvbnet_encap encapsulation) +{ + struct dvb_net_if params; + int status; + + memset(¶ms, 0, sizeof(params)); + params.pid = pid; + + switch(encapsulation) { + case DVBNET_ENCAP_MPE: + params.feedtype = DVB_NET_FEEDTYPE_MPE; + break; + + case DVBNET_ENCAP_ULE: + params.feedtype = DVB_NET_FEEDTYPE_ULE; + break; + + default: + return -EINVAL; + } + + status = ioctl(fd, NET_ADD_IF, ¶ms); + if (status < 0) + return status; + return params.if_num; +} + +int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation) +{ + struct dvb_net_if info; + int res; + + memset(&info, 0, sizeof(struct dvb_net_if)); + info.if_num = ifnum; + + if ((res = ioctl(fd, NET_GET_IF, &info)) < 0) + return res; + + *pid = info.pid; + switch(info.feedtype) { + case DVB_NET_FEEDTYPE_MPE: + *encapsulation = DVBNET_ENCAP_MPE; + break; + + case DVB_NET_FEEDTYPE_ULE: + *encapsulation = DVBNET_ENCAP_ULE; + break; + + default: + return -EINVAL; + } + return 0; +} + +int dvbnet_remove_interface(int fd, int ifnum) +{ + return ioctl(fd, NET_REMOVE_IF, ifnum); +} diff --git a/lib/libdvbapi/dvbnet.h b/lib/libdvbapi/dvbnet.h new file mode 100644 index 0000000..287919f --- /dev/null +++ b/lib/libdvbapi/dvbnet.h @@ -0,0 +1,87 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBNET_H +#define LIBDVBNET_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * Possible encapsulations of data. + */ +enum dvbnet_encap { + DVBNET_ENCAP_MPE, + DVBNET_ENCAP_ULE, +}; + +/** + * The maximum allowed number of dvb network devices per adapter netdevice. + */ +#define DVBNET_MAX_INTERFACES 10 + +/** + * Open a DVB net interface. + * + * @param adapter DVB adapter ID. + * @param netdeviceid Network control interface of that adapter to open. + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbnet_open(int adapter, int netdeviceid); + +/** + * Create a new DVBNET interface. + * + * @param fd FD opened with libdvbnet_open(). + * @param pid PID of the stream containing the network data. + * @param encapsulation Encapsulation type of the stream (one of DVBNET_ENCAP_*). + * @return Index of new interface on success, < 0 on failure. + */ +extern int dvbnet_add_interface(int fd, uint16_t pid, enum dvbnet_encap encapsulation); + +/** + * Get details of a DVBNET interface. + * + * @param fd FD opened with libdvbnet_open(). + * @param ifnum Index of interface to retrieve. + * @param pid The PID of the interface. + * @param encapsulation The encapsulation of the interface (DVBNET_ENCAP_*). + * @return 0 on success, nonzero on failure. + */ +extern int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation); + +/** + * Remove a DVBNET interface. + * + * @param fd FD opened with libdvbnet_open(). + * @param ifnum Index of interface to remove. + * @return 0 on success, nonzero on failure. + */ +extern int dvbnet_remove_interface(int fd, int ifnum); + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBNET_H diff --git a/lib/libdvbapi/dvbvideo.c b/lib/libdvbapi/dvbvideo.c new file mode 100644 index 0000000..f1ffbe8 --- /dev/null +++ b/lib/libdvbapi/dvbvideo.c @@ -0,0 +1,46 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbvideo.h" + +int dvbvideo_open(int adapter, int videodeviceid) +{ + char filename[PATH_MAX+1]; + int fd; + + sprintf(filename, "/dev/dvb/adapter%i/video%i", adapter, videodeviceid); + if ((fd = open(filename, O_RDWR)) < 0) { + // if that failed, try a flat /dev structure + sprintf(filename, "/dev/dvb%i.video%i", adapter, videodeviceid); + fd = open(filename, O_RDWR); + } + + return fd; +} diff --git a/lib/libdvbapi/dvbvideo.h b/lib/libdvbapi/dvbvideo.h new file mode 100644 index 0000000..cc49914 --- /dev/null +++ b/lib/libdvbapi/dvbvideo.h @@ -0,0 +1,46 @@ +/* + * libdvbnet - a DVB network support library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBDVBVIDEO_H +#define LIBDVBVIDEO_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * Open a DVB video device. + * + * @param adapter DVB adapter ID. + * @param videodeviceid Id of video device of that adapter to open. + * @return A unix file descriptor on success, or -1 on failure. + */ +extern int dvbvideo_open(int adapter, int videodeviceid); + +// FIXME: this is a stub library + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBVIDEO_H -- cgit v1.2.3