diff options
Diffstat (limited to '')
294 files changed, 42375 insertions, 23 deletions
diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..3389628 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,11 @@ +# Makefile for linuxtv.org dvb-apps/lib + +.PHONY: all clean install + +all clean install: +	$(MAKE) -C libdvbapi $@ +	$(MAKE) -C libdvbcfg $@ +	$(MAKE) -C libdvben50221 $@ +	$(MAKE) -C libdvbsec $@ +	$(MAKE) -C libesg $@ +	$(MAKE) -C libucsi $@ 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/dvb/audio.h> +#include <errno.h> +#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 <stdint.h> + +/** + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <linux/dvb/ca.h> +#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 <stdint.h> + +/** + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <linux/dvb/dmx.h> +#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 <stdint.h> + +/** + * 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 <abraham.manu@gmail.com> + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/poll.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <linux/dvb/frontend.h> +#include <libdvbmisc/dvbmisc.h> +#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 <abraham.manu@gmail.com> + * 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 <stdint.h> + +/** + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/dvb/net.h> +#include <errno.h> +#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 <stdint.h> + +/** + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/param.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/types.h> +#include <linux/dvb/video.h> +#include <errno.h> +#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 <stdint.h> + +/** + * 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 diff --git a/lib/libdvbcfg/Makefile b/lib/libdvbcfg/Makefile new file mode 100644 index 0000000..5e5e365 --- /dev/null +++ b/lib/libdvbcfg/Makefile @@ -0,0 +1,18 @@ +# Makefile for linuxtv.org dvb-apps/lib/libdvbcfg + +includes = dvbcfg_zapchannel.h \ +	   dvbcfg_scanfile.h + +objects  = dvbcfg_zapchannel.o \ +	   dvbcfg_scanfile.o \ +	   dvbcfg_common.o + +lib_name = libdvbcfg + +CPPFLAGS += -I../../lib + +.PHONY: all + +all: library + +include ../../Make.rules diff --git a/lib/libdvbcfg/dvbcfg_common.c b/lib/libdvbcfg/dvbcfg_common.c new file mode 100644 index 0000000..1609e51 --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_common.c @@ -0,0 +1,136 @@ +/* + * dvbcfg - support for linuxtv configuration files + * common functions + * + * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com> + * 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 <stdio.h> +#include <string.h> +#include <ctype.h> +#include "dvbcfg_common.h" + +int dvbcfg_parse_int(char **text, char *tokens) +{ +	char *start = *text; +	char *stop = *text; +	int value; + +	while (*stop != '\0') { +		if (strchr(tokens, *stop) != NULL) { +			*stop = '\0'; +			stop++; +			break; +		} +		stop++; +	} + +	if (sscanf(start, "%i", &value) == 1) { +		*text = stop; +		return value; +	} + +	*text = NULL; +	return -1; +} + +int dvbcfg_parse_char(char **text, char *tokens) +{ +	char *start = *text; +	char *stop = *text; +	char value; + +	while (*stop != '\0') { +		if (strchr(tokens, *stop) != NULL) { +			*stop = '\0'; +			stop++; +			break; +		} +		stop++; +	} + +	if (sscanf(start, "%c", &value) == 1) { +		*text = stop; +		return value; +	} + +	*text = NULL; +	return -1; +} + +int dvbcfg_parse_setting(char **text, char *tokens, const struct dvbcfg_setting *settings) +{ +	char *start = *text; +	char *stop = *text; + +	while (*stop != '\0') { +		if (strchr(tokens, *stop) != NULL) { +			*stop = '\0'; +			stop++; +			break; +		} +		stop++; +	} + +	while (settings->name) { +		if (strcmp(start, settings->name) == 0) { +			*text = stop; +			return settings->value; +		} +		settings++; +	} + +	*text = NULL; +	return -1; +} + +void dvbcfg_parse_string(char **text, char *tokens, char *dest, unsigned long size) +{ +	char *start = *text; +	char *stop = *text; +	unsigned long length; + +	while ((*stop != '\0') && (strchr(tokens, *stop) == NULL)) +		stop++; + +	length = (stop - start) + 1; + +	if (length <= size) { +		if (strchr(tokens, *stop) != NULL) { +			*stop = '\0'; +			*text = stop + 1; +		} else +			*text = stop; +			memcpy(dest, start, length); +			return; +	} + +	*text = NULL; +	return; +} + +const char *dvbcfg_lookup_setting(unsigned int setting, const struct dvbcfg_setting *settings) +{ +	while (settings->name) { +		if (setting == settings->value) +			return settings->name; +		settings++; +	} + +	return NULL; +} diff --git a/lib/libdvbcfg/dvbcfg_common.h b/lib/libdvbcfg/dvbcfg_common.h new file mode 100644 index 0000000..2b5e876 --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_common.h @@ -0,0 +1,37 @@ +/* + * dvbcfg - support for linuxtv configuration files + * common functions + * + * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com> + * 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 DVBCFG_COMMON_H +#define DVBCFG_COMMON_H 1 + +struct dvbcfg_setting { +	const char *name; +	unsigned int value; +}; + +extern int dvbcfg_parse_int(char **text, char *tokens); +extern int dvbcfg_parse_char(char **text, char *tokens); +extern int dvbcfg_parse_setting(char **text, char *tokens, const struct dvbcfg_setting *settings); +extern void dvbcfg_parse_string(char **text, char *tokens, char *dest, unsigned long size); +extern const char *dvbcfg_lookup_setting(unsigned int setting, const struct dvbcfg_setting *settings); + +#endif diff --git a/lib/libdvbcfg/dvbcfg_scanfile.c b/lib/libdvbcfg/dvbcfg_scanfile.c new file mode 100644 index 0000000..ec305a4 --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_scanfile.c @@ -0,0 +1,282 @@ +/* + * dvbcfg - support for linuxtv configuration files + * scan channel file support + * + * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com> + * 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 + */ + +#define _GNU_SOURCE + +#include <malloc.h> +#include <ctype.h> + +#include "dvbcfg_scanfile.h" +#include "dvbcfg_common.h" + +static const struct dvbcfg_setting dvbcfg_fec_list[] = { +	{ "1/2",  DVBFE_FEC_1_2  }, +	{ "2/3",  DVBFE_FEC_2_3  }, +	{ "3/4",  DVBFE_FEC_3_4  }, +	{ "4/5",  DVBFE_FEC_4_5  }, +	{ "5/6",  DVBFE_FEC_5_6  }, +	{ "6/7",  DVBFE_FEC_6_7  }, +	{ "7/8",  DVBFE_FEC_7_8  }, +	{ "8/9",  DVBFE_FEC_8_9  }, +	{ "AUTO", DVBFE_FEC_AUTO }, +	{ "NONE", DVBFE_FEC_NONE }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_dvbc_modulation_list[] = { +	{ "QAM16",   DVBFE_DVBC_MOD_QAM_16  }, +	{ "QAM32",   DVBFE_DVBC_MOD_QAM_32  }, +	{ "QAM64",   DVBFE_DVBC_MOD_QAM_64  }, +	{ "QAM128",  DVBFE_DVBC_MOD_QAM_128 }, +	{ "QAM256",  DVBFE_DVBC_MOD_QAM_256 }, +	{ "AUTO", DVBFE_DVBC_MOD_AUTO    }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_bandwidth_list[] = { +	{ "6MHz", DVBFE_DVBT_BANDWIDTH_6_MHZ }, +	{ "7MHz", DVBFE_DVBT_BANDWIDTH_7_MHZ }, +	{ "8MHz", DVBFE_DVBT_BANDWIDTH_8_MHZ }, +	{ "AUTO",  DVBFE_DVBT_BANDWIDTH_AUTO  }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_constellation_list[] = { +	{ "QAM16",   DVBFE_DVBT_CONST_QAM_16  }, +	{ "QAM32",   DVBFE_DVBT_CONST_QAM_32  }, +	{ "QAM64",   DVBFE_DVBT_CONST_QAM_64  }, +	{ "QAM128",  DVBFE_DVBT_CONST_QAM_128 }, +	{ "QAM256",  DVBFE_DVBT_CONST_QAM_256 }, +	{ "QPSK",     DVBFE_DVBT_CONST_QPSK    }, +	{ "AUTO", DVBFE_DVBT_CONST_AUTO    }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_transmission_mode_list[] = { +	{ "2k",   DVBFE_DVBT_TRANSMISSION_MODE_2K   }, +	{ "8k",   DVBFE_DVBT_TRANSMISSION_MODE_8K   }, +	{ "AUTO", DVBFE_DVBT_TRANSMISSION_MODE_AUTO }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_guard_interval_list[] = { +	{ "1/32", DVBFE_DVBT_GUARD_INTERVAL_1_32 }, +	{ "1/16", DVBFE_DVBT_GUARD_INTERVAL_1_16 }, +	{ "1/8",  DVBFE_DVBT_GUARD_INTERVAL_1_8  }, +	{ "1/4",  DVBFE_DVBT_GUARD_INTERVAL_1_4  }, +	{ "AUTO", DVBFE_DVBT_GUARD_INTERVAL_AUTO }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_hierarchy_list[] = { +	{ "1",    DVBFE_DVBT_HIERARCHY_1    }, +	{ "2",    DVBFE_DVBT_HIERARCHY_2    }, +	{ "4",    DVBFE_DVBT_HIERARCHY_4    }, +	{ "AUTO", DVBFE_DVBT_HIERARCHY_AUTO }, +	{ "NONE", DVBFE_DVBT_HIERARCHY_NONE }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_atsc_modulation_list[] = { +	{ "8VSB",    DVBFE_ATSC_MOD_VSB_8   }, +	{ "16VSB",   DVBFE_ATSC_MOD_VSB_16  }, +	{ "QAM64",  DVBFE_ATSC_MOD_QAM_64  }, +	{ "QAM256", DVBFE_ATSC_MOD_QAM_256 }, +	{ NULL, 0 } +}; + +int dvbcfg_scanfile_parse(FILE *file, dvbcfg_scancallback callback, void *private_data) +{ +	char *line_buf = NULL; +	size_t line_size = 0; +	int line_len = 0; +	int ret_val = 0; + +	while ((line_len = getline(&line_buf, &line_size, file)) > 0) { +		char *line_tmp = line_buf; +		char *line_pos = line_buf; +		struct dvbcfg_scanfile tmp; + +		/* remove newline and comments (started with hashes) */ +		while ((*line_tmp != '\0') && (*line_tmp != '\n') && (*line_tmp != '#')) +			line_tmp++; +		*line_tmp = '\0'; + +		/* always use inversion auto */ +		tmp.fe_params.inversion = DVBFE_INVERSION_AUTO; + +		/* parse frontend type */ +		switch(dvbcfg_parse_char(&line_pos, " ")) { +		case 'T': +			tmp.fe_type = DVBFE_TYPE_DVBT; +			break; +		case 'C': +			tmp.fe_type = DVBFE_TYPE_DVBC; +			break; +		case 'S': +			tmp.fe_type = DVBFE_TYPE_DVBS; +			break; +		case 'A': +			tmp.fe_type = DVBFE_TYPE_ATSC; +			break; +		default: +			continue; +		} + +		/* parse frontend specific settings */ +		switch (tmp.fe_type) { +		case DVBFE_TYPE_ATSC: + +			/* parse frequency */ +			tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* modulation */ +			tmp.fe_params.u.atsc.modulation = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_atsc_modulation_list); +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBC: + +			/* parse frequency */ +			tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* symbol rate */ +			tmp.fe_params.u.dvbc.symbol_rate = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* fec */ +			tmp.fe_params.u.dvbc.fec_inner = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* modulation */ +			tmp.fe_params.u.dvbc.modulation = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_dvbc_modulation_list); +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBS: + +			/* parse frequency */ +			tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* polarization */ +			tmp.polarization = tolower(dvbcfg_parse_char(&line_pos, " ")); +			if (!line_pos) +				continue; +			if ((tmp.polarization != 'h') && +			    (tmp.polarization != 'v') && +			    (tmp.polarization != 'l') && +			    (tmp.polarization != 'r')) +				continue; + +			/* symbol rate */ +			tmp.fe_params.u.dvbs.symbol_rate = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* fec */ +			tmp.fe_params.u.dvbc.fec_inner = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBT: + +			/* parse frequency */ +			tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " "); +			if (!line_pos) +				continue; + +			/* bandwidth */ +			tmp.fe_params.u.dvbt.bandwidth = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_bandwidth_list); +			if (!line_pos) +				continue; + +			/* fec hp */ +			tmp.fe_params.u.dvbt.code_rate_HP = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* fec lp */ +			tmp.fe_params.u.dvbt.code_rate_LP = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* constellation */ +			tmp.fe_params.u.dvbt.constellation = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_constellation_list); +			if (!line_pos) +				continue; + +			/* transmission mode */ +			tmp.fe_params.u.dvbt.transmission_mode = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_transmission_mode_list); +			if (!line_pos) +				continue; + +			/* guard interval */ +			tmp.fe_params.u.dvbt.guard_interval = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_guard_interval_list); +			if (!line_pos) +				continue; + +			/* hierarchy */ +			tmp.fe_params.u.dvbt.hierarchy_information = +				dvbcfg_parse_setting(&line_pos, " ", dvbcfg_hierarchy_list); +			if (!line_pos) +				continue; + +			break; +		} + +		/* invoke callback */ +		if ((ret_val = callback(&tmp, private_data)) != 0) { +			if (ret_val < 0) +				ret_val = 0; +			break; +		} +	} + +	if (line_buf) +		free(line_buf); + +	return ret_val; +} diff --git a/lib/libdvbcfg/dvbcfg_scanfile.h b/lib/libdvbcfg/dvbcfg_scanfile.h new file mode 100644 index 0000000..d7a20b1 --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_scanfile.h @@ -0,0 +1,61 @@ +/* + * dvbcfg - support for linuxtv configuration files + * scan channel file support + * + * 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 DVBCFG_SCANFILE_H +#define DVBCFG_SCANFILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libdvbapi/dvbfe.h> +#include <stdio.h> + +struct dvbcfg_scanfile { +	enum dvbfe_type fe_type; +	struct dvbfe_parameters fe_params; +	char polarization; /* l,r,v,h - only used for dvb-s */ +}; + +/** + * Callback used in dvbcfg_scanfile_parse() + * + * @param channel Selected channel + * @param private_data Private data for the callback + * @return 0 to continue, other values to stop (values > 0 are forwarded; see below) + */ +typedef int (*dvbcfg_scancallback)(struct dvbcfg_scanfile *channel, void *private_data); + +/** + * Parse a linuxtv scan file + * + * @param file Linuxtv scan file + * @param callback Callback called for each scan entry + * @param private_data Private data for the callback + * @return on success 0 or value from the callback if it's > 0, error code on failure + */ +extern int dvbcfg_scanfile_parse(FILE *file, dvbcfg_scancallback callback, void *private_data); + +#ifdef __cplusplus +} +#endif + +#endif /* DVBCFG_SCANFILE_H */ diff --git a/lib/libdvbcfg/dvbcfg_zapchannel.c b/lib/libdvbcfg/dvbcfg_zapchannel.c new file mode 100644 index 0000000..2c2605e --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_zapchannel.c @@ -0,0 +1,384 @@ +/* + * dvbcfg - support for linuxtv configuration files + * zap channel file support + * + * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com> + * 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 + */ + +#define _GNU_SOURCE + +#include <malloc.h> +#include <string.h> +#include <ctype.h> + +#include "dvbcfg_zapchannel.h" +#include "dvbcfg_common.h" + +static const struct dvbcfg_setting dvbcfg_inversion_list[] = { +	{ "INVERSION_ON",   DVBFE_INVERSION_ON   }, +	{ "INVERSION_OFF",  DVBFE_INVERSION_OFF  }, +	{ "INVERSION_AUTO", DVBFE_INVERSION_AUTO }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_fec_list[] = { +	{ "FEC_1_2",  DVBFE_FEC_1_2  }, +	{ "FEC_2_3",  DVBFE_FEC_2_3  }, +	{ "FEC_3_4",  DVBFE_FEC_3_4  }, +	{ "FEC_4_5",  DVBFE_FEC_4_5  }, +	{ "FEC_5_6",  DVBFE_FEC_5_6  }, +	{ "FEC_6_7",  DVBFE_FEC_6_7  }, +	{ "FEC_7_8",  DVBFE_FEC_7_8  }, +	{ "FEC_8_9",  DVBFE_FEC_8_9  }, +	{ "FEC_AUTO", DVBFE_FEC_AUTO }, +	{ "FEC_NONE", DVBFE_FEC_NONE }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_dvbc_modulation_list[] = { +	{ "QAM_16",   DVBFE_DVBC_MOD_QAM_16  }, +	{ "QAM_32",   DVBFE_DVBC_MOD_QAM_32  }, +	{ "QAM_64",   DVBFE_DVBC_MOD_QAM_64  }, +	{ "QAM_128",  DVBFE_DVBC_MOD_QAM_128 }, +	{ "QAM_256",  DVBFE_DVBC_MOD_QAM_256 }, +	{ "QAM_AUTO", DVBFE_DVBC_MOD_AUTO    }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_bandwidth_list[] = { +	{ "BANDWIDTH_6_MHZ", DVBFE_DVBT_BANDWIDTH_6_MHZ }, +	{ "BANDWIDTH_7_MHZ", DVBFE_DVBT_BANDWIDTH_7_MHZ }, +	{ "BANDWIDTH_8_MHZ", DVBFE_DVBT_BANDWIDTH_8_MHZ }, +	{ "BANDWIDTH_AUTO",  DVBFE_DVBT_BANDWIDTH_AUTO  }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_constellation_list[] = { +	{ "QAM_16",   DVBFE_DVBT_CONST_QAM_16  }, +	{ "QAM_32",   DVBFE_DVBT_CONST_QAM_32  }, +	{ "QAM_64",   DVBFE_DVBT_CONST_QAM_64  }, +	{ "QAM_128",  DVBFE_DVBT_CONST_QAM_128 }, +	{ "QAM_256",  DVBFE_DVBT_CONST_QAM_256 }, +	{ "QPSK",     DVBFE_DVBT_CONST_QPSK    }, +	{ "QAM_AUTO", DVBFE_DVBT_CONST_AUTO    }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_transmission_mode_list[] = { +	{ "TRANSMISSION_MODE_2K",   DVBFE_DVBT_TRANSMISSION_MODE_2K   }, +	{ "TRANSMISSION_MODE_8K",   DVBFE_DVBT_TRANSMISSION_MODE_8K   }, +	{ "TRANSMISSION_MODE_AUTO", DVBFE_DVBT_TRANSMISSION_MODE_AUTO }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_guard_interval_list[] = { +	{ "GUARD_INTERVAL_1_32", DVBFE_DVBT_GUARD_INTERVAL_1_32 }, +	{ "GUARD_INTERVAL_1_16", DVBFE_DVBT_GUARD_INTERVAL_1_16 }, +	{ "GUARD_INTERVAL_1_8",  DVBFE_DVBT_GUARD_INTERVAL_1_8  }, +	{ "GUARD_INTERVAL_1_4",  DVBFE_DVBT_GUARD_INTERVAL_1_4  }, +	{ "GUARD_INTERVAL_AUTO", DVBFE_DVBT_GUARD_INTERVAL_AUTO }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_hierarchy_list[] = { +	{ "HIERARCHY_1",    DVBFE_DVBT_HIERARCHY_1    }, +	{ "HIERARCHY_2",    DVBFE_DVBT_HIERARCHY_2    }, +	{ "HIERARCHY_4",    DVBFE_DVBT_HIERARCHY_4    }, +	{ "HIERARCHY_AUTO", DVBFE_DVBT_HIERARCHY_AUTO }, +	{ "HIERARCHY_NONE", DVBFE_DVBT_HIERARCHY_NONE }, +	{ NULL, 0 } +}; + +static const struct dvbcfg_setting dvbcfg_atsc_modulation_list[] = { +	{ "8VSB",    DVBFE_ATSC_MOD_VSB_8   }, +	{ "16VSB",   DVBFE_ATSC_MOD_VSB_16  }, +	{ "QAM_64",  DVBFE_ATSC_MOD_QAM_64  }, +	{ "QAM_256", DVBFE_ATSC_MOD_QAM_256 }, +	{ NULL, 0 } +}; + +int dvbcfg_zapchannel_parse(FILE *file, dvbcfg_zapcallback callback, void *private_data) +{ +	char *line_buf = NULL; +	size_t line_size = 0; +	int line_len = 0; +	int ret_val = 0; + +	while ((line_len = getline(&line_buf, &line_size, file)) > 0) { +		char *line_tmp = line_buf; +		char *line_pos = line_buf; +		struct dvbcfg_zapchannel tmp; + +		/* remove newline and comments (started with hashes) */ +		while ((*line_tmp != '\0') && (*line_tmp != '\n') && (*line_tmp != '#')) +			line_tmp++; +		*line_tmp = '\0'; + +		/* parse name */ +		dvbcfg_parse_string(&line_pos, ":", tmp.name, sizeof(tmp.name)); +		if (!line_pos) +			continue; + +		/* parse frequency */ +		tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, ":"); +		if (!line_pos) +			continue; + +		/* try to determine frontend type */ +		if (strstr(line_pos, ":FEC_")) { +			if (strstr(line_pos, ":HIERARCHY_")) +				tmp.fe_type = DVBFE_TYPE_DVBT; +			else +				tmp.fe_type = DVBFE_TYPE_DVBC; +		} else { +			if (strstr(line_pos, "VSB:") || strstr(line_pos, "QAM_")) +				tmp.fe_type = DVBFE_TYPE_ATSC; +			else +				tmp.fe_type = DVBFE_TYPE_DVBS; +		} + +		/* parse frontend specific settings */ +		switch (tmp.fe_type) { +		case DVBFE_TYPE_ATSC: +			/* inversion */ +			tmp.fe_params.inversion = DVBFE_INVERSION_AUTO; + +			/* modulation */ +			tmp.fe_params.u.atsc.modulation = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_atsc_modulation_list); +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBC: +			/* inversion */ +			tmp.fe_params.inversion = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_inversion_list); +			if (!line_pos) +				continue; + +			/* symbol rate */ +			tmp.fe_params.u.dvbc.symbol_rate = dvbcfg_parse_int(&line_pos, ":"); +			if (!line_pos) +				continue; + +			/* fec */ +			tmp.fe_params.u.dvbc.fec_inner = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* modulation */ +			tmp.fe_params.u.dvbc.modulation = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_dvbc_modulation_list); +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBS: +			/* adjust frequency */ +			tmp.fe_params.frequency *= 1000; + +			/* inversion */ +			tmp.fe_params.inversion = DVBFE_INVERSION_AUTO; + +			/* fec */ +			tmp.fe_params.u.dvbs.fec_inner = DVBFE_FEC_AUTO; + +			/* polarization */ +			tmp.polarization = tolower(dvbcfg_parse_char(&line_pos, ":")); +			if (!line_pos) +				continue; +			if ((tmp.polarization != 'h') && +			    (tmp.polarization != 'v') && +			    (tmp.polarization != 'l') && +			    (tmp.polarization != 'r')) +				continue; + +			/* satellite switch position */ +			tmp.diseqc_switch = dvbcfg_parse_int(&line_pos, ":"); +			if (!line_pos) +				continue; + +			/* symbol rate */ +			tmp.fe_params.u.dvbs.symbol_rate = +				dvbcfg_parse_int(&line_pos, ":") * 1000; +			if (!line_pos) +				continue; + +			break; + +		case DVBFE_TYPE_DVBT: +			/* inversion */ +			tmp.fe_params.inversion = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_inversion_list); +			if (!line_pos) +				continue; + +			/* bandwidth */ +			tmp.fe_params.u.dvbt.bandwidth = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_bandwidth_list); +			if (!line_pos) +				continue; + +			/* fec hp */ +			tmp.fe_params.u.dvbt.code_rate_HP = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* fec lp */ +			tmp.fe_params.u.dvbt.code_rate_LP = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list); +			if (!line_pos) +				continue; + +			/* constellation */ +			tmp.fe_params.u.dvbt.constellation = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_constellation_list); +			if (!line_pos) +				continue; + +			/* transmission mode */ +			tmp.fe_params.u.dvbt.transmission_mode = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_transmission_mode_list); +			if (!line_pos) +				continue; + +			/* guard interval */ +			tmp.fe_params.u.dvbt.guard_interval = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_guard_interval_list); +			if (!line_pos) +				continue; + +			/* hierarchy */ +			tmp.fe_params.u.dvbt.hierarchy_information = +				dvbcfg_parse_setting(&line_pos, ":", dvbcfg_hierarchy_list); +			if (!line_pos) +				continue; + +			break; +		} + +		/* parse video and audio pids and service id */ +		tmp.video_pid = dvbcfg_parse_int(&line_pos, ":"); +		if (!line_pos) +			continue; +		tmp.audio_pid = dvbcfg_parse_int(&line_pos, ":"); +		if (!line_pos) +			continue; +		tmp.service_id = dvbcfg_parse_int(&line_pos, ":"); +		if (!line_pos) /* old files don't have a service id */ +			tmp.service_id = 0; + +		/* invoke callback */ +		if ((ret_val = callback(&tmp, private_data)) != 0) { +			if (ret_val < 0) +				ret_val = 0; +			break; +		} +	} + +	if (line_buf) +		free(line_buf); + +	return ret_val; +} + +int dvbcfg_zapchannel_save(FILE *file, dvbcfg_zapcallback callback, void *private_data) +{ +	int ret_val = 0; +	struct dvbcfg_zapchannel tmp; + +	while ((ret_val = callback(&tmp, private_data)) == 0) { +		/* name */ +		if ((ret_val = fprintf(file, "%s:", tmp.name)) < 0) +			return ret_val; + +		/* frontend specific settings */ +		switch (tmp.fe_type) { +		case DVBFE_TYPE_ATSC: +			if ((ret_val = fprintf(file, "%i:%s:", +			    tmp.fe_params.frequency, +			    dvbcfg_lookup_setting(tmp.fe_params.u.atsc.modulation, +						  dvbcfg_atsc_modulation_list))) < 0) +				return ret_val; + +			break; + +		case DVBFE_TYPE_DVBC: +			if ((ret_val = fprintf(file, "%i:%s:%i:%s:%s:", +			    tmp.fe_params.frequency, +			    dvbcfg_lookup_setting(tmp.fe_params.inversion, +						  dvbcfg_inversion_list), +			    tmp.fe_params.u.dvbc.symbol_rate, +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbc.fec_inner, +						  dvbcfg_fec_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbc.modulation, +						  dvbcfg_dvbc_modulation_list))) < 0) +				return ret_val; + +			break; + +		case DVBFE_TYPE_DVBS: +			if ((ret_val = fprintf(file, "%i:%c:%i:%i:", +			    tmp.fe_params.frequency / 1000, +			    tolower(tmp.polarization), +			    tmp.diseqc_switch, +			    tmp.fe_params.u.dvbs.symbol_rate / 1000)) < 0) +				return ret_val; + +			break; +		case DVBFE_TYPE_DVBT: +			if ((ret_val = fprintf(file, "%i:%s:%s:%s:%s:%s:%s:%s:%s:", +			    tmp.fe_params.frequency, +			    dvbcfg_lookup_setting(tmp.fe_params.inversion, +						  dvbcfg_inversion_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.bandwidth, +						  dvbcfg_bandwidth_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.code_rate_HP, +						  dvbcfg_fec_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.code_rate_LP, +						  dvbcfg_fec_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.constellation, +						  dvbcfg_constellation_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.transmission_mode, +						  dvbcfg_transmission_mode_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.guard_interval, +						  dvbcfg_guard_interval_list), +			    dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.hierarchy_information, +						  dvbcfg_hierarchy_list))) < 0) +				return ret_val; + +			break; +		} + +		/* video and audio pids and service id */ +		if ((ret_val = fprintf(file, "%i:%i:%i\n", +		    tmp.video_pid, tmp.audio_pid, tmp.service_id)) < 0) +			return ret_val; + +	} + +	if (ret_val < 0) +		ret_val = 0; + +	return ret_val; +} diff --git a/lib/libdvbcfg/dvbcfg_zapchannel.h b/lib/libdvbcfg/dvbcfg_zapchannel.h new file mode 100644 index 0000000..67ec62e --- /dev/null +++ b/lib/libdvbcfg/dvbcfg_zapchannel.h @@ -0,0 +1,77 @@ +/* + * dvbcfg - support for linuxtv configuration files + * zap channel file support + * + * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com> + * 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 DVBCFG_ZAPCHANNEL_H +#define DVBCFG_ZAPCHANNEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libdvbapi/dvbfe.h> +#include <stdio.h> + +struct dvbcfg_zapchannel { +	char name[128]; +	int video_pid; +	int audio_pid; +	int service_id; +	enum dvbfe_type fe_type; +	struct dvbfe_parameters fe_params; +	char polarization; /* l,r,v,h - only used for dvb-s */ +	int diseqc_switch; /* only used for dvb-s */ +}; + +/** + * Callback used in dvbcfg_zapchannel_parse() and dvbcfg_zapchannel_save() + * + * @param channel Selected channel + * @param private_data Private data for the callback + * @return 0 to continue, other values to stop (values > 0 are forwarded; see below) + */ +typedef int (*dvbcfg_zapcallback)(struct dvbcfg_zapchannel *channel, void *private_data); + +/** + * Parse a linuxtv channel file + * + * @param file Linuxtv channel file + * @param callback Callback called for each channel + * @param private_data Private data for the callback + * @return on success 0 or value from the callback if it's > 0, error code on failure + */ +extern int dvbcfg_zapchannel_parse(FILE *file, dvbcfg_zapcallback callback, void *private_data); + +/** + * Save to a linuxtv channel file + * + * @param file Linuxtv channel file + * @param callback Callback called for each channel + * @param private_data Private data for the callback + * @return on success 0 or value from the callback if it's > 0, error code on failure + */ +extern int dvbcfg_zapchannel_save(FILE *file, dvbcfg_zapcallback callback, void *private_data); + +#ifdef __cplusplus +} +#endif + +#endif /* DVBCFG_ZAPCHANNEL_H */ diff --git a/lib/libdvbcfg/zapchannel.txt b/lib/libdvbcfg/zapchannel.txt new file mode 100644 index 0000000..cdfdb87 --- /dev/null +++ b/lib/libdvbcfg/zapchannel.txt @@ -0,0 +1,72 @@ +/** + * The zapchannel file format specifies tuning parameters for channels. Each line describes + * a single channel, and consists of multiple options separated by ':'. The exact + * format of each line depends on the DVB type of the channel (i.e. DVBS, DVBT, DVBC, or ATSC). + * + * Note: the lines have been split across multiple lines in the following due to length issues. + * + * The format for DVBT channels is: + * + * <name>:<frequency>:<inversion>:<bandwidth>:<fec_hp>:<fec_lp>: + * <constellation>:<transmission>:<guard_interval>:<hierarchy>: + * <video_pid>:<audio_pid>:<channel_number> + * + * 	name: name of the channel + * 	frequency: frequency in Hz + * 	inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO. + * 	bandwidth: one of BANDWIDTH_6_MHZ, BANDWIDTH_7_MHZ, or BANDWIDTH_8_MHZ. + * 	fec_hp: FEC of the high priority stream, one of: FEC_1_2, FEC_2_3, + * 		FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, FEC_8_9, or FEC_AUTO. + * 	fec_lp: FEC of the low priority stream, one of: FEC_1_2, FEC_2_3, + * 		FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, FEC_8_9, FEC_AUTO, or FEC_NONE. + * 	constellation: one of QPSK, QAM_128, QAM_16, QAM_256, QAM_32, or QAM_64. + * 	transmission: one of TRANSMISSION_MODE_2K, or TRANSMISSION_MODE_8K. + * 	guard_interval: one of GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, or GUARD_INTERVAL_1_4. + * 	hierarchy: one of HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, or HIERARCHY_4. + * 	video_pid: PID of the video stream. + * 	audio_pid: PID of the audio stream. + * 	channel_number: Transport stream channel number of the program. + * + * DVBC: + * + * <name>:<frequency>:<inversion>:<symbol_rate>:<fec>: + * <modulation>:<video_pid>:<audio_pid>:<channel_number> + * + * 	name: name of the channel + * 	frequency: frequency in Hz + * 	inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO. + * 	symbol_rate: Symbol rate of the channel in ksyms. + * 	fec: One of: FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, + * 			FEC_7_8, FEC_8_9, or FEC_AUTO. + * 	modulation: one of QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO. + * 	video_pid: PID of the video stream. + * 	audio_pid: PID of the audio stream. + * 	channel_number: Transport stream channel number of the program. + * + * DVBS: + * + * <name>:<frequency>:<polarization>:<satellite_switches>:<symbol_rate>:<video_pid>:<audio_pid>:<channel_number> + * + * 	name: name of the channel + * 	frequency: frequency in kHz + * 	polarization: one of H,V,L, or R. + * 	satellite_switches: Treated as a 2 bit value controlling switches in SEC equipment: + * 		bit 0: controls "satellite switch", 0: A, 1: B + * 		bit 1: controls "switch option", 0: A, 1: B + * 	symbol_rate: Symbol rate of the channel in ksyms. + * 	video_pid: PID of the video stream. + * 	audio_pid: PID of the audio stream. + * 	channel_number: Transport stream channel number of the program. + * + * ATSC: + * + * <name>:<frequency>:<inversion>:<modulation>:<video_pid>:<audio_pid>:<channel_number> + * + * 	name: name of the channel + * 	frequency: frequency in GHz + * 	inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO. + * 	modulation: one of 8VSB, 16VSB, QAM_64, or QAM_256. + * 	video_pid: PID of the video stream. + * 	audio_pid: PID of the audio stream. + * 	channel_number: Transport stream channel number of the program. + */ diff --git a/lib/libdvben50221/Makefile b/lib/libdvben50221/Makefile new file mode 100644 index 0000000..797ea2a --- /dev/null +++ b/lib/libdvben50221/Makefile @@ -0,0 +1,49 @@ +# Makefile for linuxtv.org dvb-apps/lib/libdvben50221 + +includes = asn_1.h                 \ +           en50221_app_ai.h        \ +           en50221_app_auth.h      \ +           en50221_app_ca.h        \ +           en50221_app_datetime.h  \ +           en50221_app_dvb.h       \ +           en50221_app_epg.h       \ +           en50221_app_lowspeed.h  \ +           en50221_app_mmi.h       \ +           en50221_app_rm.h        \ +           en50221_app_smartcard.h \ +           en50221_app_tags.h      \ +           en50221_app_teletext.h  \ +           en50221_app_utils.h     \ +           en50221_errno.h         \ +           en50221_session.h       \ +           en50221_stdcam.h        \ +           en50221_transport.h + +objects  = asn_1.o                 \ +           en50221_app_ai.o        \ +           en50221_app_auth.o      \ +           en50221_app_ca.o        \ +           en50221_app_datetime.o  \ +           en50221_app_dvb.o       \ +           en50221_app_epg.o       \ +           en50221_app_lowspeed.o  \ +           en50221_app_mmi.o       \ +           en50221_app_rm.o        \ +           en50221_app_smartcard.o \ +           en50221_app_teletext.o  \ +           en50221_app_utils.o     \ +           en50221_session.o       \ +           en50221_stdcam.o        \ +           en50221_stdcam_hlci.o   \ +           en50221_stdcam_llci.o   \ +           en50221_transport.o + +lib_name = libdvben50221 + +CPPFLAGS += -I../../lib -DLOG_LEVEL=1 # FIXME + +.PHONY: all + +all: library + +include ../../Make.rules diff --git a/lib/libdvben50221/asn_1.c b/lib/libdvben50221/asn_1.c new file mode 100644 index 0000000..803eb60 --- /dev/null +++ b/lib/libdvben50221/asn_1.c @@ -0,0 +1,83 @@ +/* +	ASN.1 routines, implementation for libdvben50221 +	an implementation for the High Level Common Interface + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include "asn_1.h" + +int asn_1_decode(uint16_t * length, uint8_t * asn_1_array, +		 uint32_t asn_1_array_len) +{ +	uint8_t length_field; + +	if (asn_1_array_len < 1) +		return -1; +	length_field = asn_1_array[0]; + +	if (length_field < 0x80) { +		// there is only one word +		*length = length_field & 0x7f; +		return 1; +	} else if (length_field == 0x81) { +		if (asn_1_array_len < 2) +			return -1; + +		*length = asn_1_array[1]; +		return 2; +	} else if (length_field == 0x82) { +		if (asn_1_array_len < 3) +			return -1; + +		*length = (asn_1_array[1] << 8) | asn_1_array[2]; +		return 3; +	} + +	return -1; +} + +int asn_1_encode(uint16_t length, uint8_t * asn_1_array, +		 uint32_t asn_1_array_len) +{ +	if (length < 0x80) { +		if (asn_1_array_len < 1) +			return -1; + +		asn_1_array[0] = length & 0x7f; +		return 1; +	} else if (length < 0x100) { +		if (asn_1_array_len < 2) +			return -1; + +		asn_1_array[0] = 0x81; +		asn_1_array[1] = length; +		return 2; +	} else { +		if (asn_1_array_len < 3) +			return -1; + +		asn_1_array[0] = 0x82; +		asn_1_array[1] = length >> 8; +		asn_1_array[2] = length; +		return 3; +	} + +	// never reached +} diff --git a/lib/libdvben50221/asn_1.h b/lib/libdvben50221/asn_1.h new file mode 100644 index 0000000..c8774db --- /dev/null +++ b/lib/libdvben50221/asn_1.h @@ -0,0 +1,41 @@ +/* +	ASN.1 routines, implementation for libdvben50221 +	an implementation for the High Level Common Interface + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __ASN_1_H__ +#define __ASN_1_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> + +int asn_1_decode(uint16_t * length, uint8_t * asn_1_array, +		 uint32_t asn_1_array_len); +int asn_1_encode(uint16_t length, uint8_t * asn_1_array, +		 uint32_t asn_1_array_len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_ai.c b/lib/libdvben50221/en50221_app_ai.c new file mode 100644 index 0000000..b7ded66 --- /dev/null +++ b/lib/libdvben50221/en50221_app_ai.c @@ -0,0 +1,191 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_ai.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_ai { +	struct en50221_app_send_functions *funcs; + +	en50221_app_ai_callback callback; +	void *callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_ai_parse_app_info(struct en50221_app_ai *ai, +					 uint8_t slot_id, +					 uint16_t session_number, +					 uint8_t * data, +					 uint32_t data_length); + + +struct en50221_app_ai *en50221_app_ai_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_ai *ai = NULL; + +	// create structure and set it up +	ai = malloc(sizeof(struct en50221_app_ai)); +	if (ai == NULL) { +		return NULL; +	} +	ai->funcs = funcs; +	ai->callback = NULL; + +	pthread_mutex_init(&ai->lock, NULL); + +	// done +	return ai; +} + +void en50221_app_ai_destroy(struct en50221_app_ai *ai) +{ +	pthread_mutex_destroy(&ai->lock); +	free(ai); +} + +void en50221_app_ai_register_callback(struct en50221_app_ai *ai, +				      en50221_app_ai_callback callback, +				      void *arg) +{ +	pthread_mutex_lock(&ai->lock); +	ai->callback = callback; +	ai->callback_arg = arg; +	pthread_mutex_unlock(&ai->lock); +} + +int en50221_app_ai_enquiry(struct en50221_app_ai *ai, +			   uint16_t session_number) +{ +	uint8_t data[4]; + +	data[0] = (TAG_APP_INFO_ENQUIRY >> 16) & 0xFF; +	data[1] = (TAG_APP_INFO_ENQUIRY >> 8) & 0xFF; +	data[2] = TAG_APP_INFO_ENQUIRY & 0xFF; +	data[3] = 0; + +	return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4); +} + +int en50221_app_ai_entermenu(struct en50221_app_ai *ai, +			     uint16_t session_number) +{ +	uint8_t data[4]; + +	data[0] = (TAG_ENTER_MENU >> 16) & 0xFF; +	data[1] = (TAG_ENTER_MENU >> 8) & 0xFF; +	data[2] = TAG_ENTER_MENU & 0xFF; +	data[3] = 0; + +	return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4); +} + +int en50221_app_ai_message(struct en50221_app_ai *ai, +			   uint8_t slot_id, +			   uint16_t session_number, +			   uint32_t resource_id, +			   uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_APP_INFO: +		return en50221_app_ai_parse_app_info(ai, slot_id, +						     session_number, +						     data + 3, +						     data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + + + + + +static int en50221_app_ai_parse_app_info(struct en50221_app_ai *ai, +					 uint8_t slot_id, +					 uint16_t session_number, +					 uint8_t * data, +					 uint32_t data_length) +{ +	// parse the length field +	int length_field_len; +	uint16_t asn_data_length; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return -1; +	} +	// check it +	if (asn_data_length < 6) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *app_info = data + length_field_len; + +	// parse the fields +	uint8_t application_type = app_info[0]; +	uint16_t application_manufacturer = (app_info[1] << 8) | app_info[2]; +	uint16_t manufacturer_code = (app_info[3] << 8) | app_info[4]; +	uint8_t menu_string_length = app_info[5]; +	uint8_t *menu_string = app_info + 6; + +	// check the menu_string_length +	if (menu_string_length > (asn_data_length - 6)) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received bad menu string length - adjusting\n"); +		menu_string_length = asn_data_length - 6; +	} +	// tell the app +	pthread_mutex_lock(&ai->lock); +	en50221_app_ai_callback cb = ai->callback; +	void *cb_arg = ai->callback_arg; +	pthread_mutex_unlock(&ai->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  application_type, application_manufacturer, +			  manufacturer_code, menu_string_length, +			  menu_string); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_ai.h b/lib/libdvben50221/en50221_app_ai.h new file mode 100644 index 0000000..18b5cd2 --- /dev/null +++ b/lib/libdvben50221/en50221_app_ai.h @@ -0,0 +1,136 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_AI_H__ +#define __EN50221_APPLICATION_AI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_AI_RESOURCEID MKRID(2,1,1) + +#define APPLICATION_TYPE_CA 0x01 +#define APPLICATION_TYPE_EPG 0x02 + +/** + * Type definition for application callback function - called when we receive + * an application info object. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Resource id concerned. + * @param application_type Type of application. + * @param application_manufacturer Manufacturer of application. + * @param manufacturer_code Manufacturer specific code. + * @param menu_string_length Length of menu string. + * @param menu_string The menu string itself. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_ai_callback) (void *arg, +					uint8_t slot_id, +					uint16_t session_number, +					uint8_t application_type, +					uint16_t application_manufacturer, +					uint16_t manufacturer_code, +					uint8_t menu_string_length, +					uint8_t * menu_string); + +/** + * Opaque type representing an application information resource. + */ +struct en50221_app_ai; + +/** + * Create an instance of an application information resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_ai *en50221_app_ai_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of an application information resource. + * + * @param ai Instance to destroy. + */ +extern void en50221_app_ai_destroy(struct en50221_app_ai *ai); + +/** + * Register a callback for reception of application_info objects. + * + * @param ai Application information instance. + * @param callback Callback function. + * @param arg Private argument passed during calls to the callback. + */ +extern void en50221_app_ai_register_callback(struct en50221_app_ai *ai, +					     en50221_app_ai_callback, +					     void *arg); + +/** + * send a enquiry for the app_info provided by a module + * + * @param ai Application information instance. + * @param session_number Session to send on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ai_enquiry(struct en50221_app_ai *ai, +				  uint16_t session_number); + +/** + * send a enter_menu tag, this will make the application + * open a new MMI session to provide a Menu, or so. + * + * @param ai Application information instance. + * @param session_number Session to send on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ai_entermenu(struct en50221_app_ai *ai, +				    uint16_t session_number); + +/** + * Pass data received for this resource into it for parsing. + * + * @param ai Application information instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ai_message(struct en50221_app_ai *ai, +				  uint8_t slot_id, +				  uint16_t session_number, +				  uint32_t resource_id, +				  uint8_t *data, +				  uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_auth.c b/lib/libdvben50221/en50221_app_auth.c new file mode 100644 index 0000000..a8902c1 --- /dev/null +++ b/lib/libdvben50221/en50221_app_auth.c @@ -0,0 +1,180 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_auth.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_auth { +	struct en50221_app_send_functions *funcs; + +	en50221_app_auth_request_callback callback; +	void *callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_auth_parse_request(struct en50221_app_auth *private, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint8_t * data, +					  uint32_t data_length); + + +struct en50221_app_auth *en50221_app_auth_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_auth *auth = NULL; + +	// create structure and set it up +	auth = malloc(sizeof(struct en50221_app_auth)); +	if (auth == NULL) { +		return NULL; +	} +	auth->funcs = funcs; +	auth->callback = NULL; + +	pthread_mutex_init(&auth->lock, NULL); + +	// done +	return auth; +} + +void en50221_app_auth_destroy(struct en50221_app_auth *auth) +{ +	pthread_mutex_destroy(&auth->lock); +	free(auth); +} + +void en50221_app_auth_register_request_callback(struct en50221_app_auth *auth, +						en50221_app_auth_request_callback callback, void *arg) +{ +	pthread_mutex_lock(&auth->lock); +	auth->callback = callback; +	auth->callback_arg = arg; +	pthread_mutex_unlock(&auth->lock); +} + +int en50221_app_auth_send(struct en50221_app_auth *auth, +			  uint16_t session_number, +			  uint16_t auth_protocol_id, uint8_t * auth_data, +			  uint32_t auth_data_length) +{ +	uint8_t buf[10]; + +	// the header +	buf[0] = (TAG_AUTH_RESP >> 16) & 0xFF; +	buf[1] = (TAG_AUTH_RESP >> 8) & 0xFF; +	buf[2] = TAG_AUTH_RESP & 0xFF; + +	// encode the length field +	int length_field_len; +	if ((length_field_len = asn_1_encode(auth_data_length + 2, buf + 3, 3)) < 0) { +		return -1; +	} +	// the phase_id +	buf[3 + length_field_len] = auth_protocol_id >> 8; +	buf[3 + length_field_len + 1] = auth_protocol_id; + +	// build the iovecs +	struct iovec iov[2]; +	iov[0].iov_base = buf; +	iov[0].iov_len = 3 + length_field_len + 2; +	iov[1].iov_base = auth_data; +	iov[1].iov_len = auth_data_length; + +	// sendit +	return auth->funcs->send_datav(auth->funcs->arg, session_number, +				       iov, 2); +} + +int en50221_app_auth_message(struct en50221_app_auth *auth, +			     uint8_t slot_id, +			     uint16_t session_number, +			     uint32_t resource_id, +			     uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_AUTH_REQ: +		return en50221_app_auth_parse_request(auth, slot_id, +						      session_number, +						      data + 3, +						      data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + +static int en50221_app_auth_parse_request(struct en50221_app_auth *auth, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint8_t * data, +					  uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length < 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *auth_data = data + length_field_len; + +	// process it +	uint16_t auth_protocol_id = (auth_data[0] << 8) | auth_data[1]; + +	// tell the app +	pthread_mutex_lock(&auth->lock); +	en50221_app_auth_request_callback cb = auth->callback; +	void *cb_arg = auth->callback_arg; +	pthread_mutex_unlock(&auth->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  auth_protocol_id, auth_data + 2, +			  asn_data_length - 2); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_auth.h b/lib/libdvben50221/en50221_app_auth.h new file mode 100644 index 0000000..2b1d2e7 --- /dev/null +++ b/lib/libdvben50221/en50221_app_auth.h @@ -0,0 +1,123 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_auth_H__ +#define __EN50221_APPLICATION_auth_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_AUTH_RESOURCEID MKRID(16,1,1) + +/** + * Type definition for request - called when we receive a auth request from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param auth_protocol_id Auth protocol id. + * @param auth_data Data for the request. + * @param auth_data_lenghth Number of bytes. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_auth_request_callback) (void *arg, +						  uint8_t slot_id, +						  uint16_t session_number, +						  uint16_t auth_protcol_id, +						  uint8_t *auth_data, +						  uint32_t auth_data_length); + +/** + * Opaque type representing a auth resource. + */ +struct en50221_app_auth; + +/** + * Create an instance of the auth resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_auth *en50221_app_auth_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the auth resource. + * + * @param auth Instance to destroy. + */ +extern void en50221_app_auth_destroy(struct en50221_app_auth *auth); + +/** + * Register the callback for when we receive a request. + * + * @param auth auth resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_auth_register_request_callback(struct en50221_app_auth *auth, +						       en50221_app_auth_request_callback callback, +						       void *arg); + +/** + * Send an auth response to the CAM. + * + * @param auth auth resource instance. + * @param session_number Session number to send it on. + * @param auth_protocol_id Auth protocol id. + * @param auth_data Auth data. + * @param auth_data_length Number of bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_auth_send(struct en50221_app_auth *auth, +				 uint16_t session_number, +				 uint16_t auth_protocol_id, +				 uint8_t *auth_data, +				 uint32_t auth_data_length); + +/** + * Pass data received for this resource into it for parsing. + * + * @param auth Authentication instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_auth_message(struct en50221_app_auth *auth, +				    uint8_t slot_id, +				    uint16_t session_number, +				    uint32_t resource_id, +				    uint8_t *data, +				    uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_ca.c b/lib/libdvben50221/en50221_app_ca.c new file mode 100644 index 0000000..22d4499 --- /dev/null +++ b/lib/libdvben50221/en50221_app_ca.c @@ -0,0 +1,631 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include <libucsi/mpeg/descriptor.h> +#include "en50221_app_ca.h" +#include "asn_1.h" + +// tags supported by this resource +#define TAG_CA_INFO_ENQUIRY     0x9f8030 +#define TAG_CA_INFO             0x9f8031 +#define TAG_CA_PMT              0x9f8032 +#define TAG_CA_PMT_REPLY        0x9f8033 + +struct en50221_app_ca { +	struct en50221_app_send_functions *funcs; + +	en50221_app_ca_info_callback ca_info_callback; +	void *ca_info_callback_arg; + +	en50221_app_ca_pmt_reply_callback ca_pmt_reply_callback; +	void *ca_pmt_reply_callback_arg; + +	pthread_mutex_t lock; +}; + +struct ca_pmt_descriptor { +	uint8_t *descriptor; +	uint16_t length; + +	struct ca_pmt_descriptor *next; +}; + +struct ca_pmt_stream { +	uint8_t stream_type; +	uint16_t pid; +	struct ca_pmt_descriptor *descriptors; +	uint32_t descriptors_length; +	uint32_t descriptors_count; + +	struct ca_pmt_stream *next; +}; + +static int en50221_ca_extract_pmt_descriptors(struct mpeg_pmt_section *pmt, +					      struct ca_pmt_descriptor **outdescriptors); +static int en50221_ca_extract_streams(struct mpeg_pmt_section *pmt, +				      struct ca_pmt_stream **outstreams); +static void en50221_ca_try_move_pmt_descriptors(struct ca_pmt_descriptor **pmt_descriptors, +						struct ca_pmt_stream **pmt_streams); +static uint32_t en50221_ca_calculate_length(struct ca_pmt_descriptor *pmt_descriptors, +					    uint32_t *pmt_descriptors_length, +					    struct ca_pmt_stream *pmt_streams); +static int en50221_app_ca_parse_info(struct en50221_app_ca *ca, +				     uint8_t slot_id, +				     uint16_t session_number, +				     uint8_t * data, uint32_t data_length); +static int en50221_app_ca_parse_reply(struct en50221_app_ca *ca, +				      uint8_t slot_id, +				      uint16_t session_number, +				      uint8_t * data, +				      uint32_t data_length); + + + +struct en50221_app_ca *en50221_app_ca_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_ca *ca = NULL; + +	// create structure and set it up +	ca = malloc(sizeof(struct en50221_app_ca)); +	if (ca == NULL) { +		return NULL; +	} +	ca->funcs = funcs; +	ca->ca_info_callback = NULL; +	ca->ca_pmt_reply_callback = NULL; + +	pthread_mutex_init(&ca->lock, NULL); + +	// done +	return ca; +} + +void en50221_app_ca_destroy(struct en50221_app_ca *ca) +{ +	pthread_mutex_destroy(&ca->lock); +	free(ca); +} + +void en50221_app_ca_register_info_callback(struct en50221_app_ca *ca, +					   en50221_app_ca_info_callback +					   callback, void *arg) +{ +	pthread_mutex_lock(&ca->lock); +	ca->ca_info_callback = callback; +	ca->ca_info_callback_arg = arg; +	pthread_mutex_unlock(&ca->lock); +} + +void en50221_app_ca_register_pmt_reply_callback(struct en50221_app_ca *ca, +						en50221_app_ca_pmt_reply_callback +						callback, void *arg) +{ +	pthread_mutex_lock(&ca->lock); +	ca->ca_pmt_reply_callback = callback; +	ca->ca_pmt_reply_callback_arg = arg; +	pthread_mutex_unlock(&ca->lock); +} + +int en50221_app_ca_info_enq(struct en50221_app_ca *ca, +			    uint16_t session_number) +{ +	uint8_t data[4]; + +	data[0] = (TAG_CA_INFO_ENQUIRY >> 16) & 0xFF; +	data[1] = (TAG_CA_INFO_ENQUIRY >> 8) & 0xFF; +	data[2] = TAG_CA_INFO_ENQUIRY & 0xFF; +	data[3] = 0; +	return ca->funcs->send_data(ca->funcs->arg, session_number, data, 4); +} + +int en50221_app_ca_pmt(struct en50221_app_ca *ca, +		       uint16_t session_number, +		       uint8_t * ca_pmt, uint32_t ca_pmt_length) +{ +	uint8_t buf[10]; + +	// set up the tag +	buf[0] = (TAG_CA_PMT >> 16) & 0xFF; +	buf[1] = (TAG_CA_PMT >> 8) & 0xFF; +	buf[2] = TAG_CA_PMT & 0xFF; + +	// encode the length field +	int length_field_len; +	if ((length_field_len = asn_1_encode(ca_pmt_length, buf + 3, 3)) < 0) { +		return -1; +	} +	// build the iovecs +	struct iovec iov[2]; +	iov[0].iov_base = buf; +	iov[0].iov_len = 3 + length_field_len; +	iov[1].iov_base = ca_pmt; +	iov[1].iov_len = ca_pmt_length; + +	// create the data and send it +	return ca->funcs->send_datav(ca->funcs->arg, session_number, iov, 2); +} + +int en50221_app_ca_message(struct en50221_app_ca *ca, +			   uint8_t slot_id, +			   uint16_t session_number, +			   uint32_t resource_id, +			   uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_CA_INFO: +		return en50221_app_ca_parse_info(ca, slot_id, +						 session_number, data + 3, +						 data_length - 3); +	case TAG_CA_PMT_REPLY: +		return en50221_app_ca_parse_reply(ca, slot_id, +						  session_number, data + 3, +						  data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + +int en50221_ca_format_pmt(struct mpeg_pmt_section *pmt, uint8_t * data, +			  uint32_t data_length, int move_ca_descriptors, +			  uint8_t ca_pmt_list_management, +			  uint8_t ca_pmt_cmd_id) +{ +	struct ca_pmt_descriptor *pmt_descriptors = NULL; +	uint32_t pmt_descriptors_length = 0; +	struct ca_pmt_stream *pmt_streams = NULL; +	uint32_t total_required_length = 0; +	struct ca_pmt_descriptor *cur_d; +	struct ca_pmt_stream *cur_s; +	int result = -1; + +	// extract the descriptors and streams +	if (en50221_ca_extract_pmt_descriptors(pmt, &pmt_descriptors)) +		goto cleanup; +	if (en50221_ca_extract_streams(pmt, &pmt_streams)) +		goto cleanup; + +	// try and merge them if we have no PMT descriptors +	if ((pmt_descriptors == NULL) && move_ca_descriptors) { +		en50221_ca_try_move_pmt_descriptors(&pmt_descriptors, +						    &pmt_streams); +	} +	// calculate the length of all descriptors/streams and the total length required +	total_required_length = +	    en50221_ca_calculate_length(pmt_descriptors, +					&pmt_descriptors_length, +					pmt_streams); + +	// ensure we were supplied with enough data +	if (total_required_length > data_length) { +		goto cleanup; +	} +	// format the start of the PMT +	uint32_t data_pos = 0; +	data[data_pos++] = ca_pmt_list_management; +	data[data_pos++] = mpeg_pmt_section_program_number(pmt) >> 8; +	data[data_pos++] = mpeg_pmt_section_program_number(pmt); +	data[data_pos++] = +	    (pmt->head.version_number << 1) | pmt->head. +	    current_next_indicator; +	data[data_pos++] = (pmt_descriptors_length >> 8) & 0x0f; +	data[data_pos++] = pmt_descriptors_length; + +	// append the PMT descriptors +	if (pmt_descriptors_length) { +		data[data_pos++] = ca_pmt_cmd_id; +		cur_d = pmt_descriptors; +		while (cur_d) { +			memcpy(data + data_pos, cur_d->descriptor, +			       cur_d->length); +			data_pos += cur_d->length; +			cur_d = cur_d->next; +		} +	} +	// now, append the streams +	cur_s = pmt_streams; +	while (cur_s) { +		data[data_pos++] = cur_s->stream_type; +		data[data_pos++] = (cur_s->pid >> 8) & 0x1f; +		data[data_pos++] = cur_s->pid; +		data[data_pos++] = (cur_s->descriptors_length >> 8) & 0x0f; +		data[data_pos++] = cur_s->descriptors_length; + +		// append the stream descriptors +		if (cur_s->descriptors_length) { +			data[data_pos++] = ca_pmt_cmd_id; +			cur_d = cur_s->descriptors; +			while (cur_d) { +				memcpy(data + data_pos, cur_d->descriptor, +				       cur_d->length); +				data_pos += cur_d->length; +				cur_d = cur_d->next; +			} +		} +		cur_s = cur_s->next; +	} +	result = data_pos; + + +      cleanup: +	// free the PMT descriptors +	cur_d = pmt_descriptors; +	while (cur_d) { +		struct ca_pmt_descriptor *next = cur_d->next; +		free(cur_d); +		cur_d = next; +	} + +	// free the streams +	cur_s = pmt_streams; +	while (cur_s) { +		struct ca_pmt_stream *next_s = cur_s->next; + +		// free the stream descriptors +		cur_d = cur_s->descriptors; +		while (cur_d) { +			struct ca_pmt_descriptor *next_d = cur_d->next; +			free(cur_d); +			cur_d = next_d; +		} + +		free(cur_s); +		cur_s = next_s; +	} +	return result; +} + + + + + + + +static int en50221_ca_extract_pmt_descriptors(struct mpeg_pmt_section *pmt, +					      struct ca_pmt_descriptor **outdescriptors) +{ +	struct ca_pmt_descriptor *descriptors = NULL; +	struct ca_pmt_descriptor *descriptors_tail = NULL; +	struct ca_pmt_descriptor *cur_d; + +	struct descriptor *cur_descriptor; +	mpeg_pmt_section_descriptors_for_each(pmt, cur_descriptor) { +		if (cur_descriptor->tag == dtag_mpeg_ca) { +			// create a new structure for this one +			struct ca_pmt_descriptor *new_d = +			    malloc(sizeof(struct ca_pmt_descriptor)); +			if (new_d == NULL) { +				goto error_exit; +			} +			new_d->descriptor = (uint8_t *) cur_descriptor; +			new_d->length = cur_descriptor->len + 2; +			new_d->next = NULL; + +			// append it to the list +			if (descriptors == NULL) { +				descriptors = new_d; +			} else { +				descriptors_tail->next = new_d; +			} +			descriptors_tail = new_d; +		} +	} +	*outdescriptors = descriptors; +	return 0; + +error_exit: +	cur_d = descriptors; +	while (cur_d) { +		struct ca_pmt_descriptor *next = cur_d->next; +		free(cur_d); +		cur_d = next; +	} +	return -1; +} + +static int en50221_ca_extract_streams(struct mpeg_pmt_section *pmt, +				      struct ca_pmt_stream **outstreams) +{ +	struct ca_pmt_stream *streams = NULL; +	struct ca_pmt_stream *streams_tail = NULL; +	struct mpeg_pmt_stream *cur_stream; +	struct descriptor *cur_descriptor; +	struct ca_pmt_stream *cur_s; + +	mpeg_pmt_section_streams_for_each(pmt, cur_stream) { +		struct ca_pmt_descriptor *descriptors_tail = NULL; + +		// create a new structure +		struct ca_pmt_stream *new_s = +		    malloc(sizeof(struct ca_pmt_stream)); +		if (new_s == NULL) { +			goto exit_cleanup; +		} +		new_s->stream_type = cur_stream->stream_type; +		new_s->pid = cur_stream->pid; +		new_s->descriptors = NULL; +		new_s->next = NULL; +		new_s->descriptors_count = 0; + +		// append it to the list +		if (streams == NULL) { +			streams = new_s; +		} else { +			streams_tail->next = new_s; +		} +		streams_tail = new_s; + +		// now process the descriptors +		mpeg_pmt_stream_descriptors_for_each(cur_stream, +						     cur_descriptor) { +			if (cur_descriptor->tag == dtag_mpeg_ca) { +				// create a new structure +				struct ca_pmt_descriptor *new_d = +				    malloc(sizeof(struct ca_pmt_descriptor)); +				if (new_d == NULL) { +					goto exit_cleanup; +				} +				new_d->descriptor = +				    (uint8_t *) cur_descriptor; +				new_d->length = cur_descriptor->len + 2; +				new_d->next = NULL; + +				// append it to the list +				if (new_s->descriptors == NULL) { +					new_s->descriptors = new_d; +				} else { +					descriptors_tail->next = new_d; +				} +				descriptors_tail = new_d; +				new_s->descriptors_count++; +			} +		} +	} +	*outstreams = streams; +	return 0; + +exit_cleanup: +	// free the streams +	cur_s = streams; +	while (cur_s) { +		struct ca_pmt_stream *next_s = cur_s->next; + +		// free the stream descriptors +		struct ca_pmt_descriptor *cur_d = cur_s->descriptors; +		while (cur_d) { +			struct ca_pmt_descriptor *next_d = cur_d->next; +			free(cur_d); +			cur_d = next_d; +		} + +		free(cur_s); +		cur_s = next_s; +	} +	return -1; +} + +static void en50221_ca_try_move_pmt_descriptors(struct ca_pmt_descriptor **pmt_descriptors, +						struct ca_pmt_stream **pmt_streams) +{ +	// get the first stream +	struct ca_pmt_stream *first_stream = *pmt_streams; +	if (first_stream == NULL) +		return; + +	// Check that all the other streams with CA descriptors have exactly the same CA descriptors +	struct ca_pmt_stream *cur_stream = first_stream->next; +	while (cur_stream) { +		// if there are differing numbers of descriptors, exit right now +		if (cur_stream->descriptors_count != first_stream->descriptors_count) +			return; + +		// now verify the descriptors match +		struct ca_pmt_descriptor *cur_descriptor = cur_stream->descriptors; +		struct ca_pmt_descriptor *first_cur_descriptor = first_stream->descriptors; +		while (cur_descriptor) { +			// check the descriptors are the same length +			if (cur_descriptor->length != first_cur_descriptor->length) +				return; + +			// check their contents match +			if (memcmp(cur_descriptor->descriptor, +			    	   first_cur_descriptor->descriptor, +				   cur_descriptor->length)) { +				return; +			} +			// move to next +			cur_descriptor = cur_descriptor->next; +			first_cur_descriptor = first_cur_descriptor->next; +		} + +		// move to next +		cur_stream = cur_stream->next; +	} + +	// if we end up here, all descriptors in all streams matched + +	// hook the first stream's descriptors into the PMT's +	*pmt_descriptors = first_stream->descriptors; +	first_stream->descriptors = NULL; +	first_stream->descriptors_count = 0; + +	// now free up all the descriptors in the other streams +	cur_stream = first_stream->next; +	while (cur_stream) { +		struct ca_pmt_descriptor *cur_descriptor = cur_stream->descriptors; +		while (cur_descriptor) { +			struct ca_pmt_descriptor *next = cur_descriptor->next; +			free(cur_descriptor); +			cur_descriptor = next; +		} +		cur_stream->descriptors = NULL; +		cur_stream->descriptors_count = 0; +		cur_stream = cur_stream->next; +	} +} + +static uint32_t en50221_ca_calculate_length(struct ca_pmt_descriptor *pmt_descriptors, +					    uint32_t *pmt_descriptors_length, +					    struct ca_pmt_stream *pmt_streams) +{ +	uint32_t total_required_length = 6;	// header +	struct ca_pmt_stream *cur_s; + +	// calcuate the PMT descriptors length +	(*pmt_descriptors_length) = 0; +	struct ca_pmt_descriptor *cur_d = pmt_descriptors; +	while (cur_d) { +		(*pmt_descriptors_length) += cur_d->length; +		cur_d = cur_d->next; +	} + +	// add on 1 byte for the ca_pmt_cmd_id if we have some descriptors. +	if (*pmt_descriptors_length) +		(*pmt_descriptors_length)++; + +	// update the total required length +	total_required_length += *pmt_descriptors_length; + +	// calculate the length of descriptors in the streams +	cur_s = pmt_streams; +	while (cur_s) { +		// calculate the size of descriptors in this stream +		cur_s->descriptors_length = 0; +		cur_d = cur_s->descriptors; +		while (cur_d) { +			cur_s->descriptors_length += cur_d->length; +			cur_d = cur_d->next; +		} + +		// add on 1 byte for the ca_pmt_cmd_id if we have some descriptors. +		if (cur_s->descriptors_length) +			cur_s->descriptors_length++; + +		// update the total required length; +		total_required_length += 5 + cur_s->descriptors_length; + +		cur_s = cur_s->next; +	} + +	// done +	return total_required_length; +} + +static int en50221_app_ca_parse_info(struct en50221_app_ca *ca, +				     uint8_t slot_id, +				     uint16_t session_number, +				     uint8_t * data, uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	data += length_field_len; + +	// parse +	uint32_t ca_id_count = asn_data_length / 2; + +	// byteswap the IDs +	uint16_t *ids = (uint16_t *) data; +	uint32_t i; +	for (i = 0; i < ca_id_count; i++) { +		bswap16(data); +		data += 2; +	} + +	// tell the app +	pthread_mutex_lock(&ca->lock); +	en50221_app_ca_info_callback cb = ca->ca_info_callback; +	void *cb_arg = ca->ca_info_callback_arg; +	pthread_mutex_unlock(&ca->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, ca_id_count, +			  ids); +	} +	return 0; +} + +static int en50221_app_ca_parse_reply(struct en50221_app_ca *ca, +				      uint8_t slot_id, +				      uint16_t session_number, +				      uint8_t * data, uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length < 4) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	data += length_field_len; +	data_length -= length_field_len; + +	// process the reply table to fix endian issues +	uint32_t pos = 4; +	bswap16(data); +	while (pos < asn_data_length) { +		bswap16(data + pos); +		pos += 3; +	} + +	// tell the app +	pthread_mutex_lock(&ca->lock); +	en50221_app_ca_pmt_reply_callback cb = ca->ca_pmt_reply_callback; +	void *cb_arg = ca->ca_pmt_reply_callback_arg; +	pthread_mutex_unlock(&ca->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  (struct en50221_app_pmt_reply *) data, +			  asn_data_length); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_ca.h b/lib/libdvben50221/en50221_app_ca.h new file mode 100644 index 0000000..7405b06 --- /dev/null +++ b/lib/libdvben50221/en50221_app_ca.h @@ -0,0 +1,264 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_ca_H__ +#define __EN50221_APPLICATION_ca_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> +#include <libucsi/mpeg/pmt_section.h> +#include <libucsi/dvb/descriptor.h> + +#define CA_LIST_MANAGEMENT_MORE     0x00 +#define CA_LIST_MANAGEMENT_FIRST    0x01 +#define CA_LIST_MANAGEMENT_LAST     0x02 +#define CA_LIST_MANAGEMENT_ONLY     0x03 +#define CA_LIST_MANAGEMENT_ADD      0x04 +#define CA_LIST_MANAGEMENT_UPDATE   0x05 + +#define CA_PMT_CMD_ID_OK_DESCRAMBLING   0x01 +#define CA_PMT_CMD_ID_OK_MMI            0x02 +#define CA_PMT_CMD_ID_QUERY             0x03 +#define CA_PMT_CMD_ID_NOT_SELECTED      0x04 + +#define CA_ENABLE_DESCRAMBLING_POSSIBLE                     0x01 +#define CA_ENABLE_DESCRAMBLING_POSSIBLE_PURCHASE            0x02 +#define CA_ENABLE_DESCRAMBLING_POSSIBLE_TECHNICAL           0x03 +#define CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_NO_ENTITLEMENT  0x71 +#define CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_TECHNICAL       0x73 + + +#define EN50221_APP_CA_RESOURCEID MKRID(3,1,1) + +/** + * PMT reply structure. + */ +struct en50221_app_pmt_reply { +	uint16_t program_number; +	EBIT3(uint8_t reserved_1		: 2;, +	      uint8_t version_number		: 5;, + 	      uint8_t current_next_indicator	: 1;); +	EBIT2(uint8_t CA_enable_flag		: 1;, +	      uint8_t CA_enable			: 7;); +	/* struct en50221_app_pmt_stream streams[] */ +} __attribute__ ((packed)); + +/** + * A stream within a pmt reply structure. + */ +struct en50221_app_pmt_stream { +	EBIT2(uint16_t reserved_1		: 3;, +	      uint16_t es_pid			:13;); +	EBIT2(uint8_t CA_enable_flag		: 1;, +	      uint8_t CA_enable			: 7;); +} __attribute__ ((packed)); + +/** + * Convenience iterator for the streams field of the en50221_app_pmt_reply structure. + * + * @param pmt Pointer to the en50221_app_pmt_reply structure. + * @param pos Variable holding a pointer to the current en50221_app_pmt_stream. + * @param size Total size of the PMT reply. + */ +#define en50221_app_pmt_reply_streams_for_each(pmt, pos, size) \ +    for ((pos) = en50221_app_pmt_reply_streams_first(pmt, size); \ +         (pos); \ +         (pos) = en50221_app_pmt_reply_streams_next(pmt, pos, size)) + + +/** + * Type definition for command - called when we receive a ca info response. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param ca_id_count Number of ca_system_ids. + * @param ca_ids Pointer to list of ca_system_ids. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_ca_info_callback) (void *arg, +					     uint8_t slot_id, +					     uint16_t session_number, +					     uint32_t ca_id_count, +					     uint16_t * ca_ids); + +/** + * Type definition for pmt_reply - called when we receive a pmt_reply. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param reply Pointer to a struct en50221_app_pmt_reply. + * @param reply_size Total size of the struct en50221_app_pmt_reply in bytes. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_ca_pmt_reply_callback) (void *arg, +						  uint8_t slot_id, +						  uint16_t session_number, +						  struct en50221_app_pmt_reply *reply, +						  uint32_t reply_size); + +/** + * Opaque type representing a ca resource. + */ +struct en50221_app_ca; + +/** + * Create an instance of the ca resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_ca *en50221_app_ca_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the ca resource. + * + * @param ca Instance to destroy. + */ +extern void en50221_app_ca_destroy(struct en50221_app_ca *ca); + +/** + * Register the callback for when we receive a ca info. + * + * @param ca ca resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_ca_register_info_callback(struct en50221_app_ca *ca, +						  en50221_app_ca_info_callback callback, +						  void *arg); + +/** + * Register the callback for when we receive a pmt_reply. + * + * @param ca ca resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_ca_register_pmt_reply_callback(struct en50221_app_ca *ca, +						       en50221_app_ca_pmt_reply_callback callback, +						       void *arg); + +/** + * Send a ca_info_req to the CAM. + * + * @param ca ca resource instance. + * @param session_number Session number to send it on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ca_info_enq(struct en50221_app_ca *ca, +				   uint16_t session_number); + +/** + * Send a ca_pmt structure to the CAM. + * + * @param ca ca resource instance. + * @param session_number Session number to send it on. + * @param ca_pmt A ca_pmt structure formatted with the en50221_ca_format_pmt() function. + * @param ca_pmt_length Length of ca_pmt structure in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ca_pmt(struct en50221_app_ca *ca, +			      uint16_t session_number, +			      uint8_t * ca_pmt, +			      uint32_t ca_pmt_length); + +/** + * Transform a libucsi PMT into a binary structure for sending to a CAM. + * + * @param pmt The source PMT structure. + * @param data Pointer to data buffer to write it to. + * @param data_length Number of bytes available in data buffer. + * @param move_ca_descriptors If non-zero, will attempt to move CA descriptors + * in order to reduce the size of the formatted CAPMT. + * @param ca_pmt_list_management One of the CA_LIST_MANAGEMENT_*. + * @param ca_pmt_cmd_id One of the CA_PMT_CMD_ID_*. + * @return Number of bytes used, or -1 on error. + */ +extern int en50221_ca_format_pmt(struct mpeg_pmt_section *pmt, +				 uint8_t * data, +				 uint32_t data_length, +				 int move_ca_descriptors, +				 uint8_t ca_pmt_list_management, +				 uint8_t ca_pmt_cmd_id); + +/** + * Pass data received for this resource into it for parsing. + * + * @param ca CA instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_ca_message(struct en50221_app_ca *ca, +				  uint8_t slot_id, +				  uint16_t session_number, +				  uint32_t resource_id, +				  uint8_t *data, +				  uint32_t data_length); + + + + +static inline struct en50221_app_pmt_stream * +	en50221_app_pmt_reply_streams_first(struct en50221_app_pmt_reply *reply, +					    uint32_t reply_size) +{ +	uint32_t pos = sizeof(struct en50221_app_pmt_reply); + +	if (pos >= reply_size) +		return NULL; + +	return (struct en50221_app_pmt_stream *) ((uint8_t *) reply + pos); +} + +static inline struct en50221_app_pmt_stream * +	en50221_app_pmt_reply_streams_next(struct en50221_app_pmt_reply *reply, +					   struct en50221_app_pmt_stream *pos, +					   uint32_t reply_size) +{ +	uint8_t *end = (uint8_t *) reply + reply_size; +	uint8_t *next = +		(uint8_t *) pos + +		sizeof(struct en50221_app_pmt_stream); + +	if (next >= end) +		return NULL; + +	return (struct en50221_app_pmt_stream *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libdvben50221/en50221_app_datetime.c b/lib/libdvben50221/en50221_app_datetime.c new file mode 100644 index 0000000..6777003 --- /dev/null +++ b/lib/libdvben50221/en50221_app_datetime.c @@ -0,0 +1,173 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include <libucsi/dvb/types.h> +#include "en50221_app_datetime.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_datetime { +	struct en50221_app_send_functions *funcs; + +	en50221_app_datetime_enquiry_callback callback; +	void *callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime *datetime, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t * data, +					      uint32_t data_length); + + + +struct en50221_app_datetime *en50221_app_datetime_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_datetime *datetime = NULL; + +	// create structure and set it up +	datetime = malloc(sizeof(struct en50221_app_datetime)); +	if (datetime == NULL) { +		return NULL; +	} +	datetime->funcs = funcs; +	datetime->callback = NULL; + +	pthread_mutex_init(&datetime->lock, NULL); + +	// done +	return datetime; +} + +void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime) +{ +	pthread_mutex_destroy(&datetime->lock); +	free(datetime); +} + +void en50221_app_datetime_register_enquiry_callback(struct en50221_app_datetime *datetime, +						    en50221_app_datetime_enquiry_callback callback, +						    void *arg) +{ +	pthread_mutex_lock(&datetime->lock); +	datetime->callback = callback; +	datetime->callback_arg = arg; +	pthread_mutex_unlock(&datetime->lock); +} + +int en50221_app_datetime_send(struct en50221_app_datetime *datetime, +			      uint16_t session_number, +			      time_t utc_time, int time_offset) +{ +	uint8_t data[11]; +	int data_length; + +	data[0] = (TAG_DATE_TIME >> 16) & 0xFF; +	data[1] = (TAG_DATE_TIME >> 8) & 0xFF; +	data[2] = TAG_DATE_TIME & 0xFF; +	if (time_offset != -1) { +		data[3] = 7; +		unixtime_to_dvbdate(utc_time, data + 4); +		data[9] = time_offset >> 8; +		data[10] = time_offset; +		data_length = 11; +	} else { +		data[3] = 5; +		unixtime_to_dvbdate(utc_time, data + 4); +		data_length = 9; +	} +	return datetime->funcs->send_data(datetime->funcs->arg, +					  session_number, data, +					  data_length); +} + +int en50221_app_datetime_message(struct en50221_app_datetime *datetime, +				 uint8_t slot_id, +				 uint16_t session_number, +				 uint32_t resource_id, +				 uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_DATE_TIME_ENQUIRY: +		return en50221_app_datetime_parse_enquiry(datetime, +							  slot_id, +							  session_number, +							  data + 3, +							  data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + + + + + + + + +static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime *datetime, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t * data, +					      uint32_t data_length) +{ +	// validate data +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t response_interval = data[1]; + +	// tell the app +	pthread_mutex_lock(&datetime->lock); +	en50221_app_datetime_enquiry_callback cb = datetime->callback; +	void *cb_arg = datetime->callback_arg; +	pthread_mutex_unlock(&datetime->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  response_interval); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_datetime.h b/lib/libdvben50221/en50221_app_datetime.h new file mode 100644 index 0000000..4660630 --- /dev/null +++ b/lib/libdvben50221/en50221_app_datetime.h @@ -0,0 +1,119 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_DATETIME_H__ +#define __EN50221_APPLICATION_DATETIME_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_DATETIME_RESOURCEID MKRID(36,1,1) + +/** + * Type definition for enquiry - called when we receive a date/time enquiry from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param response_interval Response interval requested by CAM. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_datetime_enquiry_callback) (void *arg, +						      uint8_t slot_id, +						      uint16_t session_number, +						      uint8_t response_interval); + +/** + * Opaque type representing a datetime resource. + */ +struct en50221_app_datetime; + +/** + * Create an instance of the datetime resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_datetime +	*en50221_app_datetime_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the datetime resource. + * + * @param datetime Instance to destroy. + */ +extern void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime); + +/** + * Register the callback for when we receive a enquiry request. + * + * @param datetime datetime resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_datetime_register_enquiry_callback(struct en50221_app_datetime *datetime, +							   en50221_app_datetime_enquiry_callback callback, +							   void *arg); + +/** + * Send the time to the CAM. + * + * @param datetime datetime resource instance. + * @param session_number Session number to send it on. + * @param utc_time UTC time in unix time format. + * @param time_offset If -1, the field will not be transmitted, otherwise it is the offset between + * UTC and local time in minutes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_datetime_send(struct en50221_app_datetime *datetime, +				     uint16_t session_number, +				     time_t utc_time, +				     int time_offset); + +/** + * Pass data received for this resource into it for parsing. + * + * @param datetime datetime instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_datetime_message(struct en50221_app_datetime *datetime, +					uint8_t slot_id, +					uint16_t session_number, +					uint32_t resource_id, +					uint8_t *data, +					uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_dvb.c b/lib/libdvben50221/en50221_app_dvb.c new file mode 100644 index 0000000..21b2bec --- /dev/null +++ b/lib/libdvben50221/en50221_app_dvb.c @@ -0,0 +1,282 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_dvb.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_dvb { +	struct en50221_app_send_functions *funcs; + +	en50221_app_dvb_tune_callback tune_callback; +	void *tune_callback_arg; + +	en50221_app_dvb_replace_callback replace_callback; +	void *replace_callback_arg; + +	en50221_app_dvb_clear_replace_callback clear_replace_callback; +	void *clear_replace_callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_dvb_parse_tune(struct en50221_app_dvb *dvb, +				      uint8_t slot_id, +				      uint16_t session_number, +				      uint8_t * data, +				      uint32_t data_length); + +static int en50221_app_dvb_parse_replace(struct en50221_app_dvb *dvb, +					 uint8_t slot_id, +					 uint16_t session_number, +					 uint8_t * data, +					 uint32_t data_length); + +static int en50221_app_dvb_parse_clear_replace(struct en50221_app_dvb *dvb, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length); + + + +struct en50221_app_dvb *en50221_app_dvb_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_dvb *dvb = NULL; + +	// create structure and set it up +	dvb = malloc(sizeof(struct en50221_app_dvb)); +	if (dvb == NULL) { +		return NULL; +	} +	dvb->funcs = funcs; +	dvb->tune_callback = NULL; +	dvb->replace_callback = NULL; +	dvb->clear_replace_callback = NULL; + +	pthread_mutex_init(&dvb->lock, NULL); + +	// done +	return dvb; +} + +void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb) +{ +	pthread_mutex_destroy(&dvb->lock); +	free(dvb); +} + +void en50221_app_dvb_register_tune_callback(struct en50221_app_dvb *dvb, +					    en50221_app_dvb_tune_callback callback, +					    void *arg) +{ +	pthread_mutex_lock(&dvb->lock); +	dvb->tune_callback = callback; +	dvb->tune_callback_arg = arg; +	pthread_mutex_unlock(&dvb->lock); +} + +void en50221_app_dvb_register_replace_callback(struct en50221_app_dvb *dvb, +					       en50221_app_dvb_replace_callback callback, +					       void *arg) +{ +	pthread_mutex_lock(&dvb->lock); +	dvb->replace_callback = callback; +	dvb->replace_callback_arg = arg; +	pthread_mutex_unlock(&dvb->lock); +} + +void en50221_app_dvb_register_clear_replace_callback(struct en50221_app_dvb *dvb, +						     en50221_app_dvb_clear_replace_callback callback, +						     void *arg) +{ +	pthread_mutex_lock(&dvb->lock); +	dvb->clear_replace_callback = callback; +	dvb->clear_replace_callback_arg = arg; +	pthread_mutex_unlock(&dvb->lock); +} + +int en50221_app_dvb_ask_release(struct en50221_app_dvb *dvb, +				uint16_t session_number) +{ +	uint8_t data[4]; + +	data[0] = (TAG_ASK_RELEASE >> 16) & 0xFF; +	data[1] = (TAG_ASK_RELEASE >> 8) & 0xFF; +	data[2] = TAG_ASK_RELEASE & 0xFF; +	data[3] = 0; + +	return dvb->funcs->send_data(dvb->funcs->arg, session_number, data, 4); +} + +int en50221_app_dvb_message(struct en50221_app_dvb *dvb, +			    uint8_t slot_id, +			    uint16_t session_number, +			    uint32_t resource_id, +			    uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_TUNE: +		return en50221_app_dvb_parse_tune(dvb, slot_id, +						  session_number, data + 3, +						  data_length - 3); +	case TAG_REPLACE: +		return en50221_app_dvb_parse_replace(dvb, slot_id, +						     session_number, +						     data + 3, +						     data_length - 3); +	case TAG_CLEAR_REPLACE: +		return en50221_app_dvb_parse_clear_replace(dvb, slot_id, +							   session_number, +							   data + 3, +							   data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + + + + + + + + +static int en50221_app_dvb_parse_tune(struct en50221_app_dvb *dvb, +				      uint8_t slot_id, +				      uint16_t session_number, +				      uint8_t * data, uint32_t data_length) +{ +	// validate data +	if (data_length < 9) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 8) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *tune_data = data + 1; + +	// parse it +	uint16_t network_id = (tune_data[0] << 8) | tune_data[1]; +	uint16_t original_network_id = (tune_data[2] << 8) | tune_data[3]; +	uint16_t transport_stream_id = (tune_data[4] << 8) | tune_data[5]; +	uint16_t service_id = (tune_data[6] << 8) | tune_data[7]; + +	// tell the app +	pthread_mutex_lock(&dvb->lock); +	en50221_app_dvb_tune_callback cb = dvb->tune_callback; +	void *cb_arg = dvb->tune_callback_arg; +	pthread_mutex_unlock(&dvb->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, network_id, +			  original_network_id, transport_stream_id, +			  service_id); +	} +	return 0; +} + +static int en50221_app_dvb_parse_replace(struct en50221_app_dvb *dvb, +					 uint8_t slot_id, +					 uint16_t session_number, +					 uint8_t * data, +					 uint32_t data_length) +{ +	// validate data +	if (data_length < 6) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 5) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *replace_data = data + 1; + +	// parse it +	uint8_t replacement_ref = replace_data[0]; +	uint16_t replace_pid = +	    ((replace_data[1] & 0x1f) << 8) | replace_data[2]; +	uint16_t replacement_pid = +	    ((replace_data[3] & 0x1f) << 8) | replace_data[4]; + +	// tell the app +	pthread_mutex_lock(&dvb->lock); +	en50221_app_dvb_replace_callback cb = dvb->replace_callback; +	void *cb_arg = dvb->replace_callback_arg; +	pthread_mutex_unlock(&dvb->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, replacement_ref, +			  replace_pid, replacement_pid); +	} +	return 0; +} + +static int en50221_app_dvb_parse_clear_replace(struct en50221_app_dvb *dvb, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length) +{ +	// validate data +	if (data_length < 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *replace_data = data + 1; + +	// parse it +	uint8_t replacement_ref = replace_data[0]; + +	// tell the app +	pthread_mutex_lock(&dvb->lock); +	en50221_app_dvb_clear_replace_callback cb = +	    dvb->clear_replace_callback; +	void *cb_arg = dvb->clear_replace_callback_arg; +	pthread_mutex_unlock(&dvb->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  replacement_ref); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_dvb.h b/lib/libdvben50221/en50221_app_dvb.h new file mode 100644 index 0000000..be74e6b --- /dev/null +++ b/lib/libdvben50221/en50221_app_dvb.h @@ -0,0 +1,176 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_DVB_H__ +#define __EN50221_APPLICATION_DVB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_DVB_RESOURCEID MKRID(32,1,1) + + +/** + * Type definition for tune - called when we receive a tune request from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param network_id Network id requested by CAM. + * @param original_network_id Original Network id requested by CAM. + * @param transport_stream_id Transport stream id requested by CAM. + * @param service_id Service id requested by CAM. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_dvb_tune_callback) (void *arg, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint16_t network_id, +					      uint32_t original_network_id, +					      uint16_t transport_stream_id, +					      uint16_t service_id); + +/** + * Type definition for replace - called when we receive a replace request from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param replacement_ref Replacement ref. + * @param replaced_pid PID to replace. + * @param replacement_pid PID to replace it with. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_dvb_replace_callback) (void *arg, +						 uint8_t slot_id, +						 uint16_t session_number, +						 uint8_t replacement_ref, +						 uint16_t replaced_pid, +						 uint16_t replacement_pid); + + +/** + * Type definition for clear_replace - called when we receive a clear_replace request from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param replacement_ref Replacement ref. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_dvb_clear_replace_callback) (void *arg, +						       uint8_t slot_id, +						       uint16_t session_number, +						       uint8_t replacement_ref); + + +/** + * Opaque type representing a dvb resource. + */ +struct en50221_app_dvb; + +/** + * Create an instance of the dvb resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_dvb *en50221_app_dvb_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the dvb resource. + * + * @param dvb Instance to destroy. + */ +extern void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb); + +/** + * Register the callback for when we receive a tune request. + * + * @param dvb DVB resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_dvb_register_tune_callback(struct en50221_app_dvb *dvb, +						   en50221_app_dvb_tune_callback callback, +						   void *arg); + +/** + * Register the callback for when we receive a replace request. + * + * @param dvb DVB resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_dvb_register_replace_callback(struct en50221_app_dvb *dvb, +						      en50221_app_dvb_replace_callback callback, +						      void *arg); + +/** + * Register the callback for when we receive a clear replace request. + * + * @param dvb DVB resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_dvb_register_clear_replace_callback(struct en50221_app_dvb *dvb, +							    en50221_app_dvb_clear_replace_callback callback, +							    void *arg); + +/** + * Send an ask release request to the CAM. + * + * @param dvb DVB resource instance. + * @param session_number Session number to send it on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_dvb_ask_release(struct en50221_app_dvb *dvb, +				       uint16_t session_number); + +/** + * Pass data received for this resource into it for parsing. + * + * @param dvb dvb instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_dvb_message(struct en50221_app_dvb *dvb, +				   uint8_t slot_id, +				   uint16_t session_number, +				   uint32_t resource_id, +				   uint8_t *data, +				   uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_epg.c b/lib/libdvben50221/en50221_app_epg.c new file mode 100644 index 0000000..87b4743 --- /dev/null +++ b/lib/libdvben50221/en50221_app_epg.c @@ -0,0 +1,167 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include <libucsi/dvb/types.h> +#include "en50221_app_epg.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_epg { +	struct en50221_app_send_functions *funcs; + +	en50221_app_epg_reply_callback callback; +	void *callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_epg_parse_reply(struct en50221_app_epg *private, +				       uint8_t slot_id, +				       uint16_t session_number, +				       uint8_t * data, +				       uint32_t data_length); + + + +struct en50221_app_epg *en50221_app_epg_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_epg *epg = NULL; + +	// create structure and set it up +	epg = malloc(sizeof(struct en50221_app_epg)); +	if (epg == NULL) { +		return NULL; +	} +	epg->funcs = funcs; +	epg->callback = NULL; + +	pthread_mutex_init(&epg->lock, NULL); + +	// done +	return epg; +} + +void en50221_app_epg_destroy(struct en50221_app_epg *epg) +{ +	pthread_mutex_destroy(&epg->lock); +	free(epg); +} + +void en50221_app_epg_register_enquiry_callback(struct en50221_app_epg *epg, +					       en50221_app_epg_reply_callback callback, +					       void *arg) +{ +	pthread_mutex_lock(&epg->lock); +	epg->callback = callback; +	epg->callback_arg = arg; +	pthread_mutex_unlock(&epg->lock); +} + +int en50221_app_epg_enquire(struct en50221_app_epg *epg, +			    uint16_t session_number, +			    uint8_t command_id, +			    uint16_t network_id, +			    uint16_t original_network_id, +			    uint16_t transport_stream_id, +			    uint16_t service_id, uint16_t event_id) +{ +	uint8_t data[15]; + +	data[0] = (TAG_EPG_ENQUIRY >> 16) & 0xFF; +	data[1] = (TAG_EPG_ENQUIRY >> 8) & 0xFF; +	data[2] = TAG_EPG_ENQUIRY & 0xFF; +	data[3] = 11; +	data[4] = command_id; +	data[5] = network_id >> 8; +	data[6] = network_id; +	data[7] = original_network_id >> 8; +	data[8] = original_network_id; +	data[9] = transport_stream_id >> 8; +	data[10] = transport_stream_id; +	data[11] = service_id >> 8; +	data[12] = service_id; +	data[13] = event_id >> 8; +	data[14] = event_id; +	return epg->funcs->send_data(epg->funcs->arg, session_number, data, 15); +} + +int en50221_app_epg_message(struct en50221_app_epg *epg, +			    uint8_t slot_id, +			    uint16_t session_number, +			    uint32_t resource_id, +			    uint8_t * data, uint32_t data_length) +{ +	struct en50221_app_epg *private = (struct en50221_app_epg *) epg; +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_EPG_REPLY: +		return en50221_app_epg_parse_reply(private, slot_id, +						   session_number, +						   data + 3, +						   data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + +static int en50221_app_epg_parse_reply(struct en50221_app_epg *epg, +				       uint8_t slot_id, +				       uint16_t session_number, +				       uint8_t * data, +				       uint32_t data_length) +{ +	// validate data +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t event_status = data[1]; + +	// tell the app +	pthread_mutex_lock(&epg->lock); +	en50221_app_epg_reply_callback cb = epg->callback; +	void *cb_arg = epg->callback_arg; +	pthread_mutex_unlock(&epg->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, event_status); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_epg.h b/lib/libdvben50221/en50221_app_epg.h new file mode 100644 index 0000000..dcfe9da --- /dev/null +++ b/lib/libdvben50221/en50221_app_epg.h @@ -0,0 +1,138 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_epg_H__ +#define __EN50221_APPLICATION_epg_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EPG_COMMAND_ID_MMI                          0x02 +#define EPG_COMMAND_ID_QUERY                        0x03 + +#define EPG_EVENTSTATUS_ENTITLEMENT_UNKNOWN         0x00 +#define EPG_EVENTSTATUS_ENTITLEMENT_AVAILABLE       0x01 +#define EPG_EVENTSTATUS_ENTITLEMENT_NOT_AVAILABLE   0x02 +#define EPG_EVENTSTATUS_MMI_DIALOGUE_REQUIRED       0x03 +#define EPG_EVENTSTATUS_MMI_COMPLETE_UNKNOWN        0x04 +#define EPG_EVENTSTATUS_MMI_COMPLETE_AVAILABLE      0x05 +#define EPG_EVENTSTATUS_MMI_COMPLETE_NOT_AVAILABLE  0x06 + +#define EN50221_APP_EPG_RESOURCEID(INSTANCE_NUM) MKRID(120,(INSTANCE_NUM),1) + + + +/** + * Type definition for reply - called when we receive an EPG reply from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param event_status One of the EPG_EVENTSTATUS_* values. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_epg_reply_callback) (void *arg, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t event_status); + +/** + * Opaque type representing a epg resource. + */ +struct en50221_app_epg; + +/** + * Create an instance of the epg resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_epg *en50221_app_epg_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the epg resource. + * + * @param epg Instance to destroy. + */ +extern void en50221_app_epg_destroy(struct en50221_app_epg *epg); + +/** + * Register the callback for when we receive a enquiry response. + * + * @param epg epg resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_epg_register_reply_callback(struct en50221_app_epg *epg, +						    en50221_app_epg_reply_callback callback, +						    void *arg); + +/** + * Enquire about the entitlement status for an EPG entry. + * + * @param epg epg resource instance. + * @param session_number Session number to send it on. + * @param command_id One of the EPG_COMMAND_ID_* fields. + * @param network_id Network ID concerned. + * @param original_network_id Original network ID concerned. + * @param transport_stream_id Transport stream ID concerned. + * @param service_id Service ID concerned. + * @param event_id Event ID concerned. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_epg_enquire(struct en50221_app_epg *epg, +				   uint16_t session_number, +				   uint8_t command_id, +				   uint16_t network_id, +				   uint16_t original_network_id, +				   uint16_t transport_stream_id, +				   uint16_t service_id, +				   uint16_t event_id); + +/** + * Pass data received for this resource into it for parsing. + * + * @param epg epg instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_epg_message(struct en50221_app_epg *epg, +				   uint8_t slot_id, +				   uint16_t session_number, +				   uint32_t resource_id, +				   uint8_t *data, +				   uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_lowspeed.c b/lib/libdvben50221/en50221_app_lowspeed.c new file mode 100644 index 0000000..a66598a --- /dev/null +++ b/lib/libdvben50221/en50221_app_lowspeed.c @@ -0,0 +1,533 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_lowspeed.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_lowspeed_session { +	uint16_t session_number; +	uint8_t *block_chain; +	uint32_t block_length; + +	struct en50221_app_lowspeed_session *next; +}; + +struct en50221_app_lowspeed { +	struct en50221_app_send_functions *funcs; + +	en50221_app_lowspeed_command_callback command_callback; +	void *command_callback_arg; + +	en50221_app_lowspeed_send_callback send_callback; +	void *send_callback_arg; + +	struct en50221_app_lowspeed_session *sessions; + +	pthread_mutex_t lock; +}; + +static int en50221_app_lowspeed_parse_connect_on_channel(struct en50221_app_lowspeed_command *command, +							 uint8_t *data, +							 int data_length); +static int en50221_app_lowspeed_parse_command(struct en50221_app_lowspeed *lowspeed, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t *data, +					      uint32_t data_length); +static int en50221_app_lowspeed_parse_send(struct en50221_app_lowspeed *lowspeed, +					   uint8_t slot_id, +					   uint16_t session_number, +					   int more_last, +					   uint8_t *data, +					   uint32_t data_length); + + + +struct en50221_app_lowspeed *en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_lowspeed *lowspeed = NULL; + +	// create structure and set it up +	lowspeed = malloc(sizeof(struct en50221_app_lowspeed)); +	if (lowspeed == NULL) { +		return NULL; +	} +	lowspeed->funcs = funcs; +	lowspeed->command_callback = NULL; +	lowspeed->send_callback = NULL; +	lowspeed->sessions = NULL; + +	pthread_mutex_init(&lowspeed->lock, NULL); + +	// done +	return lowspeed; +} + +void en50221_app_lowspeed_destroy(struct en50221_app_lowspeed *lowspeed) +{ +	struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions; +	while (cur_s) { +		struct en50221_app_lowspeed_session *next = cur_s->next; +		if (cur_s->block_chain) +			free(cur_s->block_chain); +		free(cur_s); +		cur_s = next; +	} + +	pthread_mutex_destroy(&lowspeed->lock); +	free(lowspeed); +} + +void en50221_app_lowspeed_clear_session(struct en50221_app_lowspeed *lowspeed, +					uint16_t session_number) +{ +	pthread_mutex_lock(&lowspeed->lock); +	struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions; +	struct en50221_app_lowspeed_session *prev_s = NULL; +	while (cur_s) { +		if (cur_s->session_number == session_number) { +			if (cur_s->block_chain) +				free(cur_s->block_chain); +			if (prev_s) { +				prev_s->next = cur_s->next; +			} else { +				lowspeed->sessions = cur_s->next; +			} +			free(cur_s); +			return; +		} + +		prev_s = cur_s; +		cur_s = cur_s->next; +	} +	pthread_mutex_unlock(&lowspeed->lock); +} + +void en50221_app_lowspeed_register_command_callback(struct en50221_app_lowspeed *lowspeed, +						    en50221_app_lowspeed_command_callback callback, +						    void *arg) +{ +	pthread_mutex_lock(&lowspeed->lock); +	lowspeed->command_callback = callback; +	lowspeed->command_callback_arg = arg; +	pthread_mutex_unlock(&lowspeed->lock); +} + +void en50221_app_lowspeed_register_send_callback(struct en50221_app_lowspeed *lowspeed, +						 en50221_app_lowspeed_send_callback callback, +						 void *arg) +{ +	pthread_mutex_lock(&lowspeed->lock); +	lowspeed->send_callback = callback; +	lowspeed->send_callback_arg = arg; +	pthread_mutex_unlock(&lowspeed->lock); +} + +int en50221_app_lowspeed_send_comms_reply(struct en50221_app_lowspeed *lowspeed, +					  uint16_t session_number, +					  uint8_t comms_reply_id, +					  uint8_t return_value) +{ +	uint8_t data[6]; + +	data[0] = (TAG_COMMS_REPLY >> 16) & 0xFF; +	data[1] = (TAG_COMMS_REPLY >> 8) & 0xFF; +	data[2] = TAG_COMMS_REPLY & 0xFF; +	data[3] = 2; +	data[4] = comms_reply_id; +	data[5] = return_value; +	return lowspeed->funcs->send_data(lowspeed->funcs->arg, +					  session_number, data, 6); +} + +int en50221_app_lowspeed_send_comms_data(struct en50221_app_lowspeed *lowspeed, +					 uint16_t session_number, +					 uint8_t phase_id, +					 uint32_t tx_data_length, +					 uint8_t * tx_data) +{ +	uint8_t buf[10]; + +	// the spec defines this limit +	if (tx_data_length > 254) { +		return -1; +	} +	// set up the tag +	buf[0] = (TAG_COMMS_RECV_LAST >> 16) & 0xFF; +	buf[1] = (TAG_COMMS_RECV_LAST >> 8) & 0xFF; +	buf[2] = TAG_COMMS_RECV_LAST & 0xFF; + +	// encode the length field +	int length_field_len; +	if ((length_field_len = asn_1_encode(tx_data_length + 1, buf + 3, 3)) < 0) { +		return -1; +	} +	// the phase_id +	buf[3 + length_field_len] = phase_id; + +	// build the iovecs +	struct iovec iov[2]; +	iov[0].iov_base = buf; +	iov[0].iov_len = 3 + length_field_len + 1; +	iov[1].iov_base = tx_data; +	iov[1].iov_len = tx_data_length; + +	// create the data and send it +	return lowspeed->funcs->send_datav(lowspeed->funcs->arg, +					   session_number, iov, 2); +} + +int en50221_app_lowspeed_message(struct en50221_app_lowspeed *lowspeed, +				 uint8_t slot_id, +				 uint16_t session_number, +				 uint32_t resource_id, +				 uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_COMMS_COMMAND: +		return en50221_app_lowspeed_parse_command(lowspeed, +							  slot_id, +							  session_number, +							  data + 3, +							  data_length - 3); +	case TAG_COMMS_SEND_LAST: +		return en50221_app_lowspeed_parse_send(lowspeed, slot_id, +						       session_number, 1, +						       data + 3, +						       data_length - 3); +	case TAG_COMMS_SEND_MORE: +		return en50221_app_lowspeed_parse_send(lowspeed, slot_id, +						       session_number, 0, +						       data + 3, +						       data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + +static int en50221_app_lowspeed_parse_connect_on_channel(struct en50221_app_lowspeed_command *command, +							 uint8_t *data, +							 int data_length) +{ +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// check the tag +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; +	if (tag != TAG_CONNECTION_DESCRIPTOR) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received bad CONNECT_ON_CHANNEL\n"); +		return -1; +	} +	data += 3; +	data_length -= 3; + +	// parse the descriptor-length-field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	data += length_field_len; +	data_length -= length_field_len; + +	// check length field +	if (asn_data_length > data_length) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length < 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// get the descriptor type +	command->u.connect_on_channel.descriptor_type = data[0]; +	data++; +	data_length--; +	asn_data_length--; + +	// deal with the descriptor itself +	switch (command->u.connect_on_channel.descriptor_type) { +	case CONNECTION_DESCRIPTOR_TYPE_TELEPHONE: +	{ +		// get the raw descriptor and validate length +		struct descriptor *d = (struct descriptor *) data; +		if (asn_data_length < 2) { +			print(LOG_LEVEL, ERROR, 1, +				"Received short data\n"); +			return -1; +		} +		if (asn_data_length != (2 + d->len)) { +			print(LOG_LEVEL, ERROR, 1, +				"Received short data\n"); +			return -1; +		} +		if (d->tag != dtag_dvb_telephone) { +			print(LOG_LEVEL, ERROR, 1, +				"Received invalid telephone descriptor\n"); +			return -1; +		} +		// parse the telephone descriptor +		command->u.connect_on_channel.descriptor.telephone = dvb_telephone_descriptor_codec(d); +		if (command->u.connect_on_channel.descriptor.telephone == NULL) { +			print(LOG_LEVEL, ERROR, 1, +				"Received invalid telephone descriptor\n"); +			return -1; +		} +		data += 2 + d->len; +		data_length -= 2 + d->len; +		break; +	} + +	case CONNECTION_DESCRIPTOR_TYPE_CABLE: +		if (asn_data_length != 1) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received short data\n"); +			return -1; +		} +		command->u.connect_on_channel.descriptor.cable_channel_id = data[0]; +		data++; +		data_length--; +		break; +	default: +		print(LOG_LEVEL, ERROR, 1, +		      "Received unknown connection descriptor %02x\n", +		      command->u.connect_on_channel.descriptor_type); +		return -1; +	} + +	// parse the last bit +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	command->u.connect_on_channel.retry_count = data[0]; +	command->u.connect_on_channel.timeout = data[1]; + +	// ok +	return 0; +} + +static int en50221_app_lowspeed_parse_command(struct en50221_app_lowspeed *lowspeed, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t * data, +					      uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length < 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	data += length_field_len; + +	// get command id +	uint8_t command_id = data[0]; +	data++; +	asn_data_length--; + +	// parse the command +	struct en50221_app_lowspeed_command command; +	switch (command_id) { +	case COMMS_COMMAND_ID_CONNECT_ON_CHANNEL: +		if (en50221_app_lowspeed_parse_connect_on_channel +		    (&command, data, asn_data_length)) { +			return -1; +		} +		break; +	case COMMS_COMMAND_ID_SET_PARAMS: +		if (asn_data_length != 2) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received short data\n"); +			return -1; +		} +		command.u.set_params.buffer_size = data[0]; +		command.u.set_params.timeout = data[1]; +		break; +	case COMMS_COMMAND_ID_GET_NEXT_BUFFER: +		if (asn_data_length != 1) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received short data\n"); +			return -1; +		} +		command.u.get_next_buffer.phase_id = data[0]; +		break; + +	case COMMS_COMMAND_ID_DISCONNECT_ON_CHANNEL: +	case COMMS_COMMAND_ID_ENQUIRE_STATUS: +		break; + +	default: +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected command_id %02x\n", command_id); +		return -1; +	} + +	// tell the app +	pthread_mutex_lock(&lowspeed->lock); +	en50221_app_lowspeed_command_callback cb = lowspeed->command_callback; +	void *cb_arg = lowspeed->command_callback_arg; +	pthread_mutex_unlock(&lowspeed->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, command_id, +			  &command); +	} +	return 0; +} + +static int en50221_app_lowspeed_parse_send(struct en50221_app_lowspeed *lowspeed, +					   uint8_t slot_id, +					   uint16_t session_number, +					   int more_last, +					   uint8_t *data, +					   uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// skip over the length field +	data += length_field_len; + +	// find previous session +	pthread_mutex_lock(&lowspeed->lock); +	struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions; +	while (cur_s) { +		if (cur_s->session_number == session_number) +			break; +		cur_s = cur_s->next; +	} + +	// more data is still to come +	if (!more_last) { +		// if there was no previous session, create one +		if (cur_s == NULL) { +			cur_s = malloc(sizeof(struct en50221_app_lowspeed_session)); +			if (cur_s == NULL) { +				print(LOG_LEVEL, ERROR, 1, +				      "Ran out of memory\n"); +				pthread_mutex_unlock(&lowspeed->lock); +				return -1; +			} +			cur_s->session_number = session_number; +			cur_s->block_chain = NULL; +			cur_s->block_length = 0; +			cur_s->next = lowspeed->sessions; +			lowspeed->sessions = cur_s; +		} +		// append the data +		uint8_t *new_data = realloc(cur_s->block_chain, +					    cur_s->block_length + asn_data_length); +		if (new_data == NULL) { +			print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n"); +			pthread_mutex_unlock(&lowspeed->lock); +			return -1; +		} +		memcpy(new_data + cur_s->block_length, data, asn_data_length); +		cur_s->block_chain = new_data; +		cur_s->block_length += asn_data_length; + +		// done +		pthread_mutex_unlock(&lowspeed->lock); +		return 0; +	} +	// we hit the last of a possible chain of fragments +	int do_free = 0; +	if (cur_s != NULL) { +		// we have a preceding fragment - need to append +		uint8_t *new_data = realloc(cur_s->block_chain, +					    cur_s->block_length + asn_data_length); +		if (new_data == NULL) { +			print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n"); +			pthread_mutex_unlock(&lowspeed->lock); +			return -1; +		} +		memcpy(new_data + cur_s->block_length, data, asn_data_length); +		asn_data_length = cur_s->block_length + asn_data_length; +		data = new_data; +		cur_s->block_chain = NULL; +		cur_s->block_length = 0; +		do_free = 1; +	} +	// check the reassembled data length +	if (asn_data_length < 1) { +		pthread_mutex_unlock(&lowspeed->lock); +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		if (do_free) +			free(data); +		return -1; +	} +	// now, parse the data +	uint8_t phase_id = data[0]; + +	// tell the app +	en50221_app_lowspeed_send_callback cb = lowspeed->send_callback; +	void *cb_arg = lowspeed->send_callback_arg; +	pthread_mutex_unlock(&lowspeed->lock); +	int cbstatus = 0; +	if (cb) { +		cbstatus = +		    cb(cb_arg, slot_id, session_number, phase_id, data + 1, asn_data_length - 1); +	} +	// done +	if (do_free) +		free(data); +	return cbstatus; +} diff --git a/lib/libdvben50221/en50221_app_lowspeed.h b/lib/libdvben50221/en50221_app_lowspeed.h new file mode 100644 index 0000000..0ef983c --- /dev/null +++ b/lib/libdvben50221/en50221_app_lowspeed.h @@ -0,0 +1,219 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_LOWSPEED_H__ +#define __EN50221_APPLICATION_LOWSPEED_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> +#include <libucsi/dvb/descriptor.h> + +#define COMMS_COMMAND_ID_CONNECT_ON_CHANNEL     0x01 +#define COMMS_COMMAND_ID_DISCONNECT_ON_CHANNEL  0x02 +#define COMMS_COMMAND_ID_SET_PARAMS             0x03 +#define COMMS_COMMAND_ID_ENQUIRE_STATUS         0x04 +#define COMMS_COMMAND_ID_GET_NEXT_BUFFER        0x05 + +#define CONNECTION_DESCRIPTOR_TYPE_TELEPHONE    0x01 +#define CONNECTION_DESCRIPTOR_TYPE_CABLE        0x02 + +#define COMMS_REPLY_ID_CONNECT_ACK              0x01 +#define COMMS_REPLY_ID_DISCONNECT_ACK           0x02 +#define COMMS_REPLY_ID_SET_PARAMS_ACK           0x03 +#define COMMS_REPLY_ID_STATUS_REPLY             0x04 +#define COMMS_REPLY_ID_GET_NEXT_BUFFER_ACK      0x05 +#define COMMS_REPLY_ID_SEND_ACK                 0x06 + +#define EN50221_APP_LOWSPEED_RESOURCEID(DEVICE_TYPE, DEVICE_NUMBER) MKRID(96,((DEVICE_TYPE)<<2)|((DEVICE_NUMBER) & 0x03),1) + + +/** + * Structure holding information on a received comms command. + */ +struct en50221_app_lowspeed_command { +	union { +		struct { +			uint8_t descriptor_type;	// CONNECTION_DESCRIPTOR_TYPE_* +			uint8_t retry_count; +			uint8_t timeout; +			union { +				struct dvb_telephone_descriptor *telephone; +				uint8_t cable_channel_id; +			} descriptor; +		} connect_on_channel; + +		struct { +			uint8_t buffer_size; +			uint8_t timeout; +		} set_params; + +		struct { +			uint8_t phase_id; +		} get_next_buffer; +	} u; +}; + +/** + * Type definition for command - called when we receive a comms command. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param command_id One of the COMMS_COMMAND_ID_* values + * @param command Pointer to a lowspeed command structure containing the command data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_lowspeed_command_callback) (void *arg, +						      uint8_t slot_id, +						      uint16_t session_number, +						      uint8_t command_id, +						      struct en50221_app_lowspeed_command *command); + +/** + * Type definition for send - called when we receive data to send. The block can be segmented into + * multiple pieces - last_more indicates the details of this. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param phase_id Comms phase id. + * @param data The data. + * @param length Number of bytes. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_lowspeed_send_callback) (void *arg, +						   uint8_t slot_id, +						   uint16_t session_number, +						   uint8_t phase_id, +						   uint8_t *data, +						   uint32_t length); + +/** + * Opaque type representing a lowspeed resource. + */ +struct en50221_app_lowspeed; + +/** + * Create an instance of the lowspeed resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_lowspeed * +	en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the lowspeed resource. + * + * @param lowspeed Instance to destroy. + */ +extern void en50221_app_lowspeed_destroy(struct en50221_app_lowspeed *lowspeed); + +/** + * Informs the lowspeed object that a session to it has been closed - cleans up internal state. + * + * @param lowspeed lowspeed resource instance. + * @param session_number The session concerned. + */ +extern void en50221_app_lowspeed_clear_session(struct en50221_app_lowspeed *lowspeed, +					       uint16_t session_number); + +/** + * Register the callback for when we receive a comms command. + * + * @param lowspeed lowspeed resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_lowspeed_register_command_callback(struct en50221_app_lowspeed *lowspeed, +							   en50221_app_lowspeed_command_callback callback, +							   void *arg); + +/** + * Register the callback for when we receive data to send. + * + * @param lowspeed lowspeed resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_lowspeed_register_send_callback(struct en50221_app_lowspeed *lowspeed, +							en50221_app_lowspeed_send_callback callback, +							void *arg); + +/** + * Send a comms reply to the CAM. + * + * @param lowspeed lowspeed resource instance. + * @param session_number Session number to send it on. + * @param comms_reply_id One of the COMMS_REPLY_ID_* values. + * @param return_value Comms reply specific value. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_lowspeed_send_comms_reply(struct en50221_app_lowspeed *lowspeed, +						 uint16_t session_number, +						 uint8_t comms_reply_id, +						 uint8_t return_value); + +/** + * Send received data to the CAM. + * + * @param lowspeed lowspeed resource instance. + * @param session_number Session number to send it on. + * @param phase_id Comms phase id. + * @param tx_data_length Length of data in bytes (max 254 bytes as per spec). + * @param tx_data Data. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_lowspeed_send_comms_data(struct en50221_app_lowspeed *lowspeed, +						uint16_t session_number, +						uint8_t phase_id, +						uint32_t tx_data_length, +						uint8_t * tx_data); + +/** + * Pass data received for this resource into it for parsing. + * + * @param lowspeed lowspeed instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_lowspeed_message(struct en50221_app_lowspeed *lowspeed, +					uint8_t slot_id, +					uint16_t session_number, +					uint32_t resource_id, +					uint8_t * data, +					uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_mmi.c b/lib/libdvben50221/en50221_app_mmi.c new file mode 100644 index 0000000..830eaa3 --- /dev/null +++ b/lib/libdvben50221/en50221_app_mmi.c @@ -0,0 +1,1397 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include <libucsi/dvb/types.h> +#include "en50221_app_mmi.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_mmi_session { +	uint16_t session_number; + +	uint8_t *menu_block_chain; +	uint32_t menu_block_length; + +	uint8_t *list_block_chain; +	uint32_t list_block_length; + +	uint8_t *subtitlesegment_block_chain; +	uint32_t subtitlesegment_block_length; + +	uint8_t *subtitledownload_block_chain; +	uint32_t subtitledownload_block_length; + +	struct en50221_app_mmi_session *next; +}; + +struct en50221_app_mmi { +	struct en50221_app_send_functions *funcs; +	struct en50221_app_mmi_session *sessions; + +	en50221_app_mmi_close_callback closecallback; +	void *closecallback_arg; + +	en50221_app_mmi_display_control_callback displaycontrolcallback; +	void *displaycontrolcallback_arg; + +	en50221_app_mmi_keypad_control_callback keypadcontrolcallback; +	void *keypadcontrolcallback_arg; + +	en50221_app_mmi_subtitle_segment_callback subtitlesegmentcallback; +	void *subtitlesegmentcallback_arg; + +	en50221_app_mmi_scene_end_mark_callback sceneendmarkcallback; +	void *sceneendmarkcallback_arg; + +	en50221_app_mmi_scene_control_callback scenecontrolcallback; +	void *scenecontrolcallback_arg; + +	en50221_app_mmi_subtitle_download_callback subtitledownloadcallback; +	void *subtitledownloadcallback_arg; + +	en50221_app_mmi_flush_download_callback flushdownloadcallback; +	void *flushdownloadcallback_arg; + +	en50221_app_mmi_enq_callback enqcallback; +	void *enqcallback_arg; + +	en50221_app_mmi_menu_callback menucallback; +	void *menucallback_arg; + +	en50221_app_mmi_list_callback listcallback; +	void *listcallback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_mmi_parse_close(struct en50221_app_mmi *mmi, +				       uint8_t slot_id, +				       uint16_t session_number, +				       uint8_t * data, +				       uint32_t data_length); +static int en50221_app_mmi_parse_display_control(struct en50221_app_mmi +						 *mmi, uint8_t slot_id, +						 uint16_t session_number, +						 uint8_t * data, +						 uint32_t data_length); +static int en50221_app_mmi_parse_keypad_control(struct en50221_app_mmi +						*mmi, uint8_t slot_id, +						uint16_t session_number, +						uint8_t * data, +						uint32_t data_length); +static int en50221_app_mmi_parse_enq(struct en50221_app_mmi *mmi, +				     uint8_t slot_id, +				     uint16_t session_number, +				     uint8_t * data, uint32_t data_length); +static int en50221_app_mmi_parse_list_menu(struct en50221_app_mmi *mmi, +					   uint8_t slot_id, +					   uint16_t session_number, +					   uint32_t tag_id, int more_last, +					   uint8_t * data, +					   uint32_t data_length); +static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint32_t tag_id, int more_last, +					  uint8_t * data, +					  uint32_t data_length); +static int en50221_app_mmi_parse_scene_end_mark(struct en50221_app_mmi *mmi, +						uint8_t slot_id, +						uint16_t session_number, +						uint8_t * data, +						uint32_t data_length); +static int en50221_app_mmi_parse_scene_control(struct en50221_app_mmi *mmi, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length); +static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint32_t tag_id, int more_last, +					  uint8_t * data, +					  uint32_t data_length); +static int en50221_app_mmi_parse_flush_download(struct en50221_app_mmi *mmi, +						uint8_t slot_id, +						uint16_t session_number, +						uint8_t * data, +						uint32_t data_length); +static int en50221_app_mmi_defragment(struct en50221_app_mmi *mmi, +				      uint16_t session_number, +				      uint32_t tag_id, int more_last, +				      uint8_t * indata, +				      uint32_t indata_length, +				      uint8_t ** outdata, +				      uint32_t * outdata_length); +static int en50221_app_mmi_defragment_text(uint8_t * data, +					   uint32_t data_length, +					   uint8_t ** outdata, +					   uint32_t * outdata_length, +					   uint32_t * outconsumed); + + + +struct en50221_app_mmi *en50221_app_mmi_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_mmi *mmi = NULL; + +	// create structure and set it up +	mmi = malloc(sizeof(struct en50221_app_mmi)); +	if (mmi == NULL) { +		return NULL; +	} +	mmi->funcs = funcs; +	mmi->closecallback = NULL; +	mmi->displaycontrolcallback = NULL; +	mmi->keypadcontrolcallback = NULL; +	mmi->subtitlesegmentcallback = NULL; +	mmi->sceneendmarkcallback = NULL; +	mmi->scenecontrolcallback = NULL; +	mmi->subtitledownloadcallback = NULL; +	mmi->flushdownloadcallback = NULL; +	mmi->enqcallback = NULL; +	mmi->menucallback = NULL; +	mmi->listcallback = NULL; +	mmi->sessions = NULL; + +	pthread_mutex_init(&mmi->lock, NULL); + +	// done +	return mmi; +} + +void en50221_app_mmi_destroy(struct en50221_app_mmi *mmi) +{ +	struct en50221_app_mmi_session *cur_s = mmi->sessions; +	while (cur_s) { +		struct en50221_app_mmi_session *next = cur_s->next; +		if (cur_s->menu_block_chain) +			free(cur_s->menu_block_chain); +		if (cur_s->list_block_chain) +			free(cur_s->list_block_chain); +		if (cur_s->subtitlesegment_block_chain) +			free(cur_s->subtitlesegment_block_chain); +		if (cur_s->subtitledownload_block_chain) +			free(cur_s->subtitledownload_block_chain); +		free(cur_s); +		cur_s = next; +	} + +	pthread_mutex_destroy(&mmi->lock); +	free(mmi); +} + +void en50221_app_mmi_clear_session(struct en50221_app_mmi *mmi, +				   uint16_t session_number) +{ +	pthread_mutex_lock(&mmi->lock); +	struct en50221_app_mmi_session *cur_s = mmi->sessions; +	struct en50221_app_mmi_session *prev_s = NULL; +	while (cur_s) { +		if (cur_s->session_number == session_number) { +			if (cur_s->menu_block_chain) +				free(cur_s->menu_block_chain); +			if (cur_s->list_block_chain) +				free(cur_s->list_block_chain); +			if (cur_s->subtitlesegment_block_chain) +				free(cur_s->subtitlesegment_block_chain); +			if (cur_s->subtitledownload_block_chain) +				free(cur_s->subtitledownload_block_chain); +			if (prev_s) { +				prev_s->next = cur_s->next; +			} else { +				mmi->sessions = cur_s->next; +			} +			free(cur_s); +			return; +		} + +		prev_s = cur_s; +		cur_s = cur_s->next; +	} +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_close_callback(struct en50221_app_mmi *mmi, +					     en50221_app_mmi_close_callback callback, +					     void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->closecallback = callback; +	mmi->closecallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_display_control_callback(struct en50221_app_mmi *mmi, +						       en50221_app_mmi_display_control_callback callback, +						       void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->displaycontrolcallback = callback; +	mmi->displaycontrolcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_keypad_control_callback(struct en50221_app_mmi *mmi, +						      en50221_app_mmi_keypad_control_callback callback, +						      void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->keypadcontrolcallback = callback; +	mmi->keypadcontrolcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_subtitle_segment_callback(struct en50221_app_mmi *mmi, +							en50221_app_mmi_subtitle_segment_callback callback, +							void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->subtitlesegmentcallback = callback; +	mmi->subtitlesegmentcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_scene_end_mark_callback(struct en50221_app_mmi *mmi, +						      en50221_app_mmi_scene_end_mark_callback callback, void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->sceneendmarkcallback = callback; +	mmi->sceneendmarkcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_scene_control_callback(struct en50221_app_mmi *mmi, +						     en50221_app_mmi_scene_control_callback callback, void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->scenecontrolcallback = callback; +	mmi->scenecontrolcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_subtitle_download_callback(struct en50221_app_mmi *mmi, +							 en50221_app_mmi_subtitle_download_callback callback, +							 void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->subtitledownloadcallback = callback; +	mmi->subtitledownloadcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_flush_download_callback(struct en50221_app_mmi *mmi, +						      en50221_app_mmi_flush_download_callback callback, +						      void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->flushdownloadcallback = callback; +	mmi->flushdownloadcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_enq_callback(struct en50221_app_mmi *mmi, +					   en50221_app_mmi_enq_callback callback, +					   void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->enqcallback = callback; +	mmi->enqcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_menu_callback(struct en50221_app_mmi *mmi, +					    en50221_app_mmi_menu_callback callback, +					    void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->menucallback = callback; +	mmi->menucallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +void en50221_app_mmi_register_list_callback(struct en50221_app_mmi *mmi, +					    en50221_app_mmi_list_callback callback, +					    void *arg) +{ +	pthread_mutex_lock(&mmi->lock); +	mmi->listcallback = callback; +	mmi->listcallback_arg = arg; +	pthread_mutex_unlock(&mmi->lock); +} + +int en50221_app_mmi_close(struct en50221_app_mmi *mmi, +			  uint16_t session_number, +			  uint8_t cmd_id, uint8_t delay) +{ +	uint8_t data[6]; +	int data_length = 5; + +	data[0] = (TAG_CLOSE_MMI >> 16) & 0xFF; +	data[1] = (TAG_CLOSE_MMI >> 8) & 0xFF; +	data[2] = TAG_CLOSE_MMI & 0xFF; +	data[3] = 1; +	data[4] = cmd_id; +	if (cmd_id == MMI_CLOSE_MMI_CMD_ID_DELAY) { +		data[3] = 2; +		data[5] = delay; +		data_length = 6; +	} +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, +				     data_length); +} + +int en50221_app_mmi_display_reply(struct en50221_app_mmi *mmi, +				  uint16_t session_number, +				  uint8_t reply_id, +				  struct en50221_app_mmi_display_reply_details *details) +{ +	uint8_t data[32]; +	struct iovec iov[2]; +	uint32_t iov_count; +	int length_field_len; + +	// fill out the start of the header +	data[0] = (TAG_DISPLAY_REPLY >> 16) & 0xFF; +	data[1] = (TAG_DISPLAY_REPLY >> 8) & 0xFF; +	data[2] = TAG_DISPLAY_REPLY & 0xFF; + +	switch (reply_id) { +	case MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK: +		data[3] = 2; +		data[4] = reply_id; +		data[5] = details->u.mode_ack.mmi_mode; +		iov[0].iov_base = data; +		iov[0].iov_len = 6; +		iov_count = 1; +		break; + +	case MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES: +	case MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES: +		if ((length_field_len = +			asn_1_encode(details->u.char_table.table_length + 1, data + 3, 3)) < 0) { +			return -1; +		} +		data[3 + length_field_len] = reply_id; +		iov[0].iov_base = data; +		iov[0].iov_len = 3 + length_field_len + 1; +		iov[1].iov_base = details->u.char_table.table; +		iov[1].iov_len = details->u.char_table.table_length; +		iov_count = 2; +		break; + +	case MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS: +	case MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS: +		{ +			if ((length_field_len = +				asn_1_encode(1 + 9 + (details->u.gfx.num_pixel_depths * 2), data + 3, 3)) < 0) { +				return -1; +			} +			data[3 + length_field_len] = reply_id; +			data[3 + length_field_len + 1] = details->u.gfx.width >> 8; +			data[3 + length_field_len + 2] = details->u.gfx.width; +			data[3 + length_field_len + 3] = details->u.gfx.height >> 8; +			data[3 + length_field_len + 4] = details->u.gfx.height; +			data[3 + length_field_len + 5] = +				((details->u.gfx.aspect_ratio & 0x0f) << 4) | +				((details->u.gfx.gfx_relation_to_video & 0x07) << 1) | +				(details->u.gfx.multiple_depths & 1); +			data[3 + length_field_len + 6] = details->u.gfx.display_bytes >> 4; +			data[3 + length_field_len + 7] = +				((details->u.gfx.display_bytes & 0x0f) << 4) | +				((details->u.gfx.composition_buffer_bytes & 0xf0) >> 4); +			data[3 + length_field_len + 8] = +			    	((details->u.gfx.composition_buffer_bytes & 0x0f) << 4) | +				((details->u.gfx.object_cache_bytes & 0xf0) >> 4); +			data[3 + length_field_len + 9] = +			    	((details->u.gfx.object_cache_bytes & 0x0f) << 4) | +				 (details->u.gfx.num_pixel_depths & 0x0f); + +			// render the pixel depths themselves +			uint8_t *pixdepths = +			    alloca(details->u.gfx.num_pixel_depths * 2); +			if (pixdepths == NULL) { +				return -1; +			} +			uint32_t i; +			for (i = 0; i < details->u.gfx.num_pixel_depths; i++) { +				pixdepths[0] = +				    ((details->u.gfx.pixel_depths[i].display_depth & 0x07) << 5) | +				    ((details->u.gfx.pixel_depths[i].pixels_per_byte & 0x07) << 2); +				pixdepths[1] = +				    details->u.gfx.pixel_depths[i].region_overhead; +				pixdepths += 2; +			} + +			// make up the iovs +			iov[0].iov_base = data; +			iov[0].iov_len = 3 + length_field_len + 10; +			iov[1].iov_base = pixdepths; +			iov[1].iov_len = +			    details->u.gfx.num_pixel_depths * 2; +			iov_count = 2; +			break; +		} + +	default: +		data[3] = 1; +		data[4] = reply_id; +		iov[0].iov_base = data; +		iov[0].iov_len = 5; +		iov_count = 1; +		break; +	} + +	// sendit +	return mmi->funcs->send_datav(mmi->funcs->arg, session_number, iov, iov_count); +} + +int en50221_app_mmi_keypress(struct en50221_app_mmi *mmi, +			     uint16_t session_number, uint8_t keycode) +{ +	uint8_t data[5]; + +	data[0] = (TAG_KEYPRESS >> 16) & 0xFF; +	data[1] = (TAG_KEYPRESS >> 8) & 0xFF; +	data[2] = TAG_KEYPRESS & 0xFF; +	data[3] = 1; +	data[4] = keycode; +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_display_message(struct en50221_app_mmi *mmi, +				    uint16_t session_number, +				    uint8_t display_message_id) +{ +	uint8_t data[5]; + +	data[0] = (TAG_DISPLAY_MESSAGE >> 16) & 0xFF; +	data[1] = (TAG_DISPLAY_MESSAGE >> 8) & 0xFF; +	data[2] = TAG_DISPLAY_MESSAGE & 0xFF; +	data[3] = 1; +	data[4] = display_message_id; +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_scene_done(struct en50221_app_mmi *mmi, +			       uint16_t session_number, +			       uint8_t decoder_continue, +			       uint8_t scene_reveal, uint8_t scene_tag) +{ +	uint8_t data[5]; + +	data[0] = (TAG_SCENE_DONE >> 16) & 0xFF; +	data[1] = (TAG_SCENE_DONE >> 8) & 0xFF; +	data[2] = TAG_SCENE_DONE & 0xFF; +	data[3] = 1; +	data[4] = +		(decoder_continue ? 0x80 : 0x00) | +	    	(scene_reveal ? 0x40 : 0x00) | +		(scene_tag & 0x0f); +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_download_reply(struct en50221_app_mmi *mmi, +				   uint16_t session_number, +				   uint16_t object_id, +				   uint8_t download_reply_id) +{ +	uint8_t data[7]; + +	data[0] = (TAG_DOWNLOAD_REPLY >> 16) & 0xFF; +	data[1] = (TAG_DOWNLOAD_REPLY >> 8) & 0xFF; +	data[2] = TAG_DOWNLOAD_REPLY & 0xFF; +	data[3] = 3; +	data[4] = object_id >> 8; +	data[5] = object_id; +	data[6] = download_reply_id; +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 7); +} + +int en50221_app_mmi_answ(struct en50221_app_mmi *mmi, +			 uint16_t session_number, +			 uint8_t answ_id, +			 uint8_t * text, uint32_t text_count) +{ +	uint8_t buf[10]; + +	// set up the tag +	buf[0] = (TAG_ANSWER >> 16) & 0xFF; +	buf[1] = (TAG_ANSWER >> 8) & 0xFF; +	buf[2] = TAG_ANSWER & 0xFF; + +	// encode the length field +	struct iovec iov[2]; +	int length_field_len = 0; +	int iov_count = 1; +	if (answ_id == MMI_ANSW_ID_ANSWER) { +		if ((length_field_len = asn_1_encode(text_count + 1, buf + 3, 3)) < 0) { +			return -1; +		} +		buf[3 + length_field_len] = answ_id; + +		iov[0].iov_base = buf; +		iov[0].iov_len = 3 + length_field_len + 1; +		iov[1].iov_base = text; +		iov[1].iov_len = text_count; +		iov_count = 2; +	} else { +		buf[3] = 1; +		buf[4] = answ_id; +		iov[0].iov_base = buf; +		iov[0].iov_len = 5; +		iov_count = 1; +	} + +	// create the data and send it +	return mmi->funcs->send_datav(mmi->funcs->arg, session_number, iov, +				      iov_count); +} + +int en50221_app_mmi_menu_answ(struct en50221_app_mmi *mmi, +			      uint16_t session_number, uint8_t choice_ref) +{ +	uint8_t data[5]; + +	data[0] = (TAG_MENU_ANSWER >> 16) & 0xFF; +	data[1] = (TAG_MENU_ANSWER >> 8) & 0xFF; +	data[2] = TAG_MENU_ANSWER & 0xFF; +	data[3] = 1; +	data[4] = choice_ref; +	return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_message(struct en50221_app_mmi *mmi, +			    uint8_t slot_id, +			    uint16_t session_number, +			    uint32_t resource_id, +			    uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_CLOSE_MMI: +		return en50221_app_mmi_parse_close(mmi, slot_id, +						   session_number, +						   data + 3, +						   data_length - 3); +	case TAG_DISPLAY_CONTROL: +		return en50221_app_mmi_parse_display_control(mmi, slot_id, +							     session_number, +							     data + 3, +							     data_length - 3); +	case TAG_KEYPAD_CONTROL: +		return en50221_app_mmi_parse_keypad_control(mmi, slot_id, +							    session_number, +							    data + 3, +							    data_length - 3); +	case TAG_ENQUIRY: +		return en50221_app_mmi_parse_enq(mmi, slot_id, +						 session_number, data + 3, +						 data_length - 3); +	case TAG_MENU_LAST: +		return en50221_app_mmi_parse_list_menu(mmi, slot_id, +						       session_number, tag, +						       1, data + 3, +						       data_length - 3); +	case TAG_MENU_MORE: +		return en50221_app_mmi_parse_list_menu(mmi, slot_id, +						       session_number, tag, +						       0, data + 3, +						       data_length - 3); +	case TAG_LIST_LAST: +		return en50221_app_mmi_parse_list_menu(mmi, slot_id, +						       session_number, tag, +						       1, data + 3, +						       data_length - 3); +	case TAG_LIST_MORE: +		return en50221_app_mmi_parse_list_menu(mmi, slot_id, +						       session_number, tag, +						       0, data + 3, +						       data_length - 3); +	case TAG_SUBTITLE_SEGMENT_LAST: +		return en50221_app_mmi_parse_subtitle(mmi, slot_id, +						      session_number, tag, +						      1, data + 3, +						      data_length - 3); +	case TAG_SUBTITLE_SEGMENT_MORE: +		return en50221_app_mmi_parse_subtitle(mmi, slot_id, +						      session_number, tag, +						      0, data + 3, +						      data_length - 3); +	case TAG_SCENE_END_MARK: +		return en50221_app_mmi_parse_scene_end_mark(mmi, slot_id, +							    session_number, +							    data + 3, +							    data_length - 3); +	case TAG_SCENE_CONTROL: +		return en50221_app_mmi_parse_scene_control(mmi, slot_id, +							   session_number, +							   data + 3, +							   data_length - 3); +	case TAG_SUBTITLE_DOWNLOAD_LAST: +		return en50221_app_mmi_parse_subtitle(mmi, slot_id, +						      session_number, tag, +						      1, data + 3, +						      data_length - 3); +	case TAG_SUBTITLE_DOWNLOAD_MORE: +		return en50221_app_mmi_parse_subtitle(mmi, slot_id, +						      session_number, tag, +						      0, data + 3, +						      data_length - 3); +	case TAG_FLUSH_DOWNLOAD: +		return en50221_app_mmi_parse_flush_download(mmi, slot_id, +							    session_number, +							    data + 3, +							    data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + + + +static int en50221_app_mmi_parse_close(struct en50221_app_mmi *mmi, +				       uint8_t slot_id, +				       uint16_t session_number, +				       uint8_t * data, +				       uint32_t data_length) +{ +	// validate data +	if (data_length < 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] > (data_length - 1)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t cmd_id = data[1]; +	uint8_t delay = 0; +	if (cmd_id == MMI_CLOSE_MMI_CMD_ID_DELAY) { +		if (data[0] != 2) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received short data\n"); +			return -1; +		} +		delay = data[2]; +	} +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_close_callback cb = mmi->closecallback; +	void *cb_arg = mmi->closecallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, cmd_id, delay); +	} +	return 0; +} + +static int en50221_app_mmi_parse_display_control(struct en50221_app_mmi *mmi, +						 uint8_t slot_id, +						 uint16_t session_number, +						 uint8_t *data, +						 uint32_t data_length) +{ +	// validate data +	if (data_length < 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] > (data_length - 1)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t cmd_id = data[1]; +	uint8_t mmi_mode = 0; +	if (cmd_id == MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE) { +		if (data[0] != 2) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received short data\n"); +			return -1; +		} +		mmi_mode = data[2]; +	} +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_display_control_callback cb = mmi->displaycontrolcallback; +	void *cb_arg = mmi->displaycontrolcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, cmd_id, mmi_mode); +	} +	return 0; +} + +static int en50221_app_mmi_parse_keypad_control(struct en50221_app_mmi *mmi, +						uint8_t slot_id, +						uint16_t session_number, +						uint8_t *data, +						uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length < 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// skip over the length field +	data += length_field_len; + +	// extract the information +	uint8_t cmd_id = data[0]; +	uint8_t *keycodes = data + 1; + +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_keypad_control_callback cb = mmi->keypadcontrolcallback; +	void *cb_arg = mmi->keypadcontrolcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, cmd_id, +			  keycodes, asn_data_length - 1); +	} +	return 0; +} + +static int en50221_app_mmi_parse_enq(struct en50221_app_mmi *mmi, +				     uint8_t slot_id, +				     uint16_t session_number, +				     uint8_t * data, uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length < 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// skip over the length field +	data += length_field_len; + +	// extract the information +	uint8_t blind_answer = (data[0] & 0x01) ? 1 : 0; +	uint8_t answer_length = data[1]; +	uint8_t *text = data + 2; + +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_enq_callback cb = mmi->enqcallback; +	void *cb_arg = mmi->enqcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, blind_answer, +			  answer_length, text, asn_data_length - 2); +	} +	return 0; +} + +static int en50221_app_mmi_parse_list_menu(struct en50221_app_mmi *mmi, +					   uint8_t slot_id, +					   uint16_t session_number, +					   uint32_t tag_id, int more_last, +					   uint8_t * data, +					   uint32_t data_length) +{ +	int result = 0; +	uint8_t *text_flags = NULL; +	struct en50221_app_mmi_text *text_data = NULL; +	uint32_t i; +	uint8_t text_count = 0; + +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// skip over the length field +	data += length_field_len; + +	// defragment +	pthread_mutex_lock(&mmi->lock); +	uint8_t *outdata; +	uint32_t outdata_length; +	int dfstatus = +	    en50221_app_mmi_defragment(mmi, session_number, tag_id, +				       more_last, +				       data, asn_data_length, +				       &outdata, &outdata_length); +	if (dfstatus <= 0) { +		pthread_mutex_unlock(&mmi->lock); +		return dfstatus; +	} +	data = outdata; +	data_length = outdata_length; + +	// check the reassembled data length +	if (data_length < 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		pthread_mutex_unlock(&mmi->lock); +		result = -1; +		goto exit_cleanup; +	} +	// now, parse the data +	uint8_t choice_nb = data[0]; +	text_count = choice_nb + 3; +	if (choice_nb == 0xff) +		text_count = 3; +	data++; +	data_length--; + +	// variables for extracted text state +	text_flags = alloca(text_count); +	if (text_flags == NULL) { +		pthread_mutex_unlock(&mmi->lock); +		result = -1; +		goto exit_cleanup; +	} +	memset(text_flags, 0, text_count); +	text_data = (struct en50221_app_mmi_text *) +	    alloca(sizeof(struct en50221_app_mmi_text) * text_count); +	if (text_data == NULL) { +		pthread_mutex_unlock(&mmi->lock); +		result = -1; +		goto exit_cleanup; +	} +	memset(text_data, 0, +	       sizeof(struct en50221_app_mmi_text) * text_count); + +	// extract the text! +	for (i = 0; i < text_count; i++) { +		uint32_t consumed = 0; +		int cur_status = +		    en50221_app_mmi_defragment_text(data, data_length, +						    &text_data[i].text, +						    &text_data[i].text_length, +						    &consumed); +		if (cur_status < 0) { +			pthread_mutex_unlock(&mmi->lock); +			result = -1; +			goto exit_cleanup; +		} + +		text_flags[i] = cur_status; +		data += consumed; +		data_length -= consumed; +	} + +	// work out what to pass to the user +	struct en50221_app_mmi_text *text_data_for_user = (struct en50221_app_mmi_text *) +	    alloca(sizeof(struct en50221_app_mmi_text) * text_count); +	if (text_data_for_user == NULL) { +		result = -1; +		goto exit_cleanup; +	} +	memcpy(text_data_for_user, text_data, +	       sizeof(struct en50221_app_mmi_text) * text_count); +	struct en50221_app_mmi_text *text_ptr = NULL; +	if (text_count > 3) { +		text_ptr = &text_data_for_user[3]; +	} +	uint8_t *items_raw = NULL; +	uint32_t items_raw_length = 0; +	if (choice_nb == 0xff) { +		items_raw = data; +		items_raw_length = data_length; +	} +	// do callback +	result = 0; +	switch (tag_id) { +	case TAG_MENU_LAST: +	{ +		en50221_app_mmi_menu_callback cb = mmi->menucallback; +		void *cb_arg = mmi->menucallback_arg; +		pthread_mutex_unlock(&mmi->lock); +		if (cb) { +			result = +				cb(cb_arg, slot_id, session_number, +				&text_data_for_user[0], +				&text_data_for_user[1], +				&text_data_for_user[2], +				text_count - 3, text_ptr, +				items_raw_length, items_raw); +		} +		break; +	} + +	case TAG_LIST_LAST: +	{ +		en50221_app_mmi_list_callback cb = mmi->listcallback; +		void *cb_arg = mmi->listcallback_arg; +		pthread_mutex_unlock(&mmi->lock); +		if (cb) { +			result = +				cb(cb_arg, slot_id, session_number, +				&text_data_for_user[0], +				&text_data_for_user[1], +				&text_data_for_user[2], +				text_count - 3, text_ptr, +				items_raw_length, items_raw); +		} +		break; +	} + +	default: +		pthread_mutex_unlock(&mmi->lock); +		break; +	} + +exit_cleanup: +	if ((dfstatus == 2) && outdata) +		free(outdata); +	if (text_flags && text_data) { +		for (i = 0; i < text_count; i++) { +			if ((text_flags[i] == 2) && text_data[i].text) { +				free(text_data[i].text); +			} +		} +	} +	return result; +} + +static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint32_t tag_id, int more_last, +					  uint8_t * data, +					  uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// skip over the length field +	data += length_field_len; + +	// defragment +	pthread_mutex_lock(&mmi->lock); +	uint8_t *outdata; +	uint32_t outdata_length; +	int dfstatus = +	    en50221_app_mmi_defragment(mmi, session_number, tag_id, +				       more_last, +				       data, asn_data_length, +				       &outdata, &outdata_length); +	if (dfstatus <= 0) { +		pthread_mutex_unlock(&mmi->lock); +		return dfstatus; +	} +	// do callback +	int cbstatus = 0; +	switch (tag_id) { +	case TAG_SUBTITLE_SEGMENT_LAST: +		{ +			en50221_app_mmi_subtitle_segment_callback cb = +			    mmi->subtitlesegmentcallback; +			void *cb_arg = mmi->subtitlesegmentcallback_arg; +			pthread_mutex_unlock(&mmi->lock); +			if (cb) { +				cbstatus = +				    cb(cb_arg, slot_id, session_number, outdata, outdata_length); +			} +			break; +		} + +	case TAG_SUBTITLE_DOWNLOAD_LAST: +		{ +			en50221_app_mmi_subtitle_download_callback cb = +			    mmi->subtitledownloadcallback; +			void *cb_arg = mmi->subtitledownloadcallback_arg; +			pthread_mutex_unlock(&mmi->lock); +			if (cb) { +				cbstatus = +				    cb(cb_arg, slot_id, session_number, outdata, outdata_length); +			} +			break; +		} +	} + +	// free the data returned by the defragment call if asked to +	if (dfstatus == 2) { +		free(outdata); +	} +	// done +	return cbstatus; +} + +static int en50221_app_mmi_parse_scene_end_mark(struct en50221_app_mmi *mmi, +						uint8_t slot_id, +						uint16_t session_number, +						uint8_t * data, +						uint32_t data_length) +{ +	// validate data +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t flags = data[1]; + +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_scene_end_mark_callback cb = +	    mmi->sceneendmarkcallback; +	void *cb_arg = mmi->sceneendmarkcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  (flags & 0x80) ? 1 : 0, +			  (flags & 0x40) ? 1 : 0, +			  (flags & 0x20) ? 1 : 0, flags & 0x0f); +	} +	return 0; +} + +static int en50221_app_mmi_parse_scene_control(struct en50221_app_mmi *mmi, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length) +{ +	// validate data +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t flags = data[1]; + +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_scene_control_callback cb = mmi->scenecontrolcallback; +	void *cb_arg = mmi->scenecontrolcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, +			  (flags & 0x80) ? 1 : 0, +			  (flags & 0x40) ? 1 : 0, flags & 0x0f); +	} +	return 0; +} + +static int en50221_app_mmi_parse_flush_download(struct en50221_app_mmi *mmi, +						uint8_t slot_id, +						uint16_t session_number, +						uint8_t *data, +						uint32_t data_length) +{ +	// validate data +	if (data_length != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 0) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	// tell the app +	pthread_mutex_lock(&mmi->lock); +	en50221_app_mmi_flush_download_callback cb = mmi->flushdownloadcallback; +	void *cb_arg = mmi->flushdownloadcallback_arg; +	pthread_mutex_unlock(&mmi->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number); +	} +	return 0; +} + +static int en50221_app_mmi_defragment(struct en50221_app_mmi *mmi, +				      uint16_t session_number, +				      uint32_t tag_id, +				      int more_last, +				      uint8_t * indata, +				      uint32_t indata_length, +				      uint8_t ** outdata, +				      uint32_t * outdata_length) +{ +	struct en50221_app_mmi_session *cur_s = mmi->sessions; +	while (cur_s) { +		if (cur_s->session_number == session_number) +			break; +		cur_s = cur_s->next; +	} + +	// more data is still to come +	if (!more_last) { +		// if there was no previous session, create one +		if (cur_s == NULL) { +			cur_s = malloc(sizeof(struct en50221_app_mmi_session)); +			if (cur_s == NULL) { +				print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n"); +				return -1; +			} +			cur_s->session_number = session_number; +			cur_s->menu_block_chain = NULL; +			cur_s->menu_block_length = 0; +			cur_s->list_block_chain = NULL; +			cur_s->list_block_length = 0; +			cur_s->subtitlesegment_block_chain = NULL; +			cur_s->subtitlesegment_block_length = 0; +			cur_s->subtitledownload_block_chain = NULL; +			cur_s->subtitledownload_block_length = 0; +			cur_s->next = mmi->sessions; +			mmi->sessions = cur_s; +		} +		// find the block/block_length to use +		uint8_t **block_chain; +		uint32_t *block_length; +		switch (tag_id) { +		case TAG_MENU_LAST: +		case TAG_MENU_MORE: +			block_chain = &cur_s->menu_block_chain; +			block_length = &cur_s->menu_block_length; +			break; +		case TAG_LIST_LAST: +		case TAG_LIST_MORE: +			block_chain = &cur_s->list_block_chain; +			block_length = &cur_s->list_block_length; +			break; +		case TAG_SUBTITLE_SEGMENT_LAST: +		case TAG_SUBTITLE_SEGMENT_MORE: +			block_chain = &cur_s->subtitlesegment_block_chain; +			block_length = &cur_s->subtitlesegment_block_length; +			break; +		case TAG_SUBTITLE_DOWNLOAD_LAST: +		case TAG_SUBTITLE_DOWNLOAD_MORE: +			block_chain = &cur_s->subtitledownload_block_chain; +			block_length = &cur_s->subtitledownload_block_length; +			break; +		default: +			return -1; +		} + +		// append the data +		uint8_t *new_data = +		    realloc(*block_chain, *block_length + indata_length); +		if (new_data == NULL) { +			print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n"); +			return -1; +		} +		memcpy(new_data + *block_length, indata, indata_length); +		*block_chain = new_data; +		*block_length += indata_length; + +		// success, but block not complete yet +		return 0; +	} +	// we hit the last of a possible chain of fragments +	if (cur_s != NULL) { +		// find the block/block_length to use +		uint8_t **block_chain; +		uint32_t *block_length; +		switch (tag_id) { +		case TAG_MENU_LAST: +		case TAG_MENU_MORE: +			block_chain = &cur_s->menu_block_chain; +			block_length = &cur_s->menu_block_length; +			break; +		case TAG_LIST_LAST: +		case TAG_LIST_MORE: +			block_chain = &cur_s->list_block_chain; +			block_length = &cur_s->list_block_length; +			break; +		case TAG_SUBTITLE_SEGMENT_LAST: +		case TAG_SUBTITLE_SEGMENT_MORE: +			block_chain = &cur_s->subtitlesegment_block_chain; +			block_length = &cur_s->subtitlesegment_block_length; +			break; +		case TAG_SUBTITLE_DOWNLOAD_LAST: +		case TAG_SUBTITLE_DOWNLOAD_MORE: +			block_chain = &cur_s->subtitledownload_block_chain; +			block_length = &cur_s->subtitledownload_block_length; +			break; +		default: +			return -1; +		} + +		// we have a preceding fragment - need to append +		uint8_t *new_data = +		    realloc(*block_chain, *block_length + indata_length); +		if (new_data == NULL) { +			print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n"); +			return -1; +		} +		memcpy(new_data + *block_length, indata, indata_length); +		*outdata_length = *block_length + indata_length; +		*outdata = new_data; +		*block_chain = NULL; +		*block_length = 0; + +		// success, and indicate to free the block when done +		return 2; +	} +	// success, but indicate it is not to be freed +	*outdata_length = indata_length; +	*outdata = indata; +	return 1; +} + +static int en50221_app_mmi_defragment_text(uint8_t * data, +					   uint32_t data_length, +					   uint8_t ** outdata, +					   uint32_t * outdata_length, +					   uint32_t * outconsumed) +{ +	uint8_t *text = NULL; +	uint32_t text_length = 0; +	uint32_t consumed = 0; + +	while (1) { +		// get the tag +		if (data_length < 3) { +			print(LOG_LEVEL, ERROR, 1, "Short data\n"); +			if (text) +				free(text); +			return -1; +		} +		uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; +		data += 3; +		data_length -= 3; +		consumed += 3; + +		// get the length of the data and adjust +		uint16_t asn_data_length; +		int length_field_len; +		if ((length_field_len = +		     asn_1_decode(&asn_data_length, data, +				  data_length)) < 0) { +			print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +			if (text) +				free(text); +			return -1; +		} +		data += length_field_len; +		data_length -= length_field_len; +		consumed += length_field_len; + +		// deal with the tags +		if (tag == TAG_TEXT_LAST) { +			if (text == NULL) { +				*outdata = data; +				*outdata_length = asn_data_length; +				*outconsumed = consumed + asn_data_length; +				return 1; +			} else { +				// append the data +				uint8_t *new_text = realloc(text, +							    text_length + asn_data_length); +				if (new_text == NULL) { +					print(LOG_LEVEL, ERROR, 1, +					      "Ran out of memory\n"); +					if (text) +						free(text); +					return -1; +				} +				memcpy(new_text + text_length, data, +				       asn_data_length); +				*outdata = new_text; +				*outdata_length = +				    text_length + asn_data_length; +				*outconsumed = consumed + asn_data_length; +				return 2; +			} + +		} else if (tag == TAG_TEXT_MORE) { +			// append the data +			uint8_t *new_text = +			    realloc(text, text_length + asn_data_length); +			if (new_text == NULL) { +				print(LOG_LEVEL, ERROR, 1, +				      "Ran out of memory\n"); +				if (text) +					free(text); +				return -1; +			} +			memcpy(new_text + text_length, data, +			       asn_data_length); +			text = new_text; +			text_length += asn_data_length; + +			// consume the data +			data += asn_data_length; +			data_length -= asn_data_length; +			consumed += asn_data_length; +		} else { +			// unknown tag +			print(LOG_LEVEL, ERROR, 1, +			      "Unknown MMI text tag\n"); +			if (text) +				free(text); +			return -1; +		} +	} +} diff --git a/lib/libdvben50221/en50221_app_mmi.h b/lib/libdvben50221/en50221_app_mmi.h new file mode 100644 index 0000000..5c5b727 --- /dev/null +++ b/lib/libdvben50221/en50221_app_mmi.h @@ -0,0 +1,618 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_mmi_H__ +#define __EN50221_APPLICATION_mmi_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_MMI_RESOURCEID MKRID(64,1,1) + +#define MMI_CLOSE_MMI_CMD_ID_IMMEDIATE                                  0x00 +#define MMI_CLOSE_MMI_CMD_ID_DELAY                                      0x01 + +#define MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE                         0x01 +#define MMI_DISPLAY_CONTROL_CMD_ID_GET_DISPLAY_CHAR_TABLES              0x02 +#define MMI_DISPLAY_CONTROL_CMD_ID_GET_INPUT_CHAR_TABLES                0x03 +#define MMI_DISPLAY_CONTROL_CMD_ID_GET_OVERLAY_GFX_CHARACTERISTICS      0x04 +#define MMI_DISPLAY_CONTROL_CMD_ID_GET_FULLSCREEN_GFX_CHARACTERISTICS   0x05 + +#define MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK                               0x01 +#define MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES                   0x02 +#define MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES                     0x03 +#define MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS           0x04 +#define MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS        0x05 +#define MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID                             0xF0 +#define MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE                           0xF1 +#define MMI_DISPLAY_REPLY_ID_UNKNOWN_CHAR_TABLE                         0xF2 + +#define MMI_MODE_HIGH_LEVEL                                             0x01 +#define MMI_MODE_LOW_LEVEL_OVERLAY_GFX                                  0x02 +#define MMI_MODE_LOW_LEVEL_FULLSCREEN_GFX                               0x03 + +#define MMI_KEYPAD_CONTROL_CMD_ID_INTERCEPT_ALL                         0x01 +#define MMI_KEYPAD_CONTROL_CMD_ID_IGNORE_ALL                            0x02 +#define MMI_KEYPAD_CONTROL_CMD_ID_INTERCEPT_SELECTED                    0x03 +#define MMI_KEYPAD_CONTROL_CMD_ID_IGNORE_SELECTED                       0x04 +#define MMI_KEYPAD_CONTROL_CMD_ID_REJECT_KEYPRESS                       0x05 + +#define MMI_GFX_VIDEO_RELATION_NONE                                     0x00 +#define MMI_GFX_VIDEO_RELATION_MATCHES_EXACTLY                          0x07 + +#define MMI_DISPLAY_MESSAGE_ID_OK                                       0x00 +#define MMI_DISPLAY_MESSAGE_ID_ERROR                                    0x01 +#define MMI_DISPLAY_MESSAGE_ID_OUT_OF_MEMORY                            0x02 +#define MMI_DISPLAY_MESSAGE_ID_SUBTITLE_SYNTAX_ERROR                    0x03 +#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_REGION                         0x04 +#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_CLUT                           0x05 +#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_OBJECT                         0x06 +#define MMI_DISPLAY_MESSAGE_ID_INCOMPATABLE_OBJECT                      0x07 +#define MMI_DISPLAY_MESSAGE_ID_UNKNOWN_CHARACTER                        0x08 +#define MMI_DISPLAY_MESSAGE_ID_DISPLAY_CHANGED                          0x09 + +#define MMI_DOWNLOAD_REPLY_ID_OK                                        0x00 +#define MMI_DOWNLOAD_REPLY_ID_NOT_OBJECT_SEGMENT                        0x01 +#define MMI_DOWNLOAD_REPLY_ID_OUT_OF_MEMORY                             0x02 + +#define MMI_ANSW_ID_CANCEL                                              0x00 +#define MMI_ANSW_ID_ANSWER                                              0x01 + +/** + * A pixel depth as supplied with display_reply details + */ +struct en50221_app_mmi_pixel_depth { +	uint8_t display_depth; +	uint8_t pixels_per_byte; +	uint8_t region_overhead; +}; + +/** + * Details returned with a display_reply + */ +struct en50221_app_mmi_display_reply_details { +	union { +		struct { +			uint16_t width; +			uint16_t height; +			uint8_t aspect_ratio; +			uint8_t gfx_relation_to_video;	/* one of MMI_GFX_VIDEO_RELATION_* */ +			uint8_t multiple_depths; +			uint16_t display_bytes; +			uint8_t composition_buffer_bytes; +			uint8_t object_cache_bytes; +			uint8_t num_pixel_depths; +			struct en50221_app_mmi_pixel_depth *pixel_depths; +		} gfx;	/* MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS or +				MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS */ + +		struct { +			uint32_t table_length; +			uint8_t *table; +		} char_table;	/* MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES or +					MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES */ + +		struct { +			uint8_t mmi_mode;	/* one of the MMI_MODE_* values */ +		} mode_ack;	/* for MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK */ +	} u; +}; + +/** + * Pointer to a text string. + */ +struct en50221_app_mmi_text { +	uint8_t *text; +	uint32_t text_length; +}; + +/** + * Type definition for close - called when we receive an mmi_close from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param cmd_id One of the MMI_CLOSE_MMI_CMD_ID_* values. + * @param delay Delay supplied with MMI_CLOSE_MMI_CMD_ID_DELAY. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_close_callback) (void *arg, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t cmd_id, +					       uint8_t delay); + +/** + * Type definition for display_control callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param cmd_id One of the MMI_DISPLAY_CONTROL_CMD_ID_* values. + * @param delay One of the MMI_MODE_* values. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_display_control_callback) (void *arg, +							 uint8_t slot_id, +							 uint16_t session_number, +							 uint8_t cmd_id, +							 uint8_t mmi_mode); + +/** + * Type definition for keypad_control callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param cmd_id One of the MMI_KEYPAD_CONTROL_CMD_ID_* values. + * @param key_codes Pointer to the key codes. + * @param key_codes_count Number of key codes. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_keypad_control_callback) (void *arg, +							uint8_t slot_id, +							uint16_t session_number, +							uint8_t cmd_id, +							uint8_t *key_codes, +							uint32_t key_codes_count); + +/** + * Type definition for subtitle_segment callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param segment Pointer to the segment data. + * @param segment_size Size of segment data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_subtitle_segment_callback) (void *arg, +							  uint8_t slot_id, +							  uint16_t session_number, +							  uint8_t *segment, +							  uint32_t segment_size); + +/** + * Type definition for scene_end_mark callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param decoder_continue_flag + * @param scene_reveal_flag + * @param send_scene_done + * @param scene_tag + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_scene_end_mark_callback) (void *arg, +							uint8_t slot_id, +							uint16_t session_number, +							uint8_t decoder_continue_flag, +							uint8_t scene_reveal_flag, +							uint8_t send_scene_done, +							uint8_t scene_tag); + +/** + * Type definition for scene_control callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param decoder_continue_flag + * @param scene_reveal_flag + * @param scene_tag + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_scene_control_callback) (void *arg, +						       uint8_t slot_id, +						       uint16_t session_number, +						       uint8_t decoder_continue_flag, +						       uint8_t scene_reveal_flag, +						       uint8_t scene_tag); + +/** + * Type definition for subtitle_download callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param segment Pointer to the segment data. + * @param segment_size Size of segment data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_subtitle_download_callback) (void *arg, +							   uint8_t slot_id, +							   uint16_t session_number, +							   uint8_t *segment, +							   uint32_t segment_size); + +/** + * Type definition for flush_download callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_flush_download_callback) (void *arg, +							uint8_t slot_id, +							uint16_t session_number); + +/** + * Type definition for enq callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param blind_answer 1=>Obscure text input in some manner, + * @param expected_answer_length Expected max number of characters to be returned. + * @param text Pointer to the text data. + * @param text_size Size of text data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_enq_callback) (void *arg, +					     uint8_t slot_id, +					     uint16_t session_number, +					     uint8_t blind_answer, +					     uint8_t expected_answer_length, +					     uint8_t * text, +					     uint32_t text_size); + +/** + * Type definition for menu callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param title Title text. + * @param sub_title Sub-Title text. + * @param bottom Bottom text. + * @param item_count Number of text elements in items. + * @param items Pointer to array of en50221_app_mmi_text structures which are standard menu choices, + * @param item_raw_length Length of item raw data. + * @param items_raw If nonstandard items were supplied, pointer to their data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_menu_callback) (void *arg, +					      uint8_t slot_id, +					      uint16_t session_number, +					      struct en50221_app_mmi_text *title, +					      struct en50221_app_mmi_text *sub_title, +					      struct en50221_app_mmi_text *bottom, +					      uint32_t item_count, +					      struct en50221_app_mmi_text *items, +					      uint32_t item_raw_length, +					      uint8_t *items_raw); + +/** + * Type definition for list callback. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param title Title text. + * @param sub_title Sub-Title text. + * @param bottom Bottom text. + * @param item_count Number of text elements in items. + * @param items Pointer to array of en50221_app_mmi_text structures which are standard menu choices, + * @param item_raw_length Length of item raw data. + * @param items_raw If nonstandard items were supplied, pointer to their data. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_mmi_list_callback) (void *arg, +					      uint8_t slot_id, +					      uint16_t session_number, +					      struct en50221_app_mmi_text *title, +					      struct en50221_app_mmi_text *sub_title, +					      struct en50221_app_mmi_text *bottom, +					      uint32_t item_count, +					      struct en50221_app_mmi_text *items, +					      uint32_t item_raw_length, +					      uint8_t *items_raw); + +/** + * Opaque type representing a mmi resource. + */ +struct en50221_app_mmi; + +/** + * Create an instance of the mmi resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_mmi *en50221_app_mmi_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the mmi resource. + * + * @param mmi Instance to destroy. + */ +extern void en50221_app_mmi_destroy(struct en50221_app_mmi *mmi); + +/** + * Informs the mmi object that a session to it has been closed - cleans up internal state. + * + * @param mmi mmi resource instance. + * @param session_number The session concerned. + */ +extern void en50221_app_mmi_clear_session(struct en50221_app_mmi *mmi, +					  uint16_t session_number); + +/** + * Register the callback for when we receive an mmi_close request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_close_callback(struct en50221_app_mmi *mmi, +						    en50221_app_mmi_close_callback callback, +						    void *arg); + +/** + * Register the callback for when we receive a display control request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_display_control_callback(struct en50221_app_mmi *mmi, +							      en50221_app_mmi_display_control_callback callback, +							      void *arg); + +/** + * Register the callback for when we receive a keypad control request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_keypad_control_callback(struct en50221_app_mmi *mmi, +							     en50221_app_mmi_keypad_control_callback callback, +							     void *arg); + +/** + * Register the callback for when we receive a subtitle segment request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_subtitle_segment_callback(struct en50221_app_mmi *mmi, +							       en50221_app_mmi_subtitle_segment_callback callback, +							       void *arg); + +/** + * Register the callback for when we receive a scene end mark request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_scene_end_mark_callback(struct en50221_app_mmi *mmi, +							     en50221_app_mmi_scene_end_mark_callback callback, +							     void *arg); + +/** + * Register the callback for when we receive a scene control request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_scene_control_callback(struct en50221_app_mmi *mmi, +							    en50221_app_mmi_scene_control_callback callback, +							    void *arg); + +/** + * Register the callback for when we receive a subtitle download request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_subtitle_download_callback(struct en50221_app_mmi *mmi, +							        en50221_app_mmi_subtitle_download_callback callback, +							        void *arg); + +/** + * Register the callback for when we receive a flush download request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_flush_download_callback(struct en50221_app_mmi *mmi, +							     en50221_app_mmi_flush_download_callback callback, +							     void *arg); + +/** + * Register the callback for when we receive an enq request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_enq_callback(struct en50221_app_mmi *mmi, +						  en50221_app_mmi_enq_callback callback, +						  void *arg); + +/** + * Register the callback for when we receive a menu request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_menu_callback(struct en50221_app_mmi *mmi, +						   en50221_app_mmi_menu_callback callback, +						   void *arg); + +/** + * Register the callback for when we receive a list request. + * + * @param mmi mmi resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_mmi_register_list_callback(struct en50221_app_mmi *mmi, +						   en50221_app_mmi_list_callback callback, +						   void *arg); + +/** + * Send an mmi_close to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param cmd_id One of the MMI_CLOSE_MMI_CMD_ID_* values. + * @param delay Delay to use if MMI_CLOSE_MMI_CMD_ID_DELAY specified. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_close(struct en50221_app_mmi *mmi, +				 uint16_t session_number, +				 uint8_t cmd_id, uint8_t delay); + +/** + * Send a display_reply to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param reply_id One of the MMI_DISPLAY_REPLY_ID_* values. + * @param details The details of the reply - can be NULL if the chosen reply_id does not need it. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_display_reply(struct en50221_app_mmi *mmi, +					 uint16_t session_number, +					 uint8_t reply_id, +					 struct en50221_app_mmi_display_reply_details *details); + +/** + * Send a keypress to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param keycode The keycode. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_keypress(struct en50221_app_mmi *mmi, +				    uint16_t session_number, +				    uint8_t keycode); + +/** + * Send a display message to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param display_message_id One of the MMI_DISPLAY_MESSAGE_ID_* values. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_display_message(struct en50221_app_mmi *mmi, +					   uint16_t session_number, +					   uint8_t display_message_id); + +/** + * Send a scene done message to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param decoder_continue Copy of flag in scene_end_mark. + * @param scene_reveal Copy of flag in scene_end_mark. + * @param scene_tag Scene tag this responds to. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_scene_done(struct en50221_app_mmi *mmi, +				      uint16_t session_number, +				      uint8_t decoder_continue, +				      uint8_t scene_reveal, +				      uint8_t scene_tag); + +/** + * Send a download reply to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param object_id Object id. + * @param download_reply_id One of the MMI_DOWNLOAD_REPLY_ID_* values. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_download_reply(struct en50221_app_mmi *mmi, +					  uint16_t session_number, +					  uint16_t object_id, +					  uint8_t download_reply_id); + +/** + * Send an answ to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param answ_id One of the MMI_ANSW_ID_* values. + * @param text The text if MMI_ANSW_ID_ANSWER. + * @param text_count Length of text. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_answ(struct en50221_app_mmi *mmi, +				uint16_t session_number, +				uint8_t answ_id, +				uint8_t * text, +				uint32_t text_count); + +/** + * Send a menu answ to the cam. + * + * @param mmi mmi resource instance. + * @param session_number Session number to send it on. + * @param choice_ref Option chosen by user (0=>canceled). + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_menu_answ(struct en50221_app_mmi *mmi, +				     uint16_t session_number, +				     uint8_t choice_ref); + +/** + * Pass data received for this resource into it for parsing. + * + * @param mmi mmi instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_mmi_message(struct en50221_app_mmi *mmi, +				   uint8_t slot_id, +				   uint16_t session_number, +				   uint32_t resource_id, +				   uint8_t *data, +				   uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_rm.c b/lib/libdvben50221/en50221_app_rm.c new file mode 100644 index 0000000..7a5bc2f --- /dev/null +++ b/lib/libdvben50221/en50221_app_rm.c @@ -0,0 +1,307 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include <libucsi/endianops.h> +#include "en50221_app_rm.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_rm { +	struct en50221_app_send_functions *funcs; + +	en50221_app_rm_enq_callback enqcallback; +	void *enqcallback_arg; + +	en50221_app_rm_reply_callback replycallback; +	void *replycallback_arg; + +	en50221_app_rm_changed_callback changedcallback; +	void *changedcallback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_rm_parse_profile_enq(struct en50221_app_rm *rm, +					    uint8_t slot_id, +					    uint16_t session_number, +					    uint8_t * data, +					    uint32_t data_length); +static int en50221_app_rm_parse_profile_reply(struct en50221_app_rm *rm, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t * data, +					      uint32_t data_length); +static int en50221_app_rm_parse_profile_change(struct en50221_app_rm *rm, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length); + + +struct en50221_app_rm *en50221_app_rm_create(struct +					     en50221_app_send_functions +					     *funcs) +{ +	struct en50221_app_rm *rm = NULL; + +	// create structure and set it up +	rm = malloc(sizeof(struct en50221_app_rm)); +	if (rm == NULL) { +		return NULL; +	} +	rm->funcs = funcs; +	rm->enqcallback = NULL; +	rm->replycallback = NULL; +	rm->changedcallback = NULL; + +	pthread_mutex_init(&rm->lock, NULL); + +	// done +	return rm; +} + +void en50221_app_rm_destroy(struct en50221_app_rm *rm) +{ +	pthread_mutex_destroy(&rm->lock); +	free(rm); +} + +void en50221_app_rm_register_enq_callback(struct en50221_app_rm *rm, +					  en50221_app_rm_enq_callback +					  callback, void *arg) +{ +	pthread_mutex_lock(&rm->lock); +	rm->enqcallback = callback; +	rm->enqcallback_arg = arg; +	pthread_mutex_unlock(&rm->lock); +} + +void en50221_app_rm_register_reply_callback(struct en50221_app_rm *rm, +					    en50221_app_rm_reply_callback +					    callback, void *arg) +{ +	pthread_mutex_lock(&rm->lock); +	rm->replycallback = callback; +	rm->replycallback_arg = arg; +	pthread_mutex_unlock(&rm->lock); +} + +void en50221_app_rm_register_changed_callback(struct en50221_app_rm *rm, +					      en50221_app_rm_changed_callback +					      callback, void *arg) +{ +	pthread_mutex_lock(&rm->lock); +	rm->changedcallback = callback; +	rm->changedcallback_arg = arg; +	pthread_mutex_unlock(&rm->lock); +} + +int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number) +{ +	uint8_t buf[4]; + +	// set up the tag +	buf[0] = (TAG_PROFILE_ENQUIRY >> 16) & 0xFF; +	buf[1] = (TAG_PROFILE_ENQUIRY >> 8) & 0xFF; +	buf[2] = TAG_PROFILE_ENQUIRY & 0xFF; +	buf[3] = 0; + +	// create the data and send it +	return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4); +} + +int en50221_app_rm_reply(struct en50221_app_rm *rm, +			 uint16_t session_number, +			 uint32_t resource_id_count, +			 uint32_t * resource_ids) +{ +	uint8_t buf[10]; + +	// set up the tag +	buf[0] = (TAG_PROFILE >> 16) & 0xFF; +	buf[1] = (TAG_PROFILE >> 8) & 0xFF; +	buf[2] = TAG_PROFILE & 0xFF; + +	// encode the length field +	int length_field_len; +	if ((length_field_len = asn_1_encode(resource_id_count * 4, buf + 3, 3)) < 0) { +		return -1; +	} +	// copy the data and byteswap it +	uint32_t *copy_resource_ids = alloca(4 * resource_id_count); +	if (copy_resource_ids == NULL) { +		return -1; +	} +	uint8_t *data = (uint8_t *) copy_resource_ids; +	memcpy(data, resource_ids, resource_id_count * 4); +	uint32_t i; +	for (i = 0; i < resource_id_count; i++) { +		bswap32(data); +		data += 4; +	} + +	// build the iovecs +	struct iovec iov[2]; +	iov[0].iov_base = buf; +	iov[0].iov_len = 3 + length_field_len; +	iov[1].iov_base = (uint8_t *) copy_resource_ids; +	iov[1].iov_len = resource_id_count * 4; + +	// create the data and send it +	return rm->funcs->send_datav(rm->funcs->arg, session_number, iov, 2); +} + +int en50221_app_rm_changed(struct en50221_app_rm *rm, +			   uint16_t session_number) +{ +	uint8_t buf[4]; + +	// set up the tag +	buf[0] = (TAG_PROFILE_CHANGE >> 16) & 0xFF; +	buf[1] = (TAG_PROFILE_CHANGE >> 8) & 0xFF; +	buf[2] = TAG_PROFILE_CHANGE & 0xFF; +	buf[3] = 0; + +	// create the data and send it +	return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4); +} + +int en50221_app_rm_message(struct en50221_app_rm *rm, +			   uint8_t slot_id, +			   uint16_t session_number, +			   uint32_t resource_id, +			   uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	// dispatch it +	switch (tag) { +	case TAG_PROFILE_ENQUIRY: +		return en50221_app_rm_parse_profile_enq(rm, slot_id, +							session_number, +							data + 3, +							data_length - 3); +	case TAG_PROFILE: +		return en50221_app_rm_parse_profile_reply(rm, slot_id, +							  session_number, +							  data + 3, +							  data_length - 3); +	case TAG_PROFILE_CHANGE: +		return en50221_app_rm_parse_profile_change(rm, slot_id, +							   session_number, +							   data + 3, +							   data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + +static int en50221_app_rm_parse_profile_enq(struct en50221_app_rm *rm, +					    uint8_t slot_id, +					    uint16_t session_number, +					    uint8_t * data, +					    uint32_t data_length) +{ +	(void) data; +	(void) data_length; + +	pthread_mutex_lock(&rm->lock); +	en50221_app_rm_enq_callback cb = rm->enqcallback; +	void *cb_arg = rm->enqcallback_arg; +	pthread_mutex_unlock(&rm->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number); +	} +	return 0; +} + +static int en50221_app_rm_parse_profile_reply(struct en50221_app_rm *rm, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t * data, +					      uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t resources_count = asn_data_length / 4; +	uint32_t *resource_ids = (uint32_t *) (data + length_field_len); +	data += length_field_len; + +	// byteswap it +	uint32_t i; +	for (i = 0; i < resources_count; i++) { +		bswap32(data); +		data += 4; +	} + +	// inform observer +	pthread_mutex_lock(&rm->lock); +	en50221_app_rm_reply_callback cb = rm->replycallback; +	void *cb_arg = rm->replycallback_arg; +	pthread_mutex_unlock(&rm->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, resources_count, resource_ids); +	} +	return 0; +} + +static int en50221_app_rm_parse_profile_change(struct en50221_app_rm *rm, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length) +{ +	(void) data; +	(void) data_length; + +	pthread_mutex_lock(&rm->lock); +	en50221_app_rm_changed_callback cb = rm->changedcallback; +	void *cb_arg = rm->changedcallback_arg; +	pthread_mutex_unlock(&rm->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_rm.h b/lib/libdvben50221/en50221_app_rm.h new file mode 100644 index 0000000..ec97372 --- /dev/null +++ b/lib/libdvben50221/en50221_app_rm.h @@ -0,0 +1,187 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_RM_H__ +#define __EN50221_APPLICATION_RM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_RM_RESOURCEID MKRID(1,1,1) + +/** + * Type definition for profile_enq callback function - called when we receive + * a profile_enq from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_rm_enq_callback) (void *arg, +					    uint8_t slot_id, +					    uint16_t session_number); + +/** + * Type definition for profile_reply callback function - called when we receive + * a profile_reply from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param resource_id_count Number of resource_ids. + * @param resource_ids The resource ids themselves. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_rm_reply_callback) (void *arg, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint32_t resource_id_count, +					      uint32_t *resource_ids); +/** + * Type definition for profile_changed callback function - called when we receive + * a profile_changed from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_rm_changed_callback) (void *arg, +						uint8_t slot_id, +						uint16_t session_number); + + + +/** + * Opaque type representing a resource manager. + */ +struct en50221_app_rm; + +/** + * Create an instance of the resource manager. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_rm *en50221_app_rm_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the resource manager. + * + * @param rm Instance to destroy. + */ +extern void en50221_app_rm_destroy(struct en50221_app_rm *rm); + +/** + * Register the callback for when we receive a profile_enq from a CAM. + * + * @param rm Resource manager instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_rm_register_enq_callback(struct en50221_app_rm *rm, +						 en50221_app_rm_enq_callback callback, +						 void *arg); + +/** + * Register the callback for when we receive a profile_reply from a CAM. + * + * @param rm Resource manager instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_rm_register_reply_callback(struct en50221_app_rm *rm, +						   en50221_app_rm_reply_callback callback, +						   void *arg); + +/** + * Register the callback for when we receive a profile_changed from a CAM. + * + * @param rm Resource manager instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_rm_register_changed_callback(struct en50221_app_rm *rm, +						     en50221_app_rm_changed_callback callback, +						     void *arg); + +/** + * Send a profile_enq to a CAM. + * + * @param rm Resource manager resource instance. + * @param session_number Session number to send it on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number); + +/** + * Send a profile_reply to a CAM. + * + * @param rm Resource manager resource instance. + * @param session_number Session number to send it on. + * @param resource_id_count Number of resource ids. + * @param resource_ids The resource IDs themselves + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_rm_reply(struct en50221_app_rm *rm, +				uint16_t session_number, +				uint32_t resource_id_count, +				uint32_t * resource_ids); + +/** + * Send a profile_changed to a CAM. + * + * @param rm Resource manager resource instance. + * @param session_number Session number to send it on. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_rm_changed(struct en50221_app_rm *rm, uint16_t session_number); + +/** + * Pass data received for this resource into it for parsing. + * + * @param rm rm instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_rm_message(struct en50221_app_rm *rm, +				  uint8_t slot_id, +				  uint16_t session_number, +				  uint32_t resource_id, +				  uint8_t *data, +				  uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_smartcard.c b/lib/libdvben50221/en50221_app_smartcard.c new file mode 100644 index 0000000..763c6c4 --- /dev/null +++ b/lib/libdvben50221/en50221_app_smartcard.c @@ -0,0 +1,296 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_smartcard.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_smartcard { +	struct en50221_app_send_functions *funcs; + +	en50221_app_smartcard_command_callback command_callback; +	void *command_callback_arg; + +	en50221_app_smartcard_send_callback send_callback; +	void *send_callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard *smartcard, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length); + +static int en50221_app_smartcard_parse_send(struct en50221_app_smartcard *smartcard, +					    uint8_t slot_id, +					    uint16_t session_number, +					    uint8_t * data, +					    uint32_t data_length); + + +struct en50221_app_smartcard *en50221_app_smartcard_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_smartcard *smartcard = NULL; + +	// create structure and set it up +	smartcard = malloc(sizeof(struct en50221_app_smartcard)); +	if (smartcard == NULL) { +		return NULL; +	} +	smartcard->funcs = funcs; +	smartcard->command_callback = NULL; +	smartcard->send_callback = NULL; + +	pthread_mutex_init(&smartcard->lock, NULL); + +	// done +	return smartcard; +} + +void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard) +{ +	pthread_mutex_destroy(&smartcard->lock); +	free(smartcard); +} + +void en50221_app_smartcard_register_command_callback(struct en50221_app_smartcard *smartcard, +						     en50221_app_smartcard_command_callback callback, void *arg) +{ +	pthread_mutex_lock(&smartcard->lock); +	smartcard->command_callback = callback; +	smartcard->command_callback_arg = arg; +	pthread_mutex_unlock(&smartcard->lock); +} + +void en50221_app_smartcard_register_send_callback(struct en50221_app_smartcard *smartcard, +						  en50221_app_smartcard_send_callback callback, void *arg) +{ +	pthread_mutex_lock(&smartcard->lock); +	smartcard->send_callback = callback; +	smartcard->send_callback_arg = arg; +	pthread_mutex_unlock(&smartcard->lock); +} + +int en50221_app_smartcard_command_reply(struct en50221_app_smartcard *smartcard, +					uint16_t session_number, +					uint8_t reply_id, uint8_t status, +					uint8_t *data, +					uint32_t data_length) +{ +	uint8_t hdr[10]; +	struct iovec iovec[2]; +	int iov_count = 0; + +	// the tag +	hdr[0] = (TAG_SMARTCARD_REPLY >> 16) & 0xFF; +	hdr[1] = (TAG_SMARTCARD_REPLY >> 8) & 0xFF; +	hdr[2] = TAG_SMARTCARD_REPLY & 0xFF; + +	// the rest of the data +	if (reply_id == SMARTCARD_REPLY_ID_ANSW_TO_RESET) { +		// encode the length field +		int length_field_len; +		if ((length_field_len = asn_1_encode(data_length + 2, data + 3, 3)) < 0) { +			return -1; +		} +		// the rest of the header +		hdr[3 + length_field_len] = reply_id; +		hdr[3 + length_field_len + 1] = status; +		iovec[0].iov_base = hdr; +		iovec[0].iov_len = 3 + length_field_len + 2; + +		// the data +		iovec[1].iov_base = data; +		iovec[1].iov_len = data_length; +		iov_count = 2; +	} else { +		hdr[3] = 2; +		hdr[4] = reply_id; +		hdr[5] = status; +		iovec[0].iov_base = data; +		iovec[0].iov_len = 6; +		iov_count = 1; +	} + +	return smartcard->funcs->send_datav(smartcard->funcs->arg, session_number, iovec, iov_count); +} + +int en50221_app_smartcard_receive(struct en50221_app_smartcard *smartcard, +				  uint16_t session_number, +				  uint8_t *data, +				  uint32_t data_length, +				  uint8_t SW1, uint8_t SW2) +{ +	uint8_t buf[10]; +	uint8_t trailer[10]; + +	// set up the tag +	buf[0] = (TAG_SMARTCARD_RCV >> 16) & 0xFF; +	buf[1] = (TAG_SMARTCARD_RCV >> 8) & 0xFF; +	buf[2] = TAG_SMARTCARD_RCV & 0xFF; + +	// encode the length field +	int length_field_len; +	if ((length_field_len = asn_1_encode(data_length + 2, buf + 3, 3)) < 0) { +		return -1; +	} +	// set up the trailer +	trailer[0] = SW1; +	trailer[1] = SW2; + +	// build the iovecs +	struct iovec iov[3]; +	iov[0].iov_base = buf; +	iov[0].iov_len = 3 + length_field_len; +	iov[1].iov_base = data; +	iov[1].iov_len = data_length; +	iov[2].iov_base = trailer; +	iov[2].iov_len = 2; + +	// create the data and send it +	return smartcard->funcs->send_datav(smartcard->funcs->arg, +					    session_number, iov, 3); +} + +int en50221_app_smartcard_message(struct en50221_app_smartcard *smartcard, +				  uint8_t slot_id, +				  uint16_t session_number, +				  uint32_t resource_id, +				  uint8_t *data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_SMARTCARD_COMMAND: +		return en50221_app_smartcard_parse_command(smartcard, +							   slot_id, +							   session_number, +							   data + 3, +							   data_length - 3); +	case TAG_SMARTCARD_SEND: +		return en50221_app_smartcard_parse_send(smartcard, slot_id, +							session_number, +							data + 3, +							data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + + + + + + +static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard *smartcard, +					       uint8_t slot_id, +					       uint16_t session_number, +					       uint8_t * data, +					       uint32_t data_length) +{ +	if (data_length != 2) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (data[0] != 1) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t command_id = data[1]; + +	// tell the app +	pthread_mutex_lock(&smartcard->lock); +	en50221_app_smartcard_command_callback cb = smartcard->command_callback; +	void *cb_arg = smartcard->command_callback_arg; +	pthread_mutex_unlock(&smartcard->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, command_id); +	} +	return 0; +} + +static int en50221_app_smartcard_parse_send(struct en50221_app_smartcard *smartcard, +					    uint8_t slot_id, +					    uint16_t session_number, +					    uint8_t * data, +					    uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} +	// check it +	if (asn_data_length < 8) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	data += length_field_len; + +	// parse +	uint8_t CLA = data[0]; +	uint8_t INS = data[1]; +	uint8_t P1 = data[2]; +	uint8_t P2 = data[3]; +	uint16_t length_in = (data[4] << 8) | data[5]; +	uint8_t *data_in = data + 6; + +	// validate the length +	if ((length_in + 8) != asn_data_length) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint16_t length_out = +	    (data[6 + length_in] << 8) | data[6 + length_in + 1]; + +	// tell the app +	pthread_mutex_lock(&smartcard->lock); +	en50221_app_smartcard_send_callback cb = smartcard->send_callback; +	void *cb_arg = smartcard->send_callback_arg; +	pthread_mutex_unlock(&smartcard->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, CLA, INS, P1, +			  P2, data_in, length_in, length_out); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_smartcard.h b/lib/libdvben50221/en50221_app_smartcard.h new file mode 100644 index 0000000..bbad4a9 --- /dev/null +++ b/lib/libdvben50221/en50221_app_smartcard.h @@ -0,0 +1,200 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_smartcard_H__ +#define __EN50221_APPLICATION_smartcard_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define SMARTCARD_COMMAND_ID_CONNECT            0x01 +#define SMARTCARD_COMMAND_ID_DISCONNECT         0x02 +#define SMARTCARD_COMMAND_ID_POWERON_CARD       0x03 +#define SMARTCARD_COMMAND_ID_POWEROFF_CARD      0x04 +#define SMARTCARD_COMMAND_ID_RESET_CARD         0x05 +#define SMARTCARD_COMMAND_ID_RESET_STATUS       0x06 +#define SMARTCARD_COMMAND_ID_READ_ANSW_TO_RESET 0x07 + +#define SMARTCARD_REPLY_ID_CONNECTED            0x01 +#define SMARTCARD_REPLY_ID_FREE                 0x02 +#define SMARTCARD_REPLY_ID_BUSY                 0x03 +#define SMARTCARD_REPLY_ID_ANSW_TO_RESET        0x04 +#define SMARTCARD_REPLY_ID_NO_ANSW_TO_RESET     0x05 + +#define SMARTCARD_STATUS_CARD_INSERTED          0x01 +#define SMARTCARD_STATUS_CARD_REMOVED           0x02 +#define SMARTCARD_STATUS_CARD_IN_PLACE_POWEROFF 0x03 +#define SMARTCARD_STATUS_CARD_IN_PLACE_POWERON  0x04 +#define SMARTCARD_STATUS_CARD_NO_CARD           0x05 +#define SMARTCARD_STATUS_CARD_UNRESPONSIVE_CARD 0x06 +#define SMARTCARD_STATUS_CARD_REFUSED_CARD      0x07 + +#define EN50221_APP_SMARTCARD_RESOURCEID(DEVICE_NUMBER) MKRID(112, ((DEVICE_NUMBER)& 0x0f), 1) + + + +/** + * Type definition for command - called when we receive a command. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param command_id One of the SMARTCARD_COMMAND_ID_* values + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_smartcard_command_callback) (void *arg, +						       uint8_t slot_id, +						       uint16_t session_number, +						       uint8_t command_id); + +/** + * Type definition for command - called when we receive a send command. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param CLA CLA value. + * @param INS INS value. + * @param P1 P1 value. + * @param P2 P2 value. + * @param in Data to send to the card + * @param in_length Number of bytes to send. + * @param out_length Number of bytes expected. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_smartcard_send_callback) (void *arg, +						    uint8_t slot_id, +						    uint16_t session_number, +						    uint8_t CLA, +						    uint8_t INS, +						    uint8_t P1, +						    uint8_t P2, +						    uint8_t *in, +						    uint32_t in_length, +						    uint32_t out_length); + +/** + * Opaque type representing a smartcard resource. + */ +struct en50221_app_smartcard; + +/** + * Create an instance of the smartcard resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_smartcard * +	en50221_app_smartcard_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the smartcard resource. + * + * @param smartcard Instance to destroy. + */ +extern void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard); + +/** + * Register the callback for when we receive a comms command. + * + * @param smartcard smartcard resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_smartcard_register_command_callback(struct en50221_app_smartcard *smartcard, +							    en50221_app_smartcard_command_callback callback, +							    void *arg); + +/** + * Register the callback for when we receive data to send. + * + * @param smartcard smartcard resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_smartcard_register_send_callback(struct en50221_app_smartcard *smartcard, +							 en50221_app_smartcard_send_callback callback, +							 void *arg); + +/** + * Send a command response to the CAM. + * + * @param smartcard smartcard resource instance. + * @param session_number Session number to send it on. + * @param reply_id One of the SMARTCARD_REPLY_ID_* values. + * @param status One of the SMARTCARD_STATUS_* values. + * @param data Data to send when it is a SMARTCARD_REPLY_ID_ANSW_TO_RESET. + * @param data_length Length of data to send. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_smartcard_command_reply(struct en50221_app_smartcard *smartcard, +					       uint16_t session_number, +					       uint8_t reply_id, +					       uint8_t status, +					       uint8_t * data, +					       uint32_t data_length); + +/** + * Send data received from a smartcart to the CAM. + * + * @param smartcard smartcard resource instance. + * @param session_number Session number to send it on. + * @param data Data to send when it is a SMARTCARD_REPLY_ID_ANSW_TO_RESET. + * @param data_length Length of data to send. + * @param SW1 SW1 value. + * @param SW2 SW2 value. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_smartcard_receive(struct en50221_app_smartcard *smartcard, +					 uint16_t session_number, +					 uint8_t * data, +					 uint32_t data_length, +					 uint8_t SW1, uint8_t SW2); + +/** + * Pass data received for this resource into it for parsing. + * + * @param smartcard smartcard instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_smartcard_message(struct en50221_app_smartcard *smartcard, +					 uint8_t slot_id, +					 uint16_t session_number, +					 uint32_t resource_id, +					 uint8_t * data, +					 uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_tags.h b/lib/libdvben50221/en50221_app_tags.h new file mode 100644 index 0000000..0f5c2fc --- /dev/null +++ b/lib/libdvben50221/en50221_app_tags.h @@ -0,0 +1,104 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) + +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APP_TAGS_H__ +#define __EN50221_APP_TAGS_H__ + +/*	Resource Manager		*/ +#define TAG_PROFILE_ENQUIRY		0x9f8010 +#define TAG_PROFILE			0x9f8011 +#define TAG_PROFILE_CHANGE		0x9f8012 + +/*	Application Info		*/ +#define TAG_APP_INFO_ENQUIRY		0x9f8020 +#define TAG_APP_INFO			0x9f8021 +#define TAG_ENTER_MENU			0x9f8022 + +/*	CA Support			*/ +#define TAG_CA_INFO_ENQUIRY		0x9f8030 +#define TAG_CA_INFO			0x9f8031 +#define TAG_CA_PMT			0x9f8032 +#define TAG_CA_PMT_REPLY		0x9f8033 + +/*	Host Control			*/ +#define TAG_TUNE			0x9f8400 +#define TAG_REPLACE			0x9f8401 +#define TAG_CLEAR_REPLACE		0x9f8402 +#define TAG_ASK_RELEASE			0x9f8403 + +/*	Date and Time			*/ +#define TAG_DATE_TIME_ENQUIRY		0x9f8440 +#define TAG_DATE_TIME			0x9f8441 + +/*	Man Machine Interface (MMI)	*/ +#define TAG_CLOSE_MMI			0x9f8800 +#define TAG_DISPLAY_CONTROL		0x9f8801 +#define TAG_DISPLAY_REPLY		0x9f8802 +#define TAG_TEXT_LAST			0x9f8803 +#define TAG_TEXT_MORE			0x9f8804 +#define TAG_KEYPAD_CONTROL		0x9f8805 +#define TAG_KEYPRESS			0x9f8806 +#define TAG_ENQUIRY			0x9f8807 +#define TAG_ANSWER			0x9f8808 +#define TAG_MENU_LAST			0x9f8809 +#define TAG_MENU_MORE			0x9f880a +#define TAG_MENU_ANSWER			0x9f880b +#define TAG_LIST_LAST			0x9f880c +#define TAG_LIST_MORE			0x9f880d +#define TAG_SUBTITLE_SEGMENT_LAST	0x9f880e +#define TAG_SUBTITLE_SEGMENT_MORE	0x9f880f +#define TAG_DISPLAY_MESSAGE		0x9f8810 +#define TAG_SCENE_END_MARK		0x9f8811 +#define TAG_SCENE_DONE			0x9f8812 +#define TAG_SCENE_CONTROL		0x9f8813 +#define TAG_SUBTITLE_DOWNLOAD_LAST	0x9f8814 +#define TAG_SUBTITLE_DOWNLOAD_MORE	0x9f8815 +#define TAG_FLUSH_DOWNLOAD		0x9f8816 +#define TAG_DOWNLOAD_REPLY		0x9f8817 + +/*	Low Speed Communications	*/ +#define TAG_COMMS_COMMAND		0x9f8c00 +#define TAG_CONNECTION_DESCRIPTOR	0x9f8c01 +#define TAG_COMMS_REPLY			0x9f8c02 +#define TAG_COMMS_SEND_LAST		0x9f8c03 +#define TAG_COMMS_SEND_MORE		0x9f8c04 +#define TAG_COMMS_RECV_LAST		0x9f8c05 +#define TAG_COMMS_RECV_MORE		0x9f8c06 + +/* Authentication */ +#define TAG_AUTH_REQ			0x9f8200 +#define TAG_AUTH_RESP			0x9f8201 + +/* Teletext */ +#define TAG_TELETEXT_EBU		0x9f9000 + +/* Smartcard */ +#define TAG_SMARTCARD_COMMAND		0x9f8e00 +#define TAG_SMARTCARD_REPLY		0x9f8e01 +#define TAG_SMARTCARD_SEND		0x9f8e02 +#define TAG_SMARTCARD_RCV		0x9f8e03 + +/* EPG */ +#define TAG_EPG_ENQUIRY         	0x9f8f00 +#define TAG_EPG_REPLY           	0x9f8f01 + +#endif diff --git a/lib/libdvben50221/en50221_app_teletext.c b/lib/libdvben50221/en50221_app_teletext.c new file mode 100644 index 0000000..b839407 --- /dev/null +++ b/lib/libdvben50221/en50221_app_teletext.c @@ -0,0 +1,141 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <string.h> +#include <libdvbmisc/dvbmisc.h> +#include <pthread.h> +#include "en50221_app_teletext.h" +#include "en50221_app_tags.h" +#include "asn_1.h" + +struct en50221_app_teletext { +	struct en50221_app_send_functions *funcs; + +	en50221_app_teletext_callback callback; +	void *callback_arg; + +	pthread_mutex_t lock; +}; + +static int en50221_app_teletext_parse_ebu(struct en50221_app_teletext *teletext, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint8_t * data, +					  uint32_t data_length); + + + +struct en50221_app_teletext * +	en50221_app_teletext_create(struct en50221_app_send_functions *funcs) +{ +	struct en50221_app_teletext *teletext = NULL; + +	// create structure and set it up +	teletext = malloc(sizeof(struct en50221_app_teletext)); +	if (teletext == NULL) { +		return NULL; +	} +	teletext->funcs = funcs; +	teletext->callback = NULL; + +	pthread_mutex_init(&teletext->lock, NULL); + +	// done +	return teletext; +} + +void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext) +{ +	pthread_mutex_destroy(&teletext->lock); +	free(teletext); +} + +void en50221_app_teletext_register_callback(struct en50221_app_teletext *teletext, +					    en50221_app_teletext_callback callback, void *arg) +{ +	pthread_mutex_lock(&teletext->lock); +	teletext->callback = callback; +	teletext->callback_arg = arg; +	pthread_mutex_unlock(&teletext->lock); +} + +int en50221_app_teletext_message(struct en50221_app_teletext *teletext, +				 uint8_t slot_id, +				 uint16_t session_number, +				 uint32_t resource_id, +				 uint8_t * data, uint32_t data_length) +{ +	(void) resource_id; + +	// get the tag +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2]; + +	switch (tag) { +	case TAG_TELETEXT_EBU: +		return en50221_app_teletext_parse_ebu(teletext, slot_id, +						      session_number, +						      data + 3, +						      data_length - 3); +	} + +	print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag); +	return -1; +} + + +static int en50221_app_teletext_parse_ebu(struct en50221_app_teletext *teletext, +					  uint8_t slot_id, +					  uint16_t session_number, +					  uint8_t *data, +					  uint32_t data_length) +{ +	// first of all, decode the length field +	uint16_t asn_data_length; +	int length_field_len; +	if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) { +		print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n"); +		return -1; +	} + +	// check it +	if (asn_data_length > (data_length - length_field_len)) { +		print(LOG_LEVEL, ERROR, 1, "Received short data\n"); +		return -1; +	} +	uint8_t *teletext_data = data + length_field_len; + +	// tell the app +	pthread_mutex_lock(&teletext->lock); +	en50221_app_teletext_callback cb = teletext->callback; +	void *cb_arg = teletext->callback_arg; +	pthread_mutex_unlock(&teletext->lock); +	if (cb) { +		return cb(cb_arg, slot_id, session_number, teletext_data, +			  asn_data_length); +	} +	return 0; +} diff --git a/lib/libdvben50221/en50221_app_teletext.h b/lib/libdvben50221/en50221_app_teletext.h new file mode 100644 index 0000000..b5b85f1 --- /dev/null +++ b/lib/libdvben50221/en50221_app_teletext.h @@ -0,0 +1,107 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APPLICATION_teletext_H__ +#define __EN50221_APPLICATION_teletext_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_app_utils.h> + +#define EN50221_APP_TELETEXT_RESOURCEID MKRID(128, 1, 1) + + +/** + * Type definition for request - called when we receive teletext from a CAM. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number concerned. + * @param teletext_data Data for the request. + * @param teletext_data_lenghth Number of bytes. + * @return 0 on success, -1 on failure. + */ +typedef int (*en50221_app_teletext_callback) (void *arg, +					      uint8_t slot_id, +					      uint16_t session_number, +					      uint8_t *teletext_data, +					      uint32_t teletext_data_length); + +/** + * Opaque type representing a teletext resource. + */ +struct en50221_app_teletext; + +/** + * Create an instance of the teletext resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern struct en50221_app_teletext * +	en50221_app_teletext_create(struct en50221_app_send_functions *funcs); + +/** + * Destroy an instance of the teletext resource. + * + * @param teletext Instance to destroy. + */ +extern void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext); + +/** + * Register the callback for when we receive a request. + * + * @param teletext teletext resource instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_app_teletext_register_callback(struct en50221_app_teletext *teletext, +						   en50221_app_teletext_callback callback, +						   void *arg); + +/** + * Pass data received for this resource into it for parsing. + * + * @param teletext teletext instance. + * @param slot_id Slot ID concerned. + * @param session_number Session number concerned. + * @param resource_id Resource ID concerned. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, -1 on failure. + */ +extern int en50221_app_teletext_message(struct en50221_app_teletext *teletext, +					uint8_t slot_id, +					uint16_t session_number, +					uint32_t resource_id, +					uint8_t * data, +					uint32_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_app_utils.c b/lib/libdvben50221/en50221_app_utils.c new file mode 100644 index 0000000..df2632a --- /dev/null +++ b/lib/libdvben50221/en50221_app_utils.c @@ -0,0 +1,38 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include "en50221_app_utils.h" + +struct en50221_app_public_resource_id +	*en50221_app_decode_public_resource_id(struct en50221_app_public_resource_id *idf, +					       uint32_t resource_id) +{ +	// reject private resources +	if ((resource_id & 0xc0000000) == 0xc0000000) +		return NULL; + +	idf->resource_class = (resource_id >> 16) & 0xffff;	// use the resource_id as the MSBs of class +	idf->resource_type = (resource_id >> 6) & 0x3ff; +	idf->resource_version = resource_id & 0x3f; +	return idf; +} diff --git a/lib/libdvben50221/en50221_app_utils.h b/lib/libdvben50221/en50221_app_utils.h new file mode 100644 index 0000000..5c64760 --- /dev/null +++ b/lib/libdvben50221/en50221_app_utils.h @@ -0,0 +1,112 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef __EN50221_APP_UTILS_H__ +#define __EN50221_APP_UTILS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <sys/uio.h> + +/** + * A decomposed public resource structure. + * + * we will ignore private resource (resource_id_type==3), + * because they are not used by any modules at all and + * would need special code for any private resource anyway. + */ +struct en50221_app_public_resource_id { +	uint16_t resource_class; +	uint16_t resource_type; +	uint8_t resource_version; +}; + +typedef int (*en50221_send_data) (void *arg, +				  uint16_t session_number, +				  uint8_t * data, +				  uint16_t data_length); +typedef int (*en50221_send_datav) (void *arg, +				   uint16_t session_number, +				   struct iovec * vector, +				   int iov_count); + +/** + * An abstraction away from hardcoded send functions so different layers may be + * slotted in under the application layer. + */ +struct en50221_app_send_functions { +	/** +	 * Argument to pass to these functions. +	 */ +	void *arg; + +	/** +	 * Send data. +	 */ +	en50221_send_data send_data; + +	/** +	 * Send vector data. +	 */ +	en50221_send_datav send_datav; +}; + +/** + * Make a host-endian uint32_t formatted resource id. + * + * @param CLASS Class of resource. + * @param TYPE Type of resource. + * @param VERSION Version of resource. + * @return Formatted resource id. + */ +#define MKRID(CLASS, TYPE, VERSION) ((((CLASS)&0xffff)<<16) | (((TYPE)&0x3ff)<<6) | ((VERSION)&0x3f)) + +/** + * Decode a host-endian public resource_id into an en50221_app_public_resource_id structure. + * + * @param idf Structure to write decoded resource_id into. + * @param resource_id ID to decode. + * @return Pointer to idf on success, or NULL if this is not a public resource. + */ +struct en50221_app_public_resource_id * +	en50221_app_decode_public_resource_id(struct en50221_app_public_resource_id *idf, +					      uint32_t resource_id); + +/** + * Encode an en50221_app_public_resource_id structure into a host-endian uint32_t. + * + * @param idf Structure to encode. + * @return The encoded value + */ +static inline uint32_t en50221_app_encode_public_resource_id(struct en50221_app_public_resource_id *idf) { +	return MKRID(idf->resource_class, idf->resource_type, idf->resource_version); +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_errno.h b/lib/libdvben50221/en50221_errno.h new file mode 100644 index 0000000..0b53087 --- /dev/null +++ b/lib/libdvben50221/en50221_errno.h @@ -0,0 +1,49 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 session layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef EN50221_ERRNO +#define EN50221_ERRNO 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define EN50221ERR_CAREAD -1	/* error during read from CA device. */ +#define EN50221ERR_CAWRITE -2	/* error during write to CA device. */ +#define EN50221ERR_TIMEOUT -3	/* timeout occured waiting for a response from a device. */ +#define EN50221ERR_BADSLOTID -4	/* bad slot ID supplied by user - the offending slot_id will not be set. */ +#define EN50221ERR_BADCONNECTIONID -5	/* bad connection ID supplied by user. */ +#define EN50221ERR_BADSTATE -6	/* slot/connection in the wrong state. */ +#define EN50221ERR_BADCAMDATA -7	/* CAM supplied an invalid request. */ +#define EN50221ERR_OUTOFMEMORY -8	/* memory allocation failed. */ +#define EN50221ERR_ASNENCODE -9	/* ASN.1 encode failure - indicates library bug. */ +#define EN50221ERR_OUTOFCONNECTIONS -10	/* no more connections available. */ +#define EN50221ERR_OUTOFSLOTS -11	/* no more slots available - the offending slot_id will not be set. */ +#define EN50221ERR_IOVLIMIT -12	/* Too many struct iovecs were used. */ +#define EN50221ERR_BADSESSIONNUMBER -13	/* Bad session number suppplied by user. */ +#define EN50221ERR_OUTOFSESSIONS -14	/* no more sessions available. */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_session.c b/lib/libdvben50221/en50221_session.c new file mode 100644 index 0000000..3fb9902 --- /dev/null +++ b/lib/libdvben50221/en50221_session.c @@ -0,0 +1,1055 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <time.h> +#include <libdvbmisc/dvbmisc.h> +#include <sys/uio.h> +#include <pthread.h> +#include "en50221_transport.h" +#include "en50221_session.h" +#include "en50221_errno.h" +#include "asn_1.h" + + +// these are the possible session statuses +#define S_STATUS_OPEN                    0x00	// session is opened +#define S_STATUS_CLOSE_NO_RES            0xF0	// could not open session, no proper resource available +#define S_STATUS_CLOSE_RES_UNAVAILABLE   0xF1	// could not open session, resource unavailable +#define S_STATUS_CLOSE_RES_LOW_VERSION   0xF2	// could not open session, resource version too low +#define S_STATUS_CLOSE_RES_BUSY          0xF3	// could not open session, resource is busy + +#define ST_OPEN_SESSION_REQ     0x91	// h<--m +#define ST_OPEN_SESSION_RES     0x92	// h-->m +#define ST_CREATE_SESSION       0x93	// h-->m +#define ST_CREATE_SESSION_RES   0x94	// h<--m +#define ST_CLOSE_SESSION_REQ    0x95	// h<->m +#define ST_CLOSE_SESSION_RES    0x96	// h<->m +#define ST_SESSION_NUMBER       0x90	// h<->m + +#define S_STATE_IDLE            0x01	// this session is not in use +#define S_STATE_ACTIVE          0x02	// this session is in use +#define S_STATE_IN_CREATION     0x04	// this session waits for a ST_CREATE_SESSION_RES to become active +#define S_STATE_IN_DELETION     0x08	// this session waits for ST_CLOSE_SESSION_RES to become idle again + + +// for each session we store its identifier, the resource-id +// it is linked to and the callback of the specific resource +struct en50221_session { +	uint8_t state; +	uint32_t resource_id; +	uint8_t slot_id; +	uint8_t connection_id; + +	en50221_sl_resource_callback callback; +	void *callback_arg; + +	pthread_mutex_t session_lock; +}; + +struct en50221_session_layer { +	uint32_t max_sessions; +	struct en50221_transport_layer *tl; + +	en50221_sl_lookup_callback lookup; +	void *lookup_arg; + +	en50221_sl_session_callback session; +	void *session_arg; + +	pthread_mutex_t global_lock; +	pthread_mutex_t setcallback_lock; + +	int error; + +	struct en50221_session *sessions; +}; + +static void en50221_sl_transport_callback(void *arg, int reason, +					  uint8_t * data, +					  uint32_t data_length, +					  uint8_t slot_id, +					  uint8_t connection_id); +static int en50221_sl_alloc_new_session(struct en50221_session_layer *sl, +					uint32_t resource_id, +					uint8_t slot_id, +					uint8_t connection_id, +					en50221_sl_resource_callback +					callback, void *arg); + + + + +struct en50221_session_layer *en50221_sl_create(struct en50221_transport_layer *tl, +						uint32_t max_sessions) +{ +	struct en50221_session_layer *sl = NULL; +	uint32_t i; + +	// setup structure +	sl = (struct en50221_session_layer *) +	    malloc(sizeof(struct en50221_session_layer)); +	if (sl == NULL) +		goto error_exit; +	sl->max_sessions = max_sessions; +	sl->lookup = NULL; +	sl->session = NULL; +	sl->tl = tl; +	sl->error = 0; + +	// init the mutex +	pthread_mutex_init(&sl->global_lock, NULL); +	pthread_mutex_init(&sl->setcallback_lock, NULL); + +	// create the slots +	sl->sessions = malloc(sizeof(struct en50221_session) * max_sessions); +	if (sl->sessions == NULL) +		goto error_exit; + +	// set them up +	for (i = 0; i < max_sessions; i++) { +		sl->sessions[i].state = S_STATE_IDLE; +		sl->sessions[i].callback = NULL; + +		pthread_mutex_init(&sl->sessions[i].session_lock, NULL); +	} + +	// register ourselves with the transport layer +	en50221_tl_register_callback(tl, en50221_sl_transport_callback, sl); + +	return sl; + +error_exit: +	en50221_sl_destroy(sl); +	return NULL; +} + +void en50221_sl_destroy(struct en50221_session_layer *sl) +{ +	uint32_t i; + +	if (sl) { +		if (sl->sessions) { +			for (i = 0; i < sl->max_sessions; i++) { +				pthread_mutex_destroy(&sl->sessions[i].session_lock); +			} +			free(sl->sessions); +		} + +		pthread_mutex_destroy(&sl->setcallback_lock); +		pthread_mutex_destroy(&sl->global_lock); + +		free(sl); +	} +} + +int en50221_sl_get_error(struct en50221_session_layer *sl) +{ +	return sl->error; +} + +void en50221_sl_register_lookup_callback(struct en50221_session_layer *sl, +					 en50221_sl_lookup_callback +					 callback, void *arg) +{ +	pthread_mutex_lock(&sl->setcallback_lock); +	sl->lookup = callback; +	sl->lookup_arg = arg; +	pthread_mutex_unlock(&sl->setcallback_lock); +} + +void en50221_sl_register_session_callback(struct en50221_session_layer *sl, +					  en50221_sl_session_callback +					  callback, void *arg) +{ +	pthread_mutex_lock(&sl->setcallback_lock); +	sl->session = callback; +	sl->session_arg = arg; +	pthread_mutex_unlock(&sl->setcallback_lock); +} + +int en50221_sl_create_session(struct en50221_session_layer *sl, +			      int slot_id, uint8_t connection_id, +			      uint32_t resource_id, +			      en50221_sl_resource_callback callback, +			      void *arg) +{ +	// lookup next free session_id: +	pthread_mutex_lock(&sl->global_lock); +	int session_number = +	    en50221_sl_alloc_new_session(sl, resource_id, slot_id, +					 connection_id, callback, arg); +	if (session_number == -1) { +		pthread_mutex_unlock(&sl->global_lock); +		return -1; +	} +	pthread_mutex_unlock(&sl->global_lock); + +	// make up the header +	uint8_t hdr[8]; +	hdr[0] = ST_CREATE_SESSION; +	hdr[1] = 6; +	hdr[2] = resource_id >> 24; +	hdr[3] = resource_id >> 16; +	hdr[4] = resource_id >> 8; +	hdr[5] = resource_id; +	hdr[6] = session_number >> 8; +	hdr[7] = session_number; + +	// send this command +	if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 8)) { +		pthread_mutex_lock(&sl->sessions[session_number].session_lock); +		if (sl->sessions[session_number].state == S_STATE_IN_CREATION) { +			sl->sessions[session_number].state = S_STATE_IDLE; +		} +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +		sl->error = en50221_tl_get_error(sl->tl); +		return -1; +	} +	// ok. +	return session_number; +} + +int en50221_sl_destroy_session(struct en50221_session_layer *sl, +			       uint16_t session_number) +{ +	if (session_number >= sl->max_sessions) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		return -1; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (!(sl->sessions[session_number].state & (S_STATE_ACTIVE | S_STATE_IN_DELETION))) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return -1; +	} +	// set the state +	sl->sessions[session_number].state = S_STATE_IN_DELETION; + +	// get essential details +	uint8_t slot_id = sl->sessions[session_number].slot_id; +	uint8_t connection_id = sl->sessions[session_number].connection_id; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +	//  sendit +	uint8_t hdr[4]; +	hdr[0] = ST_CLOSE_SESSION_REQ; +	hdr[1] = 2; +	hdr[2] = session_number >> 8; +	hdr[3] = session_number; +	if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 4)) { +		pthread_mutex_lock(&sl->sessions[session_number].session_lock); +		if (sl->sessions[session_number].state == S_STATE_IN_DELETION) { +			sl->sessions[session_number].state = S_STATE_IDLE; +		} +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +		sl->error = en50221_tl_get_error(sl->tl); +		return -1; +	} + +	return 0; +} + +int en50221_sl_send_data(struct en50221_session_layer *sl, +			 uint16_t session_number, +			 uint8_t *data, +			 uint16_t data_length) +{ +	if (session_number >= sl->max_sessions) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		return -1; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (sl->sessions[session_number].state != S_STATE_ACTIVE) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return -1; +	} +	// get essential details +	uint8_t slot_id = sl->sessions[session_number].slot_id; +	uint8_t connection_id = sl->sessions[session_number].connection_id; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +	// sendit +	struct iovec iov[2]; +	uint8_t hdr[4]; +	hdr[0] = ST_SESSION_NUMBER; +	hdr[1] = 2; +	hdr[2] = session_number >> 8; +	hdr[3] = session_number; +	iov[0].iov_base = hdr; +	iov[0].iov_len = 4; +	iov[1].iov_base = data; +	iov[1].iov_len = data_length; +	if (en50221_tl_send_datav(sl->tl, slot_id, connection_id, iov, 2)) { +		sl->error = en50221_tl_get_error(sl->tl); +		return -1; +	} + +	return 0; +} + +int en50221_sl_send_datav(struct en50221_session_layer *sl, +			  uint16_t session_number, +			  struct iovec *vector, +			  int iov_count) +{ +	if (session_number >= sl->max_sessions) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		return -1; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (sl->sessions[session_number].state != S_STATE_ACTIVE) { +		sl->error = EN50221ERR_BADSESSIONNUMBER; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return -1; +	} +	if (iov_count > 9) { +		sl->error = EN50221ERR_IOVLIMIT; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return -1; +	} +	uint8_t slot_id = sl->sessions[session_number].slot_id; +	uint8_t connection_id = sl->sessions[session_number].connection_id; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +	// make up the header +	struct iovec out_iov[10]; +	uint8_t hdr[4]; +	hdr[0] = ST_SESSION_NUMBER; +	hdr[1] = 2; +	hdr[2] = session_number >> 8; +	hdr[3] = session_number; +	out_iov[0].iov_base = hdr; +	out_iov[0].iov_len = 4; + +	// make up the data +	memcpy(&out_iov[1], vector, iov_count * sizeof(struct iovec)); + +	// send this command +	if (en50221_tl_send_datav(sl->tl, slot_id, connection_id, out_iov, iov_count + 1)) { +		sl->error = en50221_tl_get_error(sl->tl); +		return -1; +	} +	return 0; +} + +int en50221_sl_broadcast_data(struct en50221_session_layer *sl, +			      int slot_id, uint32_t resource_id, +			      uint8_t *data, uint16_t data_length) +{ +	uint32_t i; + +	for (i = 0; i < sl->max_sessions; i++) { +		pthread_mutex_lock(&sl->sessions[i].session_lock); + +		if (sl->sessions[i].state != S_STATE_ACTIVE) { +			pthread_mutex_unlock(&sl->sessions[i].session_lock); +			continue; +		} +		if ((slot_id != -1) +		    && (slot_id != sl->sessions[i].slot_id)) { +			pthread_mutex_unlock(&sl->sessions[i].session_lock); +			continue; +		} + +		if (sl->sessions[i].resource_id == resource_id) { +			pthread_mutex_unlock(&sl->sessions[i].session_lock); +			en50221_sl_send_data(sl, i, data, data_length); +		} else { +			pthread_mutex_unlock(&sl->sessions[i].session_lock); +		} +	} + +	return 0; +} + + + +static void en50221_sl_handle_open_session_request(struct en50221_session_layer *sl, +						   uint8_t *data, +						   uint32_t data_length, +						   uint8_t slot_id, +						   uint8_t connection_id) +{ +	// check +	if (data_length < 5) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	if (data[0] != 4) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	// get the resource id +	uint32_t requested_resource_id = +	    (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]; + +	// get lookup callback details +	pthread_mutex_lock(&sl->setcallback_lock); +	en50221_sl_lookup_callback lcb = sl->lookup; +	void *lcb_arg = sl->lookup_arg; +	pthread_mutex_unlock(&sl->setcallback_lock); + +	// first of all, lookup this resource id +	int status = S_STATUS_CLOSE_NO_RES; +	en50221_sl_resource_callback resource_callback = NULL; +	void *resource_arg = NULL; +	uint32_t connected_resource_id; +	if (lcb) { +		status = +		    lcb(lcb_arg, slot_id, requested_resource_id, +			&resource_callback, &resource_arg, +			&connected_resource_id); +		switch (status) { +		case 0: +			status = S_STATUS_OPEN; +			break; + +		case -1: +			status = S_STATUS_CLOSE_NO_RES; +			break; + +		case -2: +			status = S_STATUS_CLOSE_RES_LOW_VERSION; +			break; + +		case -3: +			status = S_STATUS_CLOSE_RES_UNAVAILABLE; +			break; +		} +	} +	// if we found it, get a new session for it +	int session_number = -1; +	if (status == S_STATUS_OPEN) { +		// lookup next free session_id: +		pthread_mutex_lock(&sl->global_lock); +		session_number = +		    en50221_sl_alloc_new_session(sl, connected_resource_id, +						 slot_id, connection_id, +						 resource_callback, +						 resource_arg); +		pthread_mutex_unlock(&sl->global_lock); + +		if (session_number == -1) { +			status = S_STATUS_CLOSE_NO_RES; +		} else { +			// inform upper layers/ check availability +			pthread_mutex_lock(&sl->setcallback_lock); +			en50221_sl_session_callback cb = sl->session; +			void *cb_arg = sl->session_arg; +			pthread_mutex_unlock(&sl->setcallback_lock); +			if (cb) { +				if (cb(cb_arg, S_SCALLBACK_REASON_CAMCONNECTING, +				       slot_id, session_number, +				       connected_resource_id)) { +					status = S_STATUS_CLOSE_RES_BUSY; +				} +			} else { +				status = S_STATUS_CLOSE_RES_UNAVAILABLE; +			} +		} +	} +	// send response +	uint8_t hdr[9]; +	hdr[0] = ST_OPEN_SESSION_RES; +	hdr[1] = 7; +	hdr[2] = status; +	hdr[3] = connected_resource_id >> 24; +	hdr[4] = connected_resource_id >> 16; +	hdr[5] = connected_resource_id >> 8; +	hdr[6] = connected_resource_id; +	hdr[7] = session_number >> 8; +	hdr[8] = session_number; +	if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 9)) { +		print(LOG_LEVEL, ERROR, 1, +		      "Transport layer error %i occurred\n", +		      en50221_tl_get_error(sl->tl)); +		status = S_STATUS_CLOSE_NO_RES; +		// fallthrough +	} +	// inform upper layers what happened +	if (session_number != -1) { +		// setup session state apppropriately from upper layer response +		pthread_mutex_lock(&sl->sessions[session_number].session_lock); +		if (status != S_STATUS_OPEN) { +			sl->sessions[session_number].state = S_STATE_IDLE; +		} else { +			sl->sessions[session_number].state = S_STATE_ACTIVE; +		} +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +		// tell upper layers +		if (sl->sessions[session_number].state == S_STATE_ACTIVE) { +			pthread_mutex_lock(&sl->setcallback_lock); +			en50221_sl_session_callback cb = sl->session; +			void *cb_arg = sl->session_arg; +			pthread_mutex_unlock(&sl->setcallback_lock); + +			if (status == S_STATUS_OPEN) { +				if (cb) +					cb(cb_arg, +					   S_SCALLBACK_REASON_CAMCONNECTED, +					   slot_id, session_number, +					   connected_resource_id); +			} else { +				sl->sessions[session_number].state = +				    S_STATE_IDLE; +				if (cb) +					cb(cb_arg, +					   S_SCALLBACK_REASON_CAMCONNECTFAIL, +					   slot_id, session_number, +					   connected_resource_id); +			} +		} +	} +} + +static void en50221_sl_handle_close_session_request(struct en50221_session_layer *sl, +						    uint8_t * data, +						    uint32_t data_length, +						    uint8_t slot_id, +						    uint8_t connection_id) +{ +	// check +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	if (data[0] != 2) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	// extract session number +	uint16_t session_number = (data[1] << 8) | data[2]; + +	// check session number is ok +	uint8_t code = 0x00; +	uint32_t resource_id = 0; +	if (session_number >= sl->max_sessions) { +		code = 0xF0;	// session close error +		print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", +		      slot_id); +	} else { +		pthread_mutex_lock(&sl->sessions[session_number]. +				   session_lock); +		if (slot_id != sl->sessions[session_number].slot_id) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received unexpected session on invalid slot %i\n", +			      slot_id); +			code = 0xF0;	// session close error +		} +		if (connection_id != sl->sessions[session_number].connection_id) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received unexpected session on invalid slot %i\n", +			      slot_id); +			code = 0xF0;	// session close error +		} +		if (!(sl->sessions[session_number].state & (S_STATE_ACTIVE | S_STATE_IN_DELETION))) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received unexpected session on invalid slot %i\n", +			      slot_id); +			code = 0xF0;	// session close error +		} + +		if (code == 0x00) { +			sl->sessions[session_number].state = S_STATE_IDLE; +			code = 0x00;	// close ok +		} +		resource_id = sl->sessions[session_number].resource_id; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +	} + +	// make up the response +	uint8_t hdr[5]; +	hdr[0] = ST_CLOSE_SESSION_RES; +	hdr[1] = 3; +	hdr[2] = code; +	hdr[3] = session_number >> 8; +	hdr[4] = session_number; + +	// sendit +	if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 5)) { +		print(LOG_LEVEL, ERROR, 1, +		      "Transport layer reports error %i on slot %i\n", +		      en50221_tl_get_error(sl->tl), slot_id); +	} +	// callback to announce destruction to resource if it was ok +	if (code == 0x00) { +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); + +		if (cb) +			cb(cb_arg, S_SCALLBACK_REASON_CLOSE, slot_id, +			   session_number, resource_id); +	} +} + +static void en50221_sl_handle_create_session_response(struct en50221_session_layer *sl, +						      uint8_t * data, +						      uint32_t data_length, +						      uint8_t slot_id, +						      uint8_t connection_id) +{ +	// check +	if (data_length < 8) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	if (data[0] != 7) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	// extract session number +	uint16_t session_number = (data[5] << 8) | data[6]; + +	// check session number is ok +	if (session_number >= sl->max_sessions) { +		print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", +		      slot_id); +		return; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (slot_id != sl->sessions[session_number].slot_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (connection_id != sl->sessions[session_number].connection_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (sl->sessions[session_number].state != S_STATE_IN_CREATION) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	// extract status +	if (data[1] != S_STATUS_OPEN) { +		print(LOG_LEVEL, ERROR, 1, +		      "Session creation failed 0x%02x\n", data[1]); +		sl->sessions[session_number].state = S_STATE_IDLE; +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +		// inform upper layers +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); +		if (cb) +			cb(cb_arg, S_SCALLBACK_REASON_CONNECTFAIL, slot_id, +			   session_number, +			   sl->sessions[session_number].resource_id); +		return; +	} +	// set it active +	sl->sessions[session_number].state = S_STATE_ACTIVE; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +	// inform upper layers +	pthread_mutex_lock(&sl->setcallback_lock); +	en50221_sl_session_callback cb = sl->session; +	void *cb_arg = sl->session_arg; +	pthread_mutex_unlock(&sl->setcallback_lock); +	if (cb) +		cb(cb_arg, S_SCALLBACK_REASON_CONNECTED, slot_id, +		   session_number, +		   sl->sessions[session_number].resource_id); +} + +static void en50221_sl_handle_close_session_response(struct en50221_session_layer *sl, +						     uint8_t *data, +						     uint32_t data_length, +						     uint8_t slot_id, +						     uint8_t connection_id) +{ +	// check +	if (data_length < 5) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	if (data[0] != 4) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %02x\n", +		      slot_id); +		return; +	} +	// extract session number +	uint16_t session_number = (data[2] << 8) | data[3]; + +	// check session number is ok +	if (session_number >= sl->max_sessions) { +		print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id); +		return; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (slot_id != sl->sessions[session_number].slot_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (connection_id != sl->sessions[session_number].connection_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (sl->sessions[session_number].state != S_STATE_IN_DELETION) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	// extract status +	if (data[1] != 0x00) { +		print(LOG_LEVEL, ERROR, 1, "Session close failed 0x%02x\n", data[1]); +		// just fallthrough anyway +	} +	// completed +	sl->sessions[session_number].state = S_STATE_IDLE; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +} + +static void en50221_sl_handle_session_package(struct en50221_session_layer *sl, +					      uint8_t *data, +					      uint32_t data_length, +					      uint8_t slot_id, +					      uint8_t connection_id) +{ +	// check +	if (data_length < 3) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %i\n", +		      slot_id); +		return; +	} +	if (data[0] != 2) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %i\n", +		      slot_id); +		return; +	} +	// get session number +	uint16_t session_number = (data[1] << 8) | data[2]; + +	// check it +	if (session_number >= sl->max_sessions) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with bad session_number from module on slot %i\n", +		      slot_id); +		return; +	} + +	pthread_mutex_lock(&sl->sessions[session_number].session_lock); +	if (slot_id != sl->sessions[session_number].slot_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (connection_id != sl->sessions[session_number].connection_id) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received unexpected session on invalid slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} +	if (sl->sessions[session_number].state != S_STATE_ACTIVE) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with bad session_number from module on slot %i\n", +		      slot_id); +		pthread_mutex_unlock(&sl->sessions[session_number].session_lock); +		return; +	} + +	en50221_sl_resource_callback cb = sl->sessions[session_number].callback; +	void *cb_arg = sl->sessions[session_number].callback_arg; +	uint32_t resource_id = sl->sessions[session_number].resource_id; +	pthread_mutex_unlock(&sl->sessions[session_number].session_lock); + +	// there can be > 1 APDU following the package - all for the same session/resource_id tho. +	data += 3; +	data_length -= 3; +	while (data_length) { +		// check length field +		if (data_length < 3) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received invalid sized session package from slot %i\n", +			      slot_id); +			return; +		} +		// parse the APDU's length field +		int length_field_len; +		uint16_t asn_data_length; +		if ((length_field_len = asn_1_decode(&asn_data_length, data + 3, data_length - 3)) < 0) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received invalid sized session package from slot %i\n", +			      slot_id); +			return; +		} +		uint32_t apdu_length = 3 + length_field_len + asn_data_length; + +		// check there is enough data +		if (apdu_length > data_length) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received invalid sized session package from slot %i\n", +			      slot_id); +			return; +		} +		// pass the APDU up to the higher layers +		if (cb) +			cb(cb_arg, slot_id, session_number, resource_id, data, apdu_length); + +		// next! +		data += apdu_length; +		data_length -= apdu_length; +	} + +} + +static void en50221_sl_transport_callback(void *arg, int reason, +					  uint8_t *data, +					  uint32_t data_length, +					  uint8_t slot_id, +					  uint8_t connection_id) +{ +	struct en50221_session_layer *sl = +	    (struct en50221_session_layer *) arg; +	uint32_t i; + +	// deal with the reason for this callback +	switch (reason) { +	case T_CALLBACK_REASON_DATA: +		// fallthrough into rest of this function +		break; + +	case T_CALLBACK_REASON_CONNECTIONOPEN: +	{ +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); + +		if (cb) +			cb(cb_arg, S_SCALLBACK_REASON_TC_CONNECT, +				slot_id, connection_id, 0); +		return; +	} + +	case T_CALLBACK_REASON_CAMCONNECTIONOPEN: +	{ +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); + +		if (cb) +			cb(cb_arg, +				S_SCALLBACK_REASON_TC_CAMCONNECT, +				slot_id, connection_id, 0); +		return; +	} + +	case T_CALLBACK_REASON_CONNECTIONCLOSE: +	{ +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); + +		for (i = 0; i < sl->max_sessions; i++) { +			pthread_mutex_lock(&sl->sessions[i].session_lock); + +			if (sl->sessions[i].state == S_STATE_IDLE) { +				pthread_mutex_unlock(&sl->sessions[i].session_lock); +				continue; +			} +			if (sl->sessions[i].connection_id != connection_id) { +				pthread_mutex_unlock(&sl->sessions[i].session_lock); +				continue; +			} + +			sl->sessions[i].state = S_STATE_IDLE; + +			uint8_t _slot_id = sl->sessions[i].slot_id; +			uint32_t resource_id = sl->sessions[i].resource_id; +			pthread_mutex_unlock(&sl->sessions[i].session_lock); + +			if (cb) +				cb(cb_arg, S_SCALLBACK_REASON_CLOSE, _slot_id, i, resource_id); +		} +		return; +	} + +	case T_CALLBACK_REASON_SLOTCLOSE: +	{ +		pthread_mutex_lock(&sl->setcallback_lock); +		en50221_sl_session_callback cb = sl->session; +		void *cb_arg = sl->session_arg; +		pthread_mutex_unlock(&sl->setcallback_lock); + +		for (i = 0; i < sl->max_sessions; i++) { +			pthread_mutex_lock(&sl->sessions[i].session_lock); + +			if (sl->sessions[i].state == S_STATE_IDLE) { +				pthread_mutex_unlock(&sl->sessions[i].session_lock); +				continue; +			} +			if (sl->sessions[i].slot_id != slot_id) { +				pthread_mutex_unlock(&sl->sessions[i].session_lock); +				continue; +			} +			sl->sessions[i].state = S_STATE_IDLE; + +			uint32_t resource_id = sl->sessions[i].resource_id; +			pthread_mutex_unlock(&sl->sessions[i].session_lock); + +			if (cb) +				cb(cb_arg, S_SCALLBACK_REASON_CLOSE, slot_id, i, resource_id); + +		} +		return; +	} +	} + +	// sanity check data length +	if (data_length < 1) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received data with invalid length from module on slot %i\n", +		      slot_id); +		return; +	} +	// deal with the data +	uint8_t spdu_tag = data[0]; +	switch (spdu_tag) { +	case ST_OPEN_SESSION_REQ: +		en50221_sl_handle_open_session_request(sl, data + 1, +						       data_length - 1, +						       slot_id, +						       connection_id); +		break; + +	case ST_CLOSE_SESSION_REQ: +		en50221_sl_handle_close_session_request(sl, data + 1, +							data_length - 1, +							slot_id, +							connection_id); +		break; + +	case ST_SESSION_NUMBER: +		en50221_sl_handle_session_package(sl, data + 1, +						  data_length - 1, slot_id, +						  connection_id); +		break; + +	case ST_CREATE_SESSION_RES: +		en50221_sl_handle_create_session_response(sl, data + 1, +							  data_length - 1, +							  slot_id, +							  connection_id); +		break; + +	case ST_CLOSE_SESSION_RES: +		en50221_sl_handle_close_session_response(sl, data + 1, +							 data_length - 1, +							 slot_id, +							 connection_id); +		break; + +	default: +		print(LOG_LEVEL, ERROR, 1, +		      "Received unknown session tag %02x from module on slot %i", +		      spdu_tag, slot_id); +		break; +	} +} + +static int en50221_sl_alloc_new_session(struct en50221_session_layer *sl, +					uint32_t resource_id, +					uint8_t slot_id, +					uint8_t connection_id, +					en50221_sl_resource_callback +					callback, void *arg) +{ +	int session_number = -1; +	uint32_t i; +	for (i = 1; i < sl->max_sessions; i++) { +		if (sl->sessions[i].state == S_STATE_IDLE) { +			session_number = i; +			break; +		} +	} +	if (session_number == -1) { +		sl->error = EN50221ERR_OUTOFSESSIONS; +		return -1; +	} +	// setup the session +	sl->sessions[session_number].state = S_STATE_IN_CREATION; +	sl->sessions[session_number].resource_id = resource_id; +	sl->sessions[session_number].slot_id = slot_id; +	sl->sessions[session_number].connection_id = connection_id; +	sl->sessions[session_number].callback = callback; +	sl->sessions[session_number].callback_arg = arg; + +	// ok +	return session_number; +} diff --git a/lib/libdvben50221/en50221_session.h b/lib/libdvben50221/en50221_session.h new file mode 100644 index 0000000..7b33518 --- /dev/null +++ b/lib/libdvben50221/en50221_session.h @@ -0,0 +1,232 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 session layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian@jusst.de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + + +#ifndef __EN50221_SESSION_H__ +#define __EN50221_SESSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <libdvben50221/en50221_transport.h> + +#define S_SCALLBACK_REASON_CAMCONNECTING  0x00	// CAM originated session connecting to resource (check for availability) +#define S_SCALLBACK_REASON_CAMCONNECTED   0x01	// CAM originated session connection established succesfully +#define S_SCALLBACK_REASON_CAMCONNECTFAIL 0x02	// CAM originated session connection failed +#define S_SCALLBACK_REASON_CONNECTED      0x03	// Host originated session ACKed by CAM. +#define S_SCALLBACK_REASON_CONNECTFAIL    0x04	// Host originated session NACKed by CAM. +#define S_SCALLBACK_REASON_CLOSE          0x05	// Session closed +#define S_SCALLBACK_REASON_TC_CONNECT     0x06	// A host originated transport connection has been established. +#define S_SCALLBACK_REASON_TC_CAMCONNECT  0x07	// A CAM originated transport connection has been established. + + +/** + * Opaque type representing a session layer. + */ +struct en50221_session_layer; + +/** + * Type definition for resource callback function - called by session layer when data + * arrives for a particular resource. + * + * @param arg Private argument. + * @param slot_id Slot id concerned. + * @param session_number Session number. + * @param resource_id Resource id. + * @param data The data. + * @param data_length Length of data in bytes. + * @return 0 on success, or -1 on failure. + */ +typedef int (*en50221_sl_resource_callback) (void *arg, +					     uint8_t slot_id, +					     uint16_t session_number, +					     uint32_t resource_id, +					     uint8_t * data, +					     uint32_t data_length); + +/** + * Type definition for resource lookup callback function - used by the session layer to + * look up requested resources. + * + * @param arg Private argument. + * @param slot_id Slot id the request came from. + * @param requested_resource_id Resource id requested. + * @param callback_out Output parameter for pointer to resource callback function. + * @param arg_out Output parameter for arg to pass to resource callback. + * @param resource_id_out Set this to the resource_id connected to (e.g. may differ from resource_id due to versions). + * @return 0 on success, + * -1 if the resource was not found, + * -2 if it exists, but had a lower version, or + * -3 if it exists, but was unavailable. + */ +typedef int (*en50221_sl_lookup_callback) (void *arg, +					   uint8_t slot_id, +					   uint32_t requested_resource_id, +					   en50221_sl_resource_callback * callback_out, +					   void **arg_out, +					   uint32_t *resource_id_out); + + +/** + * Type definition for session callback function - used to inform top level code when a CAM + * modifies a session to a resource. + * + * @param arg Private argument. + * @param reason One of the S_CCALLBACK_REASON_* values above. + * @param slot_id Slot id concerned. + * @param session_number Session number. + * @param resource_id Resource id. + * @return 0 on sucess, or -1 on error. + */ +typedef int (*en50221_sl_session_callback) (void *arg, int reason, +					    uint8_t slot_id, +					    uint16_t session_number, +					    uint32_t resource_id); + +/** + * Construct a new instance of the session layer. + * + * @param tl The en50221_transport_layer instance to use. + * @param max_sessions Maximum number of sessions supported. + * @return The en50221_session_layer instance, or NULL on error. + */ +extern struct en50221_session_layer *en50221_sl_create(struct en50221_transport_layer *tl, +						       uint32_t max_sessions); + +/** + * Destroy an instance of the session layer. + * + * @param tl The en50221_session_layer instance. + */ +extern void en50221_sl_destroy(struct en50221_session_layer *sl); + +/** + * Gets the last error. + * + * @param tl The en50221_session_layer instance. + * @return One of the EN50221ERR_* values. + */ +extern int en50221_sl_get_error(struct en50221_session_layer *tl); + +/** + * Register the callback for resource lookup. + * + * @param sl The en50221_session_layer instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_sl_register_lookup_callback(struct en50221_session_layer *sl, +						en50221_sl_lookup_callback callback, +						void *arg); + +/** + * Register the callback for informing about session from a cam. + * + * @param sl The en50221_session_layer instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_sl_register_session_callback(struct en50221_session_layer *sl, +						 en50221_sl_session_callback callback, +						 void *arg); + +/** + * Create a new session to a module in a slot. + * + * @param sl The en50221_session_layer instance. + * @param slot The slot to connect to. + * @param resource_id The resource_id to connect to. + * @param callback The callback for received data. + * @param arg Argument to pass to the callback. + * @return The new session_number, or -1 on error. + */ +extern int en50221_sl_create_session(struct en50221_session_layer *sl, int slot_id, +				     uint8_t connection_id, +				     uint32_t resource_id, +				     en50221_sl_resource_callback callback, +				     void *arg); + +/** + * Destroy a session. + * + * @param sl The en50221_session_layer instance. + * @param session_number The session to destroy. + * @return 0 on success, or -1 on error. + */ +extern int en50221_sl_destroy_session(struct en50221_session_layer *sl, +				      uint16_t session_number); + +/** + * this function is used to take a data-block, pack into + * into a SPDU (SESSION_NUMBER) and send it to the transport layer + * + * @param sl The en50221_session_layer instance to use. + * @param session_number Session number concerned. + * @param data Data to send. + * @param data_length Length of data in bytes. + * @return 0 on success, or -1 on error. + */ +extern int en50221_sl_send_data(struct en50221_session_layer *sl, +				uint16_t session_number, +				uint8_t * data, +				uint16_t data_length); + +/** + * this function is used to take a data-block, pack into + * into a SPDU (SESSION_NUMBER) and send it to the transport layer + * + * @param sl The en50221_session_layer instance to use. + * @param session_number Session number concerned. + * @param vector IOVEC to send. + * @param iov_count Number of elements in io vector. + * @return 0 on success, or -1 on error. + */ +extern int en50221_sl_send_datav(struct en50221_session_layer *sl, +				 uint16_t session_number, +				 struct iovec *vector, +				 int iov_count); + +/** + * this is used to send a message to all sessions, linked + * to resource res + * + * @param tl The en50221_session_layer instance to use. + * @param slot_id Set to -1 to send to any slot. Other values will send to only that slot. + * @param resource_id Resource id concerned. + * @param data Data to send. + * @param data_length Length of data in bytes. + * @return 0 on success, or -1 on error. + */ +extern int en50221_sl_broadcast_data(struct en50221_session_layer *sl, +				     int slot_id, +				     uint32_t resource_id, +				     uint8_t * data, +				     uint16_t data_length); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvben50221/en50221_stdcam.c b/lib/libdvben50221/en50221_stdcam.c new file mode 100644 index 0000000..a00a844 --- /dev/null +++ b/lib/libdvben50221/en50221_stdcam.c @@ -0,0 +1,54 @@ +/* +	en50221 encoder An implementation for libdvb +	an implementation for the en50221 transport layer + +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	This program 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <errno.h> +#include <libdvbapi/dvbca.h> +#include "en50221_stdcam.h" + +struct en50221_stdcam *en50221_stdcam_create(int adapter, int slotnum, +					     struct en50221_transport_layer *tl, +					     struct en50221_session_layer *sl) +{ +	struct en50221_stdcam *result = NULL; + +	int cafd = dvbca_open(adapter, 0); +	if (cafd == -1) +		return NULL; + +	int ca_type = dvbca_get_interface_type(cafd, slotnum); +	switch(ca_type) { +	case DVBCA_INTERFACE_LINK: +		result = en50221_stdcam_llci_create(cafd, slotnum, tl, sl); +		break; + +	case DVBCA_INTERFACE_HLCI: +		result = en50221_stdcam_hlci_create(cafd, slotnum); +		break; +	} + +	if (result == NULL) +		close(cafd); +	return result; +} diff --git a/lib/libdvben50221/en50221_stdcam.h b/lib/libdvben50221/en50221_stdcam.h new file mode 100644 index 0000000..154ff76 --- /dev/null +++ b/lib/libdvben50221/en50221_stdcam.h @@ -0,0 +1,102 @@ +/* +	en50221 encoder An implementation for libdvb +	an implementation for the en50221 transport layer + +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	This program 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef EN50221_STDCAM_H +#define EN50221_STDCAM_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libdvben50221/en50221_app_ai.h> +#include <libdvben50221/en50221_app_ca.h> +#include <libdvben50221/en50221_app_mmi.h> +#include <libdvben50221/en50221_session.h> +#include <libdvben50221/en50221_transport.h> + +enum en50221_stdcam_status { +	EN50221_STDCAM_CAM_NONE, +	EN50221_STDCAM_CAM_INRESET, +	EN50221_STDCAM_CAM_OK, +	EN50221_STDCAM_CAM_BAD, +}; + +struct en50221_stdcam { +	/* one of more of the following may be NULL if a CAM does not support it */ +	struct en50221_app_ai *ai_resource; +	struct en50221_app_ca *ca_resource; +	struct en50221_app_mmi *mmi_resource; + +	/* if any of these are -1, no connection is in place to this resource yet */ +	int ai_session_number; +	int ca_session_number; +	int mmi_session_number; + +	/* poll the stdcam instance */ +	enum en50221_stdcam_status (*poll)(struct en50221_stdcam *stdcam); + +	/* inform the stdcam of the current DVB time */ +	void (*dvbtime)(struct en50221_stdcam *stdcam, time_t dvbtime); + +	/* destroy the stdcam instance */ +	void (*destroy)(struct en50221_stdcam *stdcam, int closefd); +}; + +/** + * Create an instance of the STDCAM for an LLCI interface. + * + * @param cafd FD of the CA device. + * @param slotnum Slotnum on that CA device. + * @param tl Transport layer instance to use. + * @param sl Session layer instance to use. + * @return en50221_stdcam instance, or NULL on error. + */ +extern struct en50221_stdcam *en50221_stdcam_llci_create(int cafd, int slotnum, +						  struct en50221_transport_layer *tl, +						  struct en50221_session_layer *sl); + +/** + * Create an instance of the STDCAM for an HLCI interface. + * + * @param cafd FD of the CA device. + * @param slotnum Slotnum on that CA device. + * @return en50221_stdcam instance, or NULL on error. + */ +extern struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum); + +/** + * Convenience method to create a STDCAM interface for a ca device on a particular adapter. + * + * @param adapter The DVB adapter concerned. + * @param slotnum The ca slot number on that adapter. + * @param tl Transport layer instance to use (unused for HLCI cams). + * @param sl Session layer instance to use (unused for HLCI cams). + * @return en50221_stdcam instance, or NULL on error. + */ +extern struct en50221_stdcam *en50221_stdcam_create(int adapter, int slotnum, +						    struct en50221_transport_layer *tl, +						    struct en50221_session_layer *sl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libdvben50221/en50221_stdcam_hlci.c b/lib/libdvben50221/en50221_stdcam_hlci.c new file mode 100644 index 0000000..f21637b --- /dev/null +++ b/lib/libdvben50221/en50221_stdcam_hlci.c @@ -0,0 +1,216 @@ +/* +	en50221 encoder An implementation for libdvb +	an implementation for the en50221 transport layer + +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	This program 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <errno.h> +#include <libdvbapi/dvbca.h> +#include "en50221_app_utils.h" +#include "en50221_app_tags.h" +#include "en50221_stdcam.h" + + +struct en50221_stdcam_hlci { +	struct en50221_stdcam stdcam; + +	int cafd; +	int slotnum; +	int initialised; +	struct en50221_app_send_functions sendfuncs; +}; + +static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd); +static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam); +static int hlci_cam_added(struct en50221_stdcam_hlci *hlci); +static int hlci_send_data(void *arg, uint16_t session_number, +			  uint8_t * data, uint16_t data_length); +static int hlci_send_datav(void *arg, uint16_t session_number, +			   struct iovec *vector, int iov_count); + + + + +struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum) +{ +	// try and allocate space for the HLCI stdcam +	struct en50221_stdcam_hlci *hlci = +		malloc(sizeof(struct en50221_stdcam_hlci)); +	if (hlci == NULL) { +		return NULL; +	} +	memset(hlci, 0, sizeof(struct en50221_stdcam_hlci)); + +	// create the sendfuncs +	hlci->sendfuncs.arg = hlci; +	hlci->sendfuncs.send_data = hlci_send_data; +	hlci->sendfuncs.send_datav = hlci_send_datav; + +	// create the resources (NOTE: we just use fake session numbers here) +	hlci->stdcam.ai_resource = en50221_app_ai_create(&hlci->sendfuncs); +	hlci->stdcam.ai_session_number = 0; +	hlci->stdcam.ca_resource = en50221_app_ca_create(&hlci->sendfuncs); +	hlci->stdcam.ca_session_number = 1; +//      hlci->stdcam.mmi_resource = en50221_app_mmi_create(&hlci->sendfuncs); +	hlci->stdcam.mmi_session_number = -1; + +	// done +	hlci->stdcam.destroy = en50221_stdcam_hlci_destroy; +	hlci->stdcam.poll = en50221_stdcam_hlci_poll; +	hlci->slotnum = slotnum; +	hlci->cafd = cafd; +	return &hlci->stdcam; +} + +static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd) +{ +	struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam; + +	if (hlci->stdcam.ai_resource) +		en50221_app_ai_destroy(hlci->stdcam.ai_resource); +	if (hlci->stdcam.ca_resource) +		en50221_app_ca_destroy(hlci->stdcam.ca_resource); +	if (hlci->stdcam.mmi_resource) +		en50221_app_mmi_destroy(hlci->stdcam.mmi_resource); + +	if (closefd) +		close(hlci->cafd); + +	free(hlci); +} + +static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam) +{ +	struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam; + +	switch(dvbca_get_cam_state(hlci->cafd, hlci->slotnum)) { +	case DVBCA_CAMSTATE_MISSING: +		hlci->initialised = 0; +		break; + +	case DVBCA_CAMSTATE_READY: +	case DVBCA_CAMSTATE_INITIALISING: +		if (!hlci->initialised) +			hlci_cam_added(hlci); +		break; +	} + +	// delay to prevent busy loop +	usleep(10); + +	if (!hlci->initialised) { +		return EN50221_STDCAM_CAM_NONE; +	} +	return EN50221_STDCAM_CAM_OK; +} + + + +static int hlci_cam_added(struct en50221_stdcam_hlci *hlci) +{ +	uint8_t buf[256]; +	int size; + +	// get application information +	if (en50221_app_ai_enquiry(hlci->stdcam.ai_resource, 0)) { +		return -EIO; +	} +	if ((size = dvbca_hlci_read(hlci->cafd, TAG_APP_INFO, buf, sizeof(buf))) < 0) { +		return size; +	} +	if (en50221_app_ai_message(hlci->stdcam.ai_resource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) { +		return -EIO; +	} + +	// we forge a fake CA_INFO here so the main app works - since it will expect a CA_INFO +	// this will be replaced with a proper call (below) when the driver support is there +	buf[0] = TAG_CA_INFO >> 16; +	buf[1] = (uint8_t) (TAG_CA_INFO >> 8); +	buf[2] = (uint8_t) TAG_CA_INFO; +	buf[3] = 0; +	if (en50221_app_ca_message(hlci->stdcam.ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) { +		return -EIO; +	} + +	/* +	// get CA information +	   if (en50221_app_ca_info_enq(ca_resource, 0)) { +	   fprintf(stderr, "Failed to send CA INFO enquiry\n"); +	   cafd = -1; +	   return -1; +	   } +	   if ((size = dvbca_hlci_read(cafd, TAG_CA_INFO, buf, sizeof(buf))) < 0) { +	   fprintf(stderr, "Failed to read CA INFO\n"); +	   cafd = -1; +	   return -1; +	   } +	   if (en50221_app_ca_message(ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, size)) { +	   fprintf(stderr, "Failed to parse CA INFO\n"); +	   cafd = -1; +	   return -1; +	   } +	 */ + +	// done +	hlci->initialised = 1; +	return 0; +} + +static int hlci_send_data(void *arg, uint16_t session_number, +			  uint8_t * data, uint16_t data_length) +{ +	(void) session_number; +	struct en50221_stdcam_hlci *hlci = arg; + +	return dvbca_hlci_write(hlci->cafd, data, data_length); +} + +static int hlci_send_datav(void *arg, uint16_t session_number, +			   struct iovec *vector, int iov_count) +{ +	(void) session_number; +	struct en50221_stdcam_hlci *hlci = arg; + +	// calculate the total length of the data to send +	uint32_t data_size = 0; +	int i; +	for (i = 0; i < iov_count; i++) { +		data_size += vector[i].iov_len; +	} + +	// allocate memory for it +	uint8_t *buf = malloc(data_size); +	if (buf == NULL) { +		return -1; +	} +	// merge the iovecs +	uint32_t pos = 0; +	for (i = 0; i < iov_count; i++) { +		memcpy(buf + pos, vector[i].iov_base, vector[i].iov_len); +		pos += vector[i].iov_len; +	} + +	// sendit and cleanup +	int status = dvbca_hlci_write(hlci->cafd, buf, data_size); +	free(buf); +	return status; +} diff --git a/lib/libdvben50221/en50221_stdcam_llci.c b/lib/libdvben50221/en50221_stdcam_llci.c new file mode 100644 index 0000000..2266bbf --- /dev/null +++ b/lib/libdvben50221/en50221_stdcam_llci.c @@ -0,0 +1,437 @@ +/* +	en50221 encoder An implementation for libdvb +	an implementation for the en50221 transport layer + +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	This program 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <errno.h> +#include <libdvbapi/dvbca.h> +#include <libdvbmisc/dvbmisc.h> +#include "en50221_app_rm.h" +#include "en50221_app_datetime.h" +#include "en50221_app_utils.h" +#include "en50221_app_tags.h" +#include "en50221_stdcam.h" + +#define LLCI_RESPONSE_TIMEOUT_MS 1000 +#define LLCI_POLL_DELAY_MS 100 + +/* resource IDs we support */ +static uint32_t resource_ids[] = +{ 	EN50221_APP_RM_RESOURCEID, +	EN50221_APP_CA_RESOURCEID, +	EN50221_APP_AI_RESOURCEID, +	EN50221_APP_MMI_RESOURCEID, +	EN50221_APP_DATETIME_RESOURCEID, +}; +#define RESOURCE_IDS_COUNT sizeof(resource_ids)/4 + +struct llci_resource { +	struct en50221_app_public_resource_id resid; +	uint32_t binary_resource_id; +	en50221_sl_resource_callback callback; +	void *arg; +}; + +struct en50221_stdcam_llci { +	struct en50221_stdcam stdcam; + +	int cafd; +	int slotnum; +	int state; + +	struct llci_resource resources[RESOURCE_IDS_COUNT]; + +	struct en50221_transport_layer *tl; +	struct en50221_session_layer *sl; +	struct en50221_app_send_functions sendfuncs; +	int tl_slot_id; + +	struct en50221_app_rm *rm_resource; + +	struct en50221_app_datetime *datetime_resource; +	int datetime_session_number; +	uint8_t datetime_response_interval; +	time_t datetime_next_send; +	time_t datetime_dvbtime; +}; + +static enum en50221_stdcam_status en50221_stdcam_llci_poll(struct en50221_stdcam *stdcam); +static void en50221_stdcam_llci_dvbtime(struct en50221_stdcam *stdcam, time_t dvbtime); +static void en50221_stdcam_llci_destroy(struct en50221_stdcam *stdcam, int closefd); +static void llci_cam_added(struct en50221_stdcam_llci *llci); +static void llci_cam_in_reset(struct en50221_stdcam_llci *llci); +static void llci_cam_removed(struct en50221_stdcam_llci *llci); + + +static int llci_lookup_callback(void *arg, uint8_t _slot_id, uint32_t requested_resource_id, +				en50221_sl_resource_callback *callback_out, void **arg_out, +				uint32_t *connected_resource_id); +static int llci_session_callback(void *arg, int reason, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id); +static int llci_rm_enq_callback(void *arg, uint8_t _slot_id, uint16_t session_number); +static int llci_rm_reply_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id_count, uint32_t *_resource_ids); +static int llci_rm_changed_callback(void *arg, uint8_t _slot_id, uint16_t session_number); + +static int llci_datetime_enquiry_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint8_t response_interval); + + +struct en50221_stdcam *en50221_stdcam_llci_create(int cafd, int slotnum, +						  struct en50221_transport_layer *tl, +						  struct en50221_session_layer *sl) +{ +	// try and allocate space for the LLCI stdcam +	struct en50221_stdcam_llci *llci = +		malloc(sizeof(struct en50221_stdcam_llci)); +	if (llci == NULL) { +		return NULL; +	} +	memset(llci, 0, sizeof(struct en50221_stdcam_llci)); + +	// create the sendfuncs +	llci->sendfuncs.arg  = sl; +	llci->sendfuncs.send_data  = (en50221_send_data) en50221_sl_send_data; +	llci->sendfuncs.send_datav = (en50221_send_datav) en50221_sl_send_datav; + +	// create the resource manager resource +	int resource_idx = 0; +	llci->rm_resource = en50221_app_rm_create(&llci->sendfuncs); +	en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_RM_RESOURCEID); +	llci->resources[resource_idx].binary_resource_id = EN50221_APP_RM_RESOURCEID; +	llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_rm_message; +	llci->resources[resource_idx].arg = llci->rm_resource; +	en50221_app_rm_register_enq_callback(llci->rm_resource, llci_rm_enq_callback, llci); +	en50221_app_rm_register_reply_callback(llci->rm_resource, llci_rm_reply_callback, llci); +	en50221_app_rm_register_changed_callback(llci->rm_resource, llci_rm_changed_callback, llci); +	resource_idx++; + +	// create the datetime resource +	llci->datetime_resource = en50221_app_datetime_create(&llci->sendfuncs); +	en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_DATETIME_RESOURCEID); +	llci->resources[resource_idx].binary_resource_id = EN50221_APP_DATETIME_RESOURCEID; +	llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_datetime_message; +	llci->resources[resource_idx].arg = llci->datetime_resource; +	en50221_app_datetime_register_enquiry_callback(llci->datetime_resource, llci_datetime_enquiry_callback, llci); +	resource_idx++; +	llci->datetime_session_number = -1; +	llci->datetime_response_interval = 0; +	llci->datetime_next_send = 0; +	llci->datetime_dvbtime = 0; + +	// create the application information resource +	llci->stdcam.ai_resource = en50221_app_ai_create(&llci->sendfuncs); +	en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_AI_RESOURCEID); +	llci->resources[resource_idx].binary_resource_id = EN50221_APP_AI_RESOURCEID; +	llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_ai_message; +	llci->resources[resource_idx].arg = llci->stdcam.ai_resource; +	llci->stdcam.ai_session_number = -1; +	resource_idx++; + +	// create the CA resource +	llci->stdcam.ca_resource = en50221_app_ca_create(&llci->sendfuncs); +	en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_CA_RESOURCEID); +	llci->resources[resource_idx].binary_resource_id = EN50221_APP_CA_RESOURCEID; +	llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_ca_message; +	llci->resources[resource_idx].arg = llci->stdcam.ca_resource; +	llci->stdcam.ca_session_number = -1; +	resource_idx++; + +	// create the MMI resource +	llci->stdcam.mmi_resource = en50221_app_mmi_create(&llci->sendfuncs); +	en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_MMI_RESOURCEID); +	llci->resources[resource_idx].binary_resource_id = EN50221_APP_MMI_RESOURCEID; +	llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_mmi_message; +	llci->resources[resource_idx].arg = llci->stdcam.mmi_resource; +	llci->stdcam.mmi_session_number = -1; +	resource_idx++; + +	// register session layer callbacks +	en50221_sl_register_lookup_callback(sl, llci_lookup_callback, llci); +	en50221_sl_register_session_callback(sl, llci_session_callback, llci); + +	// done +	llci->stdcam.destroy = en50221_stdcam_llci_destroy; +	llci->stdcam.poll = en50221_stdcam_llci_poll; +	llci->stdcam.dvbtime = en50221_stdcam_llci_dvbtime; +	llci->cafd = cafd; +	llci->slotnum = slotnum; +	llci->tl = tl; +	llci->sl = sl; +	llci->tl_slot_id = -1; +	llci->state = EN50221_STDCAM_CAM_NONE; +	return &llci->stdcam; +} + +static void en50221_stdcam_llci_dvbtime(struct en50221_stdcam *stdcam, time_t dvbtime) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; + +	llci->datetime_dvbtime = dvbtime; +} + +static void en50221_stdcam_llci_destroy(struct en50221_stdcam *stdcam, int closefd) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; + +	// "remove" the cam +	llci_cam_removed(llci); + +	// destroy resources +	if (llci->rm_resource) +		en50221_app_rm_destroy(llci->rm_resource); +	if (llci->datetime_resource) +		en50221_app_datetime_destroy(llci->datetime_resource); +	if (llci->stdcam.ai_resource) +		en50221_app_ai_destroy(llci->stdcam.ai_resource); +	if (llci->stdcam.ca_resource) +		en50221_app_ca_destroy(llci->stdcam.ca_resource); +	if (llci->stdcam.mmi_resource) +		en50221_app_mmi_destroy(llci->stdcam.mmi_resource); + +	if (closefd) +		close(llci->cafd); + +	free(llci); +} + + + + +static enum en50221_stdcam_status en50221_stdcam_llci_poll(struct en50221_stdcam *stdcam) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam; + +	switch(dvbca_get_cam_state(llci->cafd, llci->slotnum)) { +	case DVBCA_CAMSTATE_MISSING: +		if (llci->state != EN50221_STDCAM_CAM_NONE) +			llci_cam_removed(llci); +		break; + +	case DVBCA_CAMSTATE_READY: +		if (llci->state == EN50221_STDCAM_CAM_NONE) +			llci_cam_added(llci); +		else if (llci->state == EN50221_STDCAM_CAM_INRESET) +			llci_cam_in_reset(llci); +		break; +	} + +	// poll the stack +	int error; +	if ((error = en50221_tl_poll(llci->tl)) != 0) { +		print(LOG_LEVEL, ERROR, 1, "Error reported by stack:%i\n", en50221_tl_get_error(llci->tl)); +	} + +	// send date/time response +	if (llci->datetime_session_number != -1) { +		time_t cur_time = time(NULL); +		if (llci->datetime_response_interval && (cur_time > llci->datetime_next_send)) { +			en50221_app_datetime_send(llci->datetime_resource, +						llci->datetime_session_number, +						llci->datetime_dvbtime, 0); +			llci->datetime_next_send = cur_time + llci->datetime_response_interval; +		} +	} + +	return llci->state; +} + +static void llci_cam_added(struct en50221_stdcam_llci *llci) +{ +	// clear down any old structures +	if (llci->tl_slot_id != -1) { +		llci_cam_removed(llci); +	} + +	// reset the CAM +	dvbca_reset(llci->cafd, llci->slotnum); +	llci->state = EN50221_STDCAM_CAM_INRESET; +} + +static void llci_cam_in_reset(struct en50221_stdcam_llci *llci) +{ +	if (dvbca_get_cam_state(llci->cafd, llci->slotnum) != DVBCA_CAMSTATE_READY) { +		return; +	} + +	// register the slot +	if ((llci->tl_slot_id = en50221_tl_register_slot(llci->tl, llci->cafd, llci->slotnum, +	      						 LLCI_RESPONSE_TIMEOUT_MS, LLCI_POLL_DELAY_MS)) < 0) { +		llci->state = EN50221_STDCAM_CAM_BAD; +		return; +	} + +	// create a new connection on the slot +	if (en50221_tl_new_tc(llci->tl, llci->tl_slot_id) < 0) { +		llci->state = EN50221_STDCAM_CAM_BAD; +		llci->tl_slot_id = -1; +		en50221_tl_destroy_slot(llci->tl, llci->tl_slot_id); +		return; +	} + +	llci->state = EN50221_STDCAM_CAM_OK; +} + +static void llci_cam_removed(struct en50221_stdcam_llci *llci) +{ +	if (llci->tl_slot_id != -1) { +		en50221_tl_destroy_slot(llci->tl, llci->tl_slot_id); +		llci->tl_slot_id = -1; +		llci->datetime_session_number = -1; +		llci->stdcam.ai_session_number = -1; +		llci->stdcam.ca_session_number = -1; +		llci->stdcam.mmi_session_number = -1; +	} +	llci->state = EN50221_STDCAM_CAM_NONE; +} + + + +static int llci_lookup_callback(void *arg, uint8_t _slot_id, uint32_t requested_resource_id, +				en50221_sl_resource_callback *callback_out, void **arg_out, +				uint32_t *connected_resource_id) +{ +	struct en50221_app_public_resource_id resid; +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; + +	// decode the resource id +	if (!en50221_app_decode_public_resource_id(&resid, requested_resource_id)) { +		return -1; +	} + +	// try and find an instance of the resource +	uint32_t i; +	for(i=0; i<RESOURCE_IDS_COUNT; i++) { +		if ((resid.resource_class == llci->resources[i].resid.resource_class) && +		    (resid.resource_type == llci->resources[i].resid.resource_type)) { + +			// limit sessions to certain resources +			switch(requested_resource_id) { +			case EN50221_APP_DATETIME_RESOURCEID: +				if (llci->datetime_session_number != -1) +					return -3; +				break; +			case EN50221_APP_AI_RESOURCEID: +				if (llci->stdcam.ai_session_number != -1) +					return -3; +				break; +			case EN50221_APP_CA_RESOURCEID: +				if (llci->stdcam.ca_session_number != -1) +					return -3; +				break; +			case EN50221_APP_MMI_RESOURCEID: +				if (llci->stdcam.mmi_session_number != -1) +					return -3; +				break; +			} + +			// resource is ok. +			*callback_out = llci->resources[i].callback; +			*arg_out = llci->resources[i].arg; +			*connected_resource_id = llci->resources[i].binary_resource_id; +			return 0; +		} +	} + +	return -1; +} + +static int llci_session_callback(void *arg, int reason, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; + +	switch(reason) { +	case S_SCALLBACK_REASON_CAMCONNECTED: +		if (resource_id == EN50221_APP_RM_RESOURCEID) { +			en50221_app_rm_enq(llci->rm_resource, session_number); +		} else if (resource_id == EN50221_APP_DATETIME_RESOURCEID) { +			llci->datetime_session_number = session_number; +		} else if (resource_id == EN50221_APP_AI_RESOURCEID) { +			en50221_app_ai_enquiry(llci->stdcam.ai_resource, session_number); +			llci->stdcam.ai_session_number = session_number; +		} else if (resource_id == EN50221_APP_CA_RESOURCEID) { +			en50221_app_ca_info_enq(llci->stdcam.ca_resource, session_number); +			llci->stdcam.ca_session_number = session_number; +		} else if (resource_id == EN50221_APP_MMI_RESOURCEID) { +			llci->stdcam.mmi_session_number = session_number; +		} + +		break; +    case S_SCALLBACK_REASON_CLOSE: +        if (resource_id == EN50221_APP_MMI_RESOURCEID) { +            llci->stdcam.mmi_session_number = -1; +        } + +        break; +	} +	return 0; +} + +static int llci_rm_enq_callback(void *arg, uint8_t _slot_id, uint16_t session_number) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; + +	if (en50221_app_rm_reply(llci->rm_resource, session_number, RESOURCE_IDS_COUNT, resource_ids)) { +		print(LOG_LEVEL, ERROR, 1, "Failed to send RM ENQ on slot %02x\n", _slot_id); +	} +	return 0; +} + +static int llci_rm_reply_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id_count, uint32_t *_resource_ids) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; +	(void) resource_id_count; +	(void) _resource_ids; + +	if (en50221_app_rm_changed(llci->rm_resource, session_number)) { +		print(LOG_LEVEL, ERROR, 1, "Failed to send RM REPLY on slot %02x\n", _slot_id); +	} +	return 0; +} + +static int llci_rm_changed_callback(void *arg, uint8_t _slot_id, uint16_t session_number) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; + +	if (en50221_app_rm_enq(llci->rm_resource, session_number)) { +		print(LOG_LEVEL, ERROR, 1, "Failed to send RM CHANGED on slot %02x\n", _slot_id); +	} +	return 0; +} + +static int llci_datetime_enquiry_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint8_t response_interval) +{ +	struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg; +	(void) _slot_id; + +	llci->datetime_response_interval = response_interval; +	llci->datetime_next_send = 0; +	if (response_interval) { +		llci->datetime_next_send = time(NULL) + response_interval; +	} +	en50221_app_datetime_send(llci->datetime_resource, session_number, llci->datetime_dvbtime, 0); + +	return 0; +} diff --git a/lib/libdvben50221/en50221_transport.c b/lib/libdvben50221/en50221_transport.c new file mode 100644 index 0000000..f6f46db --- /dev/null +++ b/lib/libdvben50221/en50221_transport.c @@ -0,0 +1,1296 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 transport layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#include <time.h> +#include <libdvbmisc/dvbmisc.h> +#include <libdvbapi/dvbca.h> +#include "en50221_errno.h" +#include "en50221_transport.h" +#include "asn_1.h" + +// these are the Transport Tags, like +// described in EN50221, Annex A.4.1.13 (pg70) +#define T_SB                0x80	// sb                           primitive   h<--m +#define T_RCV               0x81	// receive                      primitive   h-->m +#define T_CREATE_T_C        0x82	// create transport connection  primitive   h-->m +#define T_C_T_C_REPLY       0x83	// ctc reply                    primitive   h<--m +#define T_DELETE_T_C        0x84	// delete tc                    primitive   h<->m +#define T_D_T_C_REPLY       0x85	// dtc reply                    primitive   h<->m +#define T_REQUEST_T_C       0x86	// request transport connection primitive   h<--m +#define T_NEW_T_C           0x87	// new tc / reply to t_request  primitive   h-->m +#define T_T_C_ERROR         0x77	// error creating tc            primitive   h-->m +#define T_DATA_LAST         0xA0	// convey data from higher      constructed h<->m +				 // layers +#define T_DATA_MORE         0xA1	// convey data from higher      constructed h<->m +				 // layers + +struct en50221_message { +	struct en50221_message *next; +	uint32_t length; +	uint8_t data[0]; +}; + +struct en50221_connection { +	uint32_t state;		// the current state: idle/in_delete/in_create/active +	struct timeval tx_time;	// time last request was sent from host->module, or 0 if ok +	struct timeval last_poll_time;	// time of last poll transmission +	uint8_t *chain_buffer;	// used to save parts of chained packets +	uint32_t buffer_length; + +	struct en50221_message *send_queue; +	struct en50221_message *send_queue_tail; +}; + +struct en50221_slot { +	int ca_hndl; +	uint8_t slot;		// CAM slot +	struct en50221_connection *connections; + +	pthread_mutex_t slot_lock; + +	uint32_t response_timeout; +	uint32_t poll_delay; +}; + +struct en50221_transport_layer { +	uint8_t max_slots; +	uint8_t max_connections_per_slot; +	struct en50221_slot *slots; +	struct pollfd *slot_pollfds; +	int slots_changed; + +	pthread_mutex_t global_lock; +	pthread_mutex_t setcallback_lock; + +	int error; +	int error_slot; + +	en50221_tl_callback callback; +	void *callback_arg; +}; + +static int en50221_tl_process_data(struct en50221_transport_layer *tl, +				   uint8_t slot_id, uint8_t * data, +				   uint32_t data_length); +static int en50221_tl_poll_tc(struct en50221_transport_layer *tl, +			      uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl, +				   uint8_t slot_id); +static void queue_message(struct en50221_transport_layer *tl, +			  uint8_t slot_id, uint8_t connection_id, +			  struct en50221_message *msg); +static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer +					     *tl, uint8_t slot_id, +					     uint8_t connection_id); +static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id); +static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer +					     *tl, uint8_t slot_id, +					     uint8_t connection_id); +static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl, +					uint8_t slot_id, +					uint8_t connection_id); +static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id, +				       uint8_t * data, +				       uint32_t data_length); +static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id, +				       uint8_t * data, +				       uint32_t data_length); +static int en50221_tl_handle_sb(struct en50221_transport_layer *tl, +				uint8_t slot_id, uint8_t connection_id, +				uint8_t * data, uint32_t data_length); + + +struct en50221_transport_layer *en50221_tl_create(uint8_t max_slots, +						  uint8_t +						  max_connections_per_slot) +{ +	struct en50221_transport_layer *tl = NULL; +	int i; +	int j; + +	// setup structure +	tl = (struct en50221_transport_layer *) +		malloc(sizeof(struct en50221_transport_layer)); +	if (tl == NULL) +		goto error_exit; +	tl->max_slots = max_slots; +	tl->max_connections_per_slot = max_connections_per_slot; +	tl->slots = NULL; +	tl->slot_pollfds = NULL; +	tl->slots_changed = 1; +	tl->callback = NULL; +	tl->callback_arg = NULL; +	tl->error_slot = 0; +	tl->error = 0; +	pthread_mutex_init(&tl->global_lock, NULL); +	pthread_mutex_init(&tl->setcallback_lock, NULL); + +	// create the slots +	tl->slots = malloc(sizeof(struct en50221_slot) * max_slots); +	if (tl->slots == NULL) +		goto error_exit; + +	// set them up +	for (i = 0; i < max_slots; i++) { +		tl->slots[i].ca_hndl = -1; + +		// create the connections for this slot +		tl->slots[i].connections = +		    malloc(sizeof(struct en50221_connection) * max_connections_per_slot); +		if (tl->slots[i].connections == NULL) +			goto error_exit; + +		// create a mutex for the slot +		pthread_mutex_init(&tl->slots[i].slot_lock, NULL); + +		// set them up +		for (j = 0; j < max_connections_per_slot; j++) { +			tl->slots[i].connections[j].state = T_STATE_IDLE; +			tl->slots[i].connections[j].tx_time.tv_sec = 0; +			tl->slots[i].connections[j].last_poll_time.tv_sec = 0; +			tl->slots[i].connections[j].last_poll_time.tv_usec = 0; +			tl->slots[i].connections[j].chain_buffer = NULL; +			tl->slots[i].connections[j].buffer_length = 0; +			tl->slots[i].connections[j].send_queue = NULL; +			tl->slots[i].connections[j].send_queue_tail = NULL; +		} +	} + +	// create the pollfds +	tl->slot_pollfds = malloc(sizeof(struct pollfd) * max_slots); +	if (tl->slot_pollfds == NULL) { +		goto error_exit; +	} +	memset(tl->slot_pollfds, 0, sizeof(struct pollfd) * max_slots); + +	return tl; + +      error_exit: +	en50221_tl_destroy(tl); +	return NULL; +} + +// Destroy an instance of the transport layer +void en50221_tl_destroy(struct en50221_transport_layer *tl) +{ +	int i, j; + +	if (tl) { +		if (tl->slots) { +			for (i = 0; i < tl->max_slots; i++) { +				if (tl->slots[i].connections) { +					for (j = 0; j < tl->max_connections_per_slot; j++) { +						if (tl->slots[i].connections[j].chain_buffer) { +							free(tl->slots[i].connections[j].chain_buffer); +						} + +						struct en50221_message *cur_msg = +							tl->slots[i].connections[j].send_queue; +						while (cur_msg) { +							struct en50221_message *next_msg = cur_msg->next; +							free(cur_msg); +							cur_msg = next_msg; +						} +						tl->slots[i].connections[j].send_queue = NULL; +						tl->slots[i].connections[j].send_queue_tail = NULL; +					} +					free(tl->slots[i].connections); +					pthread_mutex_destroy(&tl->slots[i].slot_lock); +				} +			} +			free(tl->slots); +		} +		if (tl->slot_pollfds) { +			free(tl->slot_pollfds); +		} +		pthread_mutex_destroy(&tl->setcallback_lock); +		pthread_mutex_destroy(&tl->global_lock); +		free(tl); +	} +} + +// this can be called from the user-space app to +// register new slots that we should work with +int en50221_tl_register_slot(struct en50221_transport_layer *tl, +			     int ca_hndl, uint8_t slot, +			     uint32_t response_timeout, +			     uint32_t poll_delay) +{ +	// lock +	pthread_mutex_lock(&tl->global_lock); + +	// we browse through the array of slots +	// to look for the first unused one +	int i; +	int16_t slot_id = -1; +	for (i = 0; i < tl->max_slots; i++) { +		if (tl->slots[i].ca_hndl == -1) { +			slot_id = i; +			break; +		} +	} +	if (slot_id == -1) { +		tl->error = EN50221ERR_OUTOFSLOTS; +		pthread_mutex_unlock(&tl->global_lock); +		return -1; +	} +	// set up the slot struct +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	tl->slots[slot_id].ca_hndl = ca_hndl; +	tl->slots[slot_id].slot = slot; +	tl->slots[slot_id].response_timeout = response_timeout; +	tl->slots[slot_id].poll_delay = poll_delay; +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); + +	tl->slots_changed = 1; +	pthread_mutex_unlock(&tl->global_lock); +	return slot_id; +} + +void en50221_tl_destroy_slot(struct en50221_transport_layer *tl, +			     uint8_t slot_id) +{ +	int i; + +	if (slot_id >= tl->max_slots) +		return; + +	// lock +	pthread_mutex_lock(&tl->global_lock); + +	// clear the slot +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	tl->slots[slot_id].ca_hndl = -1; +	for (i = 0; i < tl->max_connections_per_slot; i++) { +		tl->slots[slot_id].connections[i].state = T_STATE_IDLE; +		tl->slots[slot_id].connections[i].tx_time.tv_sec = 0; +		tl->slots[slot_id].connections[i].last_poll_time.tv_sec = 0; +		tl->slots[slot_id].connections[i].last_poll_time.tv_usec = 0; +		if (tl->slots[slot_id].connections[i].chain_buffer) { +			free(tl->slots[slot_id].connections[i]. +			     chain_buffer); +		} +		tl->slots[slot_id].connections[i].chain_buffer = NULL; +		tl->slots[slot_id].connections[i].buffer_length = 0; + +		struct en50221_message *cur_msg = +		    tl->slots[slot_id].connections[i].send_queue; +		while (cur_msg) { +			struct en50221_message *next_msg = cur_msg->next; +			free(cur_msg); +			cur_msg = next_msg; +		} +		tl->slots[slot_id].connections[i].send_queue = NULL; +		tl->slots[slot_id].connections[i].send_queue_tail = NULL; +	} +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); + +	// tell upper layers +	pthread_mutex_lock(&tl->setcallback_lock); +	en50221_tl_callback cb = tl->callback; +	void *cb_arg = tl->callback_arg; +	pthread_mutex_unlock(&tl->setcallback_lock); +	if (cb) +		cb(cb_arg, T_CALLBACK_REASON_SLOTCLOSE, NULL, 0, slot_id, 0); + +	tl->slots_changed = 1; +	pthread_mutex_unlock(&tl->global_lock); +} + +int en50221_tl_poll(struct en50221_transport_layer *tl) +{ +	uint8_t data[4096]; +	int slot_id; +	int j; + +	// make up pollfds if the slots have changed +	pthread_mutex_lock(&tl->global_lock); +	if (tl->slots_changed) { +		for (slot_id = 0; slot_id < tl->max_slots; slot_id++) { +			if (tl->slots[slot_id].ca_hndl != -1) { +				tl->slot_pollfds[slot_id].fd = tl->slots[slot_id].ca_hndl; +				tl->slot_pollfds[slot_id].events = POLLIN | POLLPRI | POLLERR; +				tl->slot_pollfds[slot_id].revents = 0; +			} else { +				tl->slot_pollfds[slot_id].fd = 0; +				tl->slot_pollfds[slot_id].events = 0; +				tl->slot_pollfds[slot_id].revents = 0; +			} +		} +		tl->slots_changed = 0; +	} +	pthread_mutex_unlock(&tl->global_lock); + +	// anything happened? +	if (poll(tl->slot_pollfds, tl->max_slots, 10) < 0) { +		tl->error_slot = -1; +		tl->error = EN50221ERR_CAREAD; +		return -1; +	} +	// go through all slots (even though poll may not have reported any events +	for (slot_id = 0; slot_id < tl->max_slots; slot_id++) { + +		// check if this slot is still used and get its handle +		pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +		if (tl->slots[slot_id].ca_hndl == -1) { +			pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +			continue; +		} +		int ca_hndl = tl->slots[slot_id].ca_hndl; + +		if (tl->slot_pollfds[slot_id].revents & (POLLPRI | POLLIN)) { +			// read data +			uint8_t r_slot_id; +			uint8_t connection_id; +			int readcnt = dvbca_link_read(ca_hndl, &r_slot_id, +						      &connection_id, +						      data, sizeof(data)); +			if (readcnt < 0) { +				tl->error_slot = slot_id; +				tl->error = EN50221ERR_CAREAD; +				pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +				return -1; +			} +			// process it if we got some +			if (readcnt > 0) { +				if (tl->slots[slot_id].slot != r_slot_id) { +					// this message is for an other CAM of the same CA +					int new_slot_id; +					for (new_slot_id = 0; new_slot_id < tl->max_slots; new_slot_id++) { +						if ((tl->slots[new_slot_id].ca_hndl == ca_hndl) && +						    (tl->slots[new_slot_id].slot == r_slot_id)) +							break; +					} +					if (new_slot_id != tl->max_slots) { +						// we found the requested CAM +						pthread_mutex_lock(&tl->slots[new_slot_id].slot_lock); +						if (en50221_tl_process_data(tl, new_slot_id, data, readcnt)) { +							pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock); +							pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +							return -1; +						} +						pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock); +					} else { +						tl->error = EN50221ERR_BADSLOTID; +						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +						return -1; +					} +				} else +				    if (en50221_tl_process_data(tl, slot_id, data, readcnt)) { +					pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +					return -1; +				} +			} +		} else if (tl->slot_pollfds[slot_id].revents & POLLERR) { +			// an error was reported +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAREAD; +			pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +			return -1; +		} +		// poll the connections on this slot + check for timeouts +		for (j = 0; j < tl->max_connections_per_slot; j++) { +			// ignore connection if idle +			if (tl->slots[slot_id].connections[j].state == T_STATE_IDLE) { +				continue; +			} +			// send queued data +			if (tl->slots[slot_id].connections[j].state & +				(T_STATE_IN_CREATION | T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) { +				// send data if there is some to go and we're not waiting for a response already +				if (tl->slots[slot_id].connections[j].send_queue && +				    (tl->slots[slot_id].connections[j].tx_time.tv_sec == 0)) { + +					// get the message +					struct en50221_message *msg = +						tl->slots[slot_id].connections[j].send_queue; +					if (msg->next != NULL) { +						tl->slots[slot_id].connections[j].send_queue = msg->next; +					} else { +						tl->slots[slot_id].connections[j].send_queue = NULL; +						tl->slots[slot_id].connections[j].send_queue_tail = NULL; +					} + +					// send the message +					if (dvbca_link_write(tl->slots[slot_id].ca_hndl, +					    		     tl->slots[slot_id].slot, +							     j, +							     msg->data, msg->length) < 0) { +						free(msg); +						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +						tl->error_slot = slot_id; +						tl->error = EN50221ERR_CAWRITE; +						print(LOG_LEVEL, ERROR, 1, "CAWrite failed"); +						return -1; +					} +					gettimeofday(&tl->slots[slot_id].connections[j].tx_time, 0); + +					// fixup connection state for T_DELETE_T_C +					if (msg->length && (msg->data[0] == T_DELETE_T_C)) { +						tl->slots[slot_id].connections[j].state = T_STATE_IN_DELETION; +						if (tl->slots[slot_id].connections[j].chain_buffer) { +							free(tl->slots[slot_id].connections[j].chain_buffer); +						} +						tl->slots[slot_id].connections[j].chain_buffer = NULL; +						tl->slots[slot_id].connections[j].buffer_length = 0; +					} + +					free(msg); +				} +			} +			// poll it if we're not expecting a reponse and the poll time has elapsed +			if (tl->slots[slot_id].connections[j].state & T_STATE_ACTIVE) { +				if ((tl->slots[slot_id].connections[j].tx_time.tv_sec == 0) && +				    (time_after(tl->slots[slot_id].connections[j].last_poll_time, +				     		tl->slots[slot_id].poll_delay))) { + +					gettimeofday(&tl->slots[slot_id].connections[j].last_poll_time, 0); +					if (en50221_tl_poll_tc(tl, slot_id, j)) { +						pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +						return -1; +					} +				} +			} + +			// check for timeouts - in any state +			if (tl->slots[slot_id].connections[j].tx_time.tv_sec && +			    (time_after(tl->slots[slot_id].connections[j].tx_time, +			     		tl->slots[slot_id].response_timeout))) { + +				if (tl->slots[slot_id].connections[j].state & +				    (T_STATE_IN_CREATION |T_STATE_IN_DELETION)) { +					tl->slots[slot_id].connections[j].state = T_STATE_IDLE; +				} else if (tl->slots[slot_id].connections[j].state & +					   (T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) { +					tl->error_slot = slot_id; +					tl->error = EN50221ERR_TIMEOUT; +					pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +					return -1; +				} +			} +		} +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +	} + +	return 0; +} + +void en50221_tl_register_callback(struct en50221_transport_layer *tl, +				  en50221_tl_callback callback, void *arg) +{ +	pthread_mutex_lock(&tl->setcallback_lock); +	tl->callback = callback; +	tl->callback_arg = arg; +	pthread_mutex_unlock(&tl->setcallback_lock); +} + +int en50221_tl_get_error_slot(struct en50221_transport_layer *tl) +{ +	return tl->error_slot; +} + +int en50221_tl_get_error(struct en50221_transport_layer *tl) +{ +	return tl->error; +} + +int en50221_tl_send_data(struct en50221_transport_layer *tl, +			 uint8_t slot_id, uint8_t connection_id, +			 uint8_t * data, uint32_t data_size) +{ +#ifdef DEBUG_TXDATA +	printf("[[[[[[[[[[[[[[[[[[[[\n"); +	uint32_t ii = 0; +	for (ii = 0; ii < data_size; ii++) { +		printf("%02x: %02x\n", ii, data[ii]); +	} +	printf("]]]]]]]]]]]]]]]]]]]]\n"); +#endif + +	if (slot_id >= tl->max_slots) { +		tl->error = EN50221ERR_BADSLOTID; +		return -1; +	} + +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	if (tl->slots[slot_id].ca_hndl == -1) { +		tl->error = EN50221ERR_BADSLOTID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (connection_id >= tl->max_connections_per_slot) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// allocate msg structure +	struct en50221_message *msg = +	    malloc(sizeof(struct en50221_message) + data_size + 10); +	if (msg == NULL) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFMEMORY; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// make up data to send +	int length_field_len; +	msg->data[0] = T_DATA_LAST; +	if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) { +		free(msg); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_ASNENCODE; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	msg->data[1 + length_field_len] = connection_id; +	memcpy(msg->data + 1 + length_field_len + 1, data, data_size); +	msg->length = 1 + length_field_len + 1 + data_size; + +	// queue it for transmission +	queue_message(tl, slot_id, connection_id, msg); + +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +	return 0; +} + +int en50221_tl_send_datav(struct en50221_transport_layer *tl, +			  uint8_t slot_id, uint8_t connection_id, +			  struct iovec *vector, int iov_count) +{ +#ifdef DEBUG_TXDATA +	printf("[[[[[[[[[[[[[[[[[[[[\n"); +	uint32_t ii = 0; +	uint32_t iipos = 0; +	for (ii = 0; ii < (uint32_t) iov_count; ii++) { +		uint32_t jj; +		for (jj = 0; jj < vector[ii].iov_len; jj++) { +			printf("%02x: %02x\n", jj + iipos, +			       *((uint8_t *) (vector[ii].iov_base) + jj)); +		} +		iipos += vector[ii].iov_len; +	} +	printf("]]]]]]]]]]]]]]]]]]]]\n"); +#endif + +	if (slot_id >= tl->max_slots) { +		tl->error = EN50221ERR_BADSLOTID; +		return -1; +	} + +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	if (tl->slots[slot_id].ca_hndl == -1) { +		tl->error = EN50221ERR_BADSLOTID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (connection_id >= tl->max_connections_per_slot) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// calculate the total length of the data to send +	uint32_t data_size = 0; +	int i; +	for (i = 0; i < iov_count; i++) { +		data_size += vector[i].iov_len; +	} + +	// allocate msg structure +	struct en50221_message *msg = +	    malloc(sizeof(struct en50221_message) + data_size + 10); +	if (msg == NULL) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFMEMORY; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// make up data to send +	int length_field_len; +	msg->data[0] = T_DATA_LAST; +	if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) { +		free(msg); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_ASNENCODE; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	msg->data[1 + length_field_len] = connection_id; +	msg->length = 1 + length_field_len + 1 + data_size; +	msg->next = NULL; + +	// merge the iovecs +	uint32_t pos = 1 + length_field_len + 1; +	for (i = 0; i < iov_count; i++) { +		memcpy(msg->data + pos, vector[i].iov_base, +		       vector[i].iov_len); +		pos += vector[i].iov_len; +	} + +	// queue it for transmission +	queue_message(tl, slot_id, connection_id, msg); + +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +	return 0; +} + +int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id) +{ +	// check +	if (slot_id >= tl->max_slots) { +		tl->error = EN50221ERR_BADSLOTID; +		return -1; +	} + +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	if (tl->slots[slot_id].ca_hndl == -1) { +		tl->error = EN50221ERR_BADSLOTID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// allocate a new connection if possible +	int conid = en50221_tl_alloc_new_tc(tl, slot_id); +	if (conid == -1) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFCONNECTIONS; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// allocate msg structure +	struct en50221_message *msg = +	    malloc(sizeof(struct en50221_message) + 3); +	if (msg == NULL) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFMEMORY; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// make up the data to send +	msg->data[0] = T_CREATE_T_C; +	msg->data[1] = 1; +	msg->data[2] = conid; +	msg->length = 3; +	msg->next = NULL; + +	// queue it for transmission +	queue_message(tl, slot_id, conid, msg); + +	// done +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +	return conid; +} + +int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id, +		      uint8_t connection_id) +{ +	// check +	if (slot_id >= tl->max_slots) { +		tl->error = EN50221ERR_BADSLOTID; +		return -1; +	} + +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	if (tl->slots[slot_id].ca_hndl == -1) { +		tl->error = EN50221ERR_BADSLOTID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (connection_id >= tl->max_connections_per_slot) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (!(tl->slots[slot_id].connections[connection_id].state & +	      (T_STATE_ACTIVE | T_STATE_IN_DELETION))) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADSTATE; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// allocate msg structure +	struct en50221_message *msg = +	    malloc(sizeof(struct en50221_message) + 3); +	if (msg == NULL) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFMEMORY; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	// make up the data to send +	msg->data[0] = T_DELETE_T_C; +	msg->data[1] = 1; +	msg->data[2] = connection_id; +	msg->length = 3; +	msg->next = NULL; + +	// queue it for transmission +	queue_message(tl, slot_id, connection_id, msg); +	tl->slots[slot_id].connections[connection_id].state = +	    T_STATE_ACTIVE_DELETEQUEUED; + +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +	return 0; +} + +int en50221_tl_get_connection_state(struct en50221_transport_layer *tl, +				    uint8_t slot_id, uint8_t connection_id) +{ +	if (slot_id >= tl->max_slots) { +		tl->error = EN50221ERR_BADSLOTID; +		return -1; +	} + +	pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +	if (tl->slots[slot_id].ca_hndl == -1) { +		tl->error = EN50221ERR_BADSLOTID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	if (connection_id >= tl->max_connections_per_slot) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCONNECTIONID; +		pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); +		return -1; +	} +	int state = tl->slots[slot_id].connections[connection_id].state; +	pthread_mutex_unlock(&tl->slots[slot_id].slot_lock); + +	return state; +} + + + + +// ask the module for new data +static int en50221_tl_poll_tc(struct en50221_transport_layer *tl, +			      uint8_t slot_id, uint8_t connection_id) +{ +	gettimeofday(&tl->slots[slot_id].connections[connection_id]. +		     tx_time, 0); + +	// send command +	uint8_t hdr[3]; +	hdr[0] = T_DATA_LAST; +	hdr[1] = 1; +	hdr[2] = connection_id; +	if (dvbca_link_write(tl->slots[slot_id].ca_hndl, +	    		     tl->slots[slot_id].slot, +			     connection_id, hdr, 3) < 0) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_CAWRITE; +		return -1; +	} +	return 0; +} + +// handle incoming data +static int en50221_tl_process_data(struct en50221_transport_layer *tl, +				   uint8_t slot_id, uint8_t * data, +				   uint32_t data_length) +{ +	int result; + +#ifdef DEBUG_RXDATA +	printf("-------------------\n"); +	uint32_t ii = 0; +	for (ii = 0; ii < data_length; ii++) { +		printf("%02x: %02x\n", ii, data[ii]); +	} +	printf("+++++++++++++++++++\n"); +#endif + +	// process the received data +	while (data_length) { +		// parse the header +		uint8_t tpdu_tag = data[0]; +		uint16_t asn_data_length; +		int length_field_len; +		if ((length_field_len = asn_1_decode(&asn_data_length, data + 1, data_length - 1)) < 0) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received data with invalid asn from module on slot %02x\n", +			      slot_id); +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_BADCAMDATA; +			return -1; +		} +		if ((asn_data_length < 1) || +		    (asn_data_length > (data_length - (1 + length_field_len)))) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received data with invalid length from module on slot %02x\n", +			      slot_id); +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_BADCAMDATA; +			return -1; +		} +		uint8_t connection_id = data[1 + length_field_len]; +		data += 1 + length_field_len + 1; +		data_length -= (1 + length_field_len + 1); +		asn_data_length--; + +		// check the connection_id +		if (connection_id >= tl->max_connections_per_slot) { +			print(LOG_LEVEL, ERROR, 1, +			      "Received bad connection id %02x from module on slot %02x\n", +			      connection_id, slot_id); +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_BADCONNECTIONID; +			return -1; +		} +		// process the TPDUs +		switch (tpdu_tag) { +		case T_C_T_C_REPLY: +			if ((result = en50221_tl_handle_create_tc_reply(tl, slot_id, connection_id)) < 0) { +				return -1; +			} +			break; +		case T_DELETE_T_C: +			if ((result = en50221_tl_handle_delete_tc(tl, slot_id, connection_id)) < 0) { +				return -1; +			} +			break; +		case T_D_T_C_REPLY: +			if ((result = en50221_tl_handle_delete_tc_reply(tl, slot_id, connection_id)) < 0) { +				return -1; +			} +			break; +		case T_REQUEST_T_C: +			if ((result = en50221_tl_handle_request_tc(tl, slot_id, connection_id)) < 0) { +				return -1; +			} +			break; +		case T_DATA_MORE: +			if ((result = en50221_tl_handle_data_more(tl, slot_id, +			     					  connection_id, +								  data, +								  asn_data_length)) < 0) { +				return -1; +			} +			break; +		case T_DATA_LAST: +			if ((result = en50221_tl_handle_data_last(tl, slot_id, +			     					  connection_id, +								  data, +								  asn_data_length)) < 0) { +				return -1; +			} +			break; +		case T_SB: +			if ((result = en50221_tl_handle_sb(tl, slot_id, +			     				   connection_id, +							   data, +							   asn_data_length)) < 0) { +				return -1; +			} +			break; +		default: +			print(LOG_LEVEL, ERROR, 1, +			      "Recieved unexpected TPDU tag %02x from module on slot %02x\n", +			      tpdu_tag, slot_id); +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_BADCAMDATA; +			return -1; +		} + +		// skip over the consumed data +		data += asn_data_length; +		data_length -= asn_data_length; +	} + +	return 0; +} + +static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer +					     *tl, uint8_t slot_id, +					     uint8_t connection_id) +{ +	// set this connection to state active +	if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_CREATION) { +		tl->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE; +		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + +		// tell upper layers +		pthread_mutex_lock(&tl->setcallback_lock); +		en50221_tl_callback cb = tl->callback; +		void *cb_arg = tl->callback_arg; +		pthread_mutex_unlock(&tl->setcallback_lock); +		if (cb) +			cb(cb_arg, T_CALLBACK_REASON_CONNECTIONOPEN, NULL, 0, slot_id, connection_id); +	} else { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_C_T_C_REPLY for connection not in " +		      "T_STATE_IN_CREATION from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} + +	return 0; +} + +static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id) +{ +	// immediately delete this connection and send D_T_C_REPLY +	if (tl->slots[slot_id].connections[connection_id].state & +	    (T_STATE_ACTIVE | T_STATE_IN_DELETION)) { +		// clear down the slot +		tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE; +		if (tl->slots[slot_id].connections[connection_id].chain_buffer) { +			free(tl->slots[slot_id].connections[connection_id].chain_buffer); +		} +		tl->slots[slot_id].connections[connection_id].chain_buffer = NULL; +		tl->slots[slot_id].connections[connection_id].buffer_length = 0; + +		// send the reply +		uint8_t hdr[3]; +		hdr[0] = T_D_T_C_REPLY; +		hdr[1] = 1; +		hdr[2] = connection_id; +		if (dvbca_link_write(tl->slots[slot_id].ca_hndl, +		    		     tl->slots[slot_id].slot, +				     connection_id, hdr, 3) < 0) { +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAWRITE; +			return -1; +		} +		// tell upper layers +		pthread_mutex_lock(&tl->setcallback_lock); +		en50221_tl_callback cb = tl->callback; +		void *cb_arg = tl->callback_arg; +		pthread_mutex_unlock(&tl->setcallback_lock); +		if (cb) +			cb(cb_arg, T_CALLBACK_REASON_CONNECTIONCLOSE, NULL, 0, slot_id, connection_id); +	} else { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_DELETE_T_C for inactive connection from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} + +	return 0; +} + +static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer +					     *tl, uint8_t slot_id, +					     uint8_t connection_id) +{ +	// delete this connection, should be in T_STATE_IN_DELETION already +	if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_DELETION) { +		tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE; +	} else { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_D_T_C_REPLY received for connection not in " +		      "T_STATE_IN_DELETION from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} + +	return 0; +} + +static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl, +					uint8_t slot_id, +					uint8_t connection_id) +{ +	// allocate a new connection if possible +	int conid = en50221_tl_alloc_new_tc(tl, slot_id); +	int ca_hndl = tl->slots[slot_id].ca_hndl; +	if (conid == -1) { +		print(LOG_LEVEL, ERROR, 1, +		      "Too many connections requested by module on slot %02x\n", +		      slot_id); + +		// send the error +		uint8_t hdr[4]; +		hdr[0] = T_T_C_ERROR; +		hdr[1] = 2; +		hdr[2] = connection_id; +		hdr[3] = 1; +		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) { +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAWRITE; +			return -1; +		} +		tl->slots[slot_id].connections[connection_id].tx_time. +		    tv_sec = 0; +	} else { +		// send the NEW_T_C on the connection we received it on +		uint8_t hdr[4]; +		hdr[0] = T_NEW_T_C; +		hdr[1] = 2; +		hdr[2] = connection_id; +		hdr[3] = conid; +		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) { +			tl->slots[slot_id].connections[conid].state = T_STATE_IDLE; +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAWRITE; +			return -1; +		} +		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + +		// send the CREATE_T_C on the new connnection +		hdr[0] = T_CREATE_T_C; +		hdr[1] = 1; +		hdr[2] = conid; +		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, conid, hdr, 3) < 0) { +			tl->slots[slot_id].connections[conid].state = T_STATE_IDLE; +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAWRITE; +			return -1; +		} +		gettimeofday(&tl->slots[slot_id].connections[conid].tx_time, 0); + +		// tell upper layers +		pthread_mutex_lock(&tl->setcallback_lock); +		en50221_tl_callback cb = tl->callback; +		void *cb_arg = tl->callback_arg; +		pthread_mutex_unlock(&tl->setcallback_lock); +		if (cb) +			cb(cb_arg, T_CALLBACK_REASON_CAMCONNECTIONOPEN, NULL, 0, slot_id, conid); +	} + +	return 0; +} + +static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id, +				       uint8_t * data, +				       uint32_t data_length) +{ +	// connection in correct state? +	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_DATA_MORE for connection not in " +		      "T_STATE_ACTIVE from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} +	// a chained data packet is coming in, save +	// it to the buffer and wait for more +	tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; +	int new_data_length = +	    tl->slots[slot_id].connections[connection_id].buffer_length + data_length; +	uint8_t *new_data_buffer = +	    realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length); +	if (new_data_buffer == NULL) { +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_OUTOFMEMORY; +		return -1; +	} +	tl->slots[slot_id].connections[connection_id].chain_buffer = new_data_buffer; + +	memcpy(tl->slots[slot_id].connections[connection_id].chain_buffer + +	       tl->slots[slot_id].connections[connection_id].buffer_length, +	       data, data_length); +	tl->slots[slot_id].connections[connection_id].buffer_length = new_data_length; + +	return 0; +} + +static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl, +				       uint8_t slot_id, +				       uint8_t connection_id, +				       uint8_t * data, +				       uint32_t data_length) +{ +	// connection in correct state? +	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_DATA_LAST received for connection not in " +		      "T_STATE_ACTIVE from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} +	// last package of a chain or single package comes in +	tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; +	if (tl->slots[slot_id].connections[connection_id].chain_buffer == NULL) { +		// single package => dispatch immediately +		pthread_mutex_lock(&tl->setcallback_lock); +		en50221_tl_callback cb = tl->callback; +		void *cb_arg = tl->callback_arg; +		pthread_mutex_unlock(&tl->setcallback_lock); + +		if (cb && data_length) { +			pthread_mutex_unlock(&tl->slots[slot_id]. +					     slot_lock); +			cb(cb_arg, T_CALLBACK_REASON_DATA, data, data_length, slot_id, connection_id); +			pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +		} +	} else { +		int new_data_length = +		    tl->slots[slot_id].connections[connection_id].buffer_length + data_length; +		uint8_t *new_data_buffer = +		    realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length); +		if (new_data_buffer == NULL) { +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_OUTOFMEMORY; +			return -1; +		} + +		memcpy(new_data_buffer + +		       tl->slots[slot_id].connections[connection_id]. +		       buffer_length, data, data_length); + +		// clean the buffer position +		tl->slots[slot_id].connections[connection_id].chain_buffer = NULL; +		tl->slots[slot_id].connections[connection_id].buffer_length = 0; + +		// tell the upper layers +		pthread_mutex_lock(&tl->setcallback_lock); +		en50221_tl_callback cb = tl->callback; +		void *cb_arg = tl->callback_arg; +		pthread_mutex_unlock(&tl->setcallback_lock); +		if (cb && data_length) { +			pthread_mutex_unlock(&tl->slots[slot_id]. +					     slot_lock); +			cb(cb_arg, T_CALLBACK_REASON_DATA, new_data_buffer, +			   new_data_length, slot_id, connection_id); +			pthread_mutex_lock(&tl->slots[slot_id].slot_lock); +		} + +		free(new_data_buffer); +	} + +	return 0; +} + +static int en50221_tl_handle_sb(struct en50221_transport_layer *tl, +				uint8_t slot_id, uint8_t connection_id, +				uint8_t * data, uint32_t data_length) +{ +	// is the connection id ok? +	if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { +		print(LOG_LEVEL, ERROR, 1, +		      "Received T_SB for connection not in T_STATE_ACTIVE from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} +	// did we get enough data in the T_SB? +	if (data_length != 1) { +		print(LOG_LEVEL, ERROR, 1, +		      "Recieved T_SB with invalid length from module on slot %02x\n", +		      slot_id); +		tl->error_slot = slot_id; +		tl->error = EN50221ERR_BADCAMDATA; +		return -1; +	} +	// tell it to send the data if it says there is some +	if (data[0] & 0x80) { +		int ca_hndl = tl->slots[slot_id].ca_hndl; + +		// send the RCV +		uint8_t hdr[3]; +		hdr[0] = T_RCV; +		hdr[1] = 1; +		hdr[2] = connection_id; +		if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 3) < 0) { +			tl->error_slot = slot_id; +			tl->error = EN50221ERR_CAWRITE; +			return -1; +		} +		gettimeofday(&tl->slots[slot_id].connections[connection_id].tx_time, 0); + +	} else { +		// no data - indicate not waiting for anything now +		tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; +	} + +	return 0; +} + +static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl, +				   uint8_t slot_id) +{ +	// we browse through the array of connection +	// types, to look for the first unused one +	int i, conid = -1; +	for (i = 1; i < tl->max_connections_per_slot; i++) { +		if (tl->slots[slot_id].connections[i].state == T_STATE_IDLE) { +			conid = i; +			break; +		} +	} +	if (conid == -1) { +		print(LOG_LEVEL, ERROR, 1, +		      "CREATE_T_C failed: no more connections available\n"); +		return -1; +	} +	// set up the connection struct +	tl->slots[slot_id].connections[conid].state = T_STATE_IN_CREATION; +	tl->slots[slot_id].connections[conid].chain_buffer = NULL; +	tl->slots[slot_id].connections[conid].buffer_length = 0; + +	return conid; +} + +static void queue_message(struct en50221_transport_layer *tl, +			  uint8_t slot_id, uint8_t connection_id, +			  struct en50221_message *msg) +{ +	msg->next = NULL; +	if (tl->slots[slot_id].connections[connection_id].send_queue_tail) { +		tl->slots[slot_id].connections[connection_id].send_queue_tail->next = msg; +		tl->slots[slot_id].connections[connection_id].send_queue_tail = msg; +	} else { +		tl->slots[slot_id].connections[connection_id].send_queue = msg; +		tl->slots[slot_id].connections[connection_id].send_queue_tail = msg; +	} +} diff --git a/lib/libdvben50221/en50221_transport.h b/lib/libdvben50221/en50221_transport.h new file mode 100644 index 0000000..7882060 --- /dev/null +++ b/lib/libdvben50221/en50221_transport.h @@ -0,0 +1,234 @@ +/* +    en50221 encoder An implementation for libdvb +    an implementation for the en50221 session layer + +    Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +    Copyright (C) 2005 Julian Scheel (julian at jusst dot de) +    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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + + +#ifndef __EN50221_TRANSPORT_H__ +#define __EN50221_TRANSPORT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <sys/uio.h> + +/** + * Callback reasons. + */ +#define T_CALLBACK_REASON_CONNECTIONOPEN       0x00	// A connection we opened _to_ the cam has been ACKed +#define T_CALLBACK_REASON_CAMCONNECTIONOPEN    0x01	// The cam has opened a connection to _us_. +#define T_CALLBACK_REASON_DATA                 0x02	// Data received +#define T_CALLBACK_REASON_CONNECTIONCLOSE      0x03	// The cam has told us to close a connection. +#define T_CALLBACK_REASON_SLOTCLOSE            0x04	// The cam in the supplied slot id has been removed. + +// these are the states a TC can be in +#define T_STATE_IDLE            0x01	// this transport connection is not in use +#define T_STATE_ACTIVE          0x02	// this transport connection is in use +#define T_STATE_ACTIVE_DELETEQUEUED 0x04	// this transport connection is about to be deleted +#define T_STATE_IN_CREATION     0x08	// this transport waits for a T_C_T_C_REPLY to become active +#define T_STATE_IN_DELETION     0x10	// this transport waits for T_D_T_C_REPLY to become idle again + +/** + * Opaque type representing a transport layer. + */ +struct en50221_transport_layer; + +/** + * Type definition for callback function - used when events are received from a module. + * + * **IMPORTANT** For all callback reasons except T_CALLBACK_REASON_DATA, an internal lock is held in the + * transport layer. Therefore, to avoid deadlock, you *must not* call back into the transport layer for + * these reasons. + * + * However, for T_CALLBACK_REASON_DATA, the internal lock is not held, so calling back into the transport + * layer is fine in this case. + * + * @param arg Private data. + * @param reason One of the T_CALLBACK_REASON_* values. + * @param data The data. + * @param data_length Length of the data. + * @param slot_id Slot_id the data was received from. + * @param connection_id Connection_id the data was received from. + */ +typedef void (*en50221_tl_callback) (void *arg, int reason, +				     uint8_t * data, +				     uint32_t data_length, +				     uint8_t slot_id, +				     uint8_t connection_id); + + +/** + * Construct a new instance of the transport layer. + * + * @param max_slots Maximum number of slots to support. + * @param max_connections_per_slot Maximum connections per slot. + * @return The en50221_transport_layer instance, or NULL on error. + */ +extern struct en50221_transport_layer *en50221_tl_create(uint8_t max_slots, +							 uint8_t max_connections_per_slot); + +/** + * Destroy an instance of the transport layer. + * + * @param tl The en50221_transport_layer instance. + */ +extern void en50221_tl_destroy(struct en50221_transport_layer *tl); + +/** + * Register a new slot with the library. + * + * @param tl The en50221_transport_layer instance. + * @param ca_hndl FD for talking to the slot. + * @param slot CAM slot where the requested CAM of the CA is in. + * @param response_timeout Maximum timeout in ms to a response we send before signalling a timeout. + * @param poll_delay Interval between polls in ms. + * @return slot_id on sucess, or -1 on error. + */ +extern int en50221_tl_register_slot(struct en50221_transport_layer *tl, +				    int ca_hndl, uint8_t slot, +				    uint32_t response_timeout, +				    uint32_t poll_delay); + +/** + * Destroy a registered slot - e.g. if a CAM is removed, or an error occurs. Does + * not attempt to reset the CAM. + * + * @param tl The en50221_transport_layer instance. + * @param slot_id Slot to destroy. + */ +extern void en50221_tl_destroy_slot(struct en50221_transport_layer *tl, uint8_t slot_id); + +/** + * Performs one iteration of the transport layer poll - + * checking for incoming data furthermore it will handle + * the timeouts of certain commands like T_DELETE_T_C it + * should be called by the application regularly, generally + * faster than the poll delay. + * + * @param tl The en50221_transport_layer instance. + * @return 0 on succes, or -1 if there was an error of some sort. + */ +extern int en50221_tl_poll(struct en50221_transport_layer *tl); + +/** + * Register the callback for data reception. + * + * @param tl The en50221_transport_layer instance. + * @param callback The callback. Set to NULL to remove the callback completely. + * @param arg Private data passed as arg0 of the callback. + */ +extern void en50221_tl_register_callback(struct en50221_transport_layer *tl, +					 en50221_tl_callback callback, void *arg); + +/** + * Gets the ID of the slot an error occurred on. + * + * @param tl The en50221_transport_layer instance. + * @return The offending slot id. + */ +extern int en50221_tl_get_error_slot(struct en50221_transport_layer *tl); + +/** + * Gets the last error. + * + * @param tl The en50221_transport_layer instance. + * @return One of the EN50221ERR_* values. + */ +extern int en50221_tl_get_error(struct en50221_transport_layer *tl); + +/** + * This function is used to take a data-block, pack into + * into a TPDU (DATA_LAST) and send it to the device + * + * @param tl The en50221_transport_layer instance. + * @param slot_id ID of the slot. + * @param connection_id Connection id. + * @param data Data to send. + * @param data_length Number of bytes to send. + * @return 0 on success, or -1 on error. + */ +extern int en50221_tl_send_data(struct en50221_transport_layer *tl, +				uint8_t slot_id, +				uint8_t connection_id, +				uint8_t * data, +				uint32_t data_length); + +/** + * This function is used to take a data-block, pack into + * into a TPDU (DATA_LAST) and send it to the device + * + * @param tl The en50221_transport_layer instance. + * @param slot_id ID of the slot. + * @param connection_id Connection id. + * @param vector iov to send. + * @param io_count Number of elements in vector. + * @return 0 on success, or -1 on error. + */ +extern int en50221_tl_send_datav(struct en50221_transport_layer *tl, +				 uint8_t slot_id, uint8_t connection_id, +				 struct iovec *vector, int iov_count); + +/** + * Create a new transport connection to the cam. + * + * **IMPORTANT** When this function returns, it means the request to create a connection + * has been submitted. You will need to poll using en50221_tl_get_connection_state() to find out + * if/when the connection is established. A callback with T_CALLBACK_REASON_CONNECTIONOPEN reason + * will also be sent when it is acked by the CAM. + * + * @param tl The en50221_transport_layer instance. + * @param slot_id ID of the slot. + * @return The allocated connection id on success, or -1 on error. + */ +extern int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id); + +/** + * Deallocates a transport connection. + * + * **IMPORTANT** When this function returns, it means the request to destroy a connection + * has been submitted. You will need to poll using en50221_tl_get_connection_state() to find out + * if/when the connection is destroyed. + * + * @param tl The en50221_transport_layer instance. + * @param slot_id ID of the slot. + * @param connection_id Connection id to send the request _on_. + * @return 0 on success, or -1 on error. + */ +extern int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id, uint8_t connection_id); + +/** + * Checks the state of a connection. + * + * @param tl The en50221_transport_layer instance. + * @param slot_id ID of the slot. + * @param connection_id Connection id to send the request _on_. + * @return One of the T_STATE_* values. + */ +extern int en50221_tl_get_connection_state(struct en50221_transport_layer *tl, +					   uint8_t slot_id, uint8_t connection_id); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libdvbmisc/dvbmisc.h b/lib/libdvbmisc/dvbmisc.h new file mode 100644 index 0000000..8ac6eee --- /dev/null +++ b/lib/libdvbmisc/dvbmisc.h @@ -0,0 +1,72 @@ +/* +	libdvbmisc - DVB miscellaneous library + +	Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com> + +	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 DVB_MISC_H +#define DVB_MISC_H + +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/time.h> + +#define ERROR		0 +#define NOTICE		1 +#define INFO		2 +#define DEBUG		3 + +#define print(x, y, z, fmt, arg...) do {				\ +	if (z) {							\ +		if	((x > ERROR) && (x > y))			\ +			vprint("%s: " fmt "\n", __func__ , ##arg);	\ +		else if	((x > NOTICE) && (x > y))			\ +			vprint("%s: " fmt "\n",__func__ , ##arg);	\ +		else if ((x > INFO) && (x > y))				\ +			vprint("%s: " fmt "\n", __func__ , ##arg);	\ +		else if ((x > DEBUG) && (x > y))			\ +			vprint("%s: " fmt "\n", __func__ , ##arg);	\ +	} else {							\ +		if (x > y)						\ +			vprint(fmt, ##arg);				\ +	}								\ +} while(0) + +static inline void vprint(char *fmt, ...) +{ +	va_list args; + +	va_start(args, fmt); +	vfprintf(stderr, fmt, args); +	va_end(args); +} + +static inline int time_after(struct timeval oldtime, uint32_t delta_ms) +{ +	// calculate the oldtime + add on the delta +	uint64_t oldtime_ms = (oldtime.tv_sec * 1000) + (oldtime.tv_usec / 1000); +	oldtime_ms += delta_ms; + +	// calculate the nowtime +	struct timeval nowtime; +	gettimeofday(&nowtime, 0); +	uint64_t nowtime_ms = (nowtime.tv_sec * 1000) + (nowtime.tv_usec / 1000); + +	// check +	return nowtime_ms > oldtime_ms; +} + +#endif diff --git a/lib/libdvbsec/Makefile b/lib/libdvbsec/Makefile new file mode 100644 index 0000000..3d405f4 --- /dev/null +++ b/lib/libdvbsec/Makefile @@ -0,0 +1,17 @@ +# Makefile for linuxtv.org dvb-apps/lib/libdvbsec + +includes = dvbsec_api.h        \ +           dvbsec_cfg.h + +objects  = dvbsec_api.o        \ +           dvbsec_cfg.o + +lib_name = libdvbsec + +CPPFLAGS += -I../../lib + +.PHONY: all + +all: library + +include ../../Make.rules diff --git a/lib/libdvbsec/dvbsec_api.c b/lib/libdvbsec/dvbsec_api.c new file mode 100644 index 0000000..5f2ae22 --- /dev/null +++ b/lib/libdvbsec/dvbsec_api.c @@ -0,0 +1,951 @@ +/* +	libdvbsec - an SEC library + +	Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com> +	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 <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <linux/types.h> +#include <libdvbapi/dvbfe.h> +#include "dvbsec_api.h" + +// uncomment this to make dvbsec_command print out debug instead of talking to a frontend +// #define TEST_SEC_COMMAND 1 + +int dvbsec_set(struct dvbfe_handle *fe, +		   struct dvbsec_config *sec_config, +		   enum dvbsec_diseqc_polarization polarization, +		   enum dvbsec_diseqc_switch sat_pos, +		   enum dvbsec_diseqc_switch switch_option, +		   struct dvbfe_parameters *params, +		   int timeout) +{ +	int tmp; +	struct dvbfe_parameters localparams; +	struct dvbfe_parameters *topass = params; + +	// perform SEC +	if (sec_config != NULL) { +		switch(sec_config->config_type) { +		case DVBSEC_CONFIG_NONE: +			break; + +		case DVBSEC_CONFIG_POWER: +			dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13); +			break; + +		case DVBSEC_CONFIG_STANDARD: +		{ +			// calculate the correct oscillator value +			enum dvbsec_diseqc_oscillator osc = DISEQC_OSCILLATOR_LOW; +			if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency)) +				osc = DISEQC_OSCILLATOR_HIGH; + +			if ((tmp = dvbsec_std_sequence(fe, +			     				  osc, +							  polarization, +							  sat_pos, +							  switch_option)) < 0) +				return tmp; +			break; +		} + +		case DVBSEC_CONFIG_ADVANCED: +		{ +			// are we high or not? +			int high = 0; +			if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency)) +				high = 1; + +			//  determine correct string +			char *cmd = NULL; +			switch(polarization) { +			case DISEQC_POLARIZATION_H: +				if (!high) +					cmd = sec_config->adv_cmd_lo_h; +				else +					cmd = sec_config->adv_cmd_hi_h; +				break; +			case DISEQC_POLARIZATION_V: +				if (!high) +					cmd = sec_config->adv_cmd_lo_v; +				else +					cmd = sec_config->adv_cmd_hi_v; +				break; +			case DISEQC_POLARIZATION_L: +				if (!high) +					cmd = sec_config->adv_cmd_lo_l; +				else +					cmd = sec_config->adv_cmd_hi_l; +				break; +			case DISEQC_POLARIZATION_R: +				if (!high) +					cmd = sec_config->adv_cmd_lo_r; +				else +					cmd = sec_config->adv_cmd_hi_r; +				break; +			default: +				return -EINVAL; +			} + +			// do it +			if (cmd) +				if ((tmp = dvbsec_command(fe, cmd)) < 0) +					return tmp; +			break; +		} +		} + +		// work out the correct LOF value +		uint32_t lof = 0; +		if ((sec_config->switch_frequency == 0) || (params->frequency < sec_config->switch_frequency)) { +			// LOW band +			switch(polarization) { +			case DISEQC_POLARIZATION_H: +				lof = sec_config->lof_lo_h; +				break; +			case DISEQC_POLARIZATION_V: +				lof = sec_config->lof_lo_v; +				break; +			case DISEQC_POLARIZATION_L: +				lof = sec_config->lof_lo_l; +				break; +			case DISEQC_POLARIZATION_R: +				lof = sec_config->lof_lo_r; +				break; +			case DISEQC_POLARIZATION_UNCHANGED: +				break; +			} +		} else { +			// HIGH band +			switch(polarization) { +			case DISEQC_POLARIZATION_H: +				lof = sec_config->lof_hi_h; +				break; +			case DISEQC_POLARIZATION_V: +				lof = sec_config->lof_hi_v; +				break; +			case DISEQC_POLARIZATION_L: +				lof = sec_config->lof_hi_l; +				break; +			case DISEQC_POLARIZATION_R: +				lof = sec_config->lof_hi_r; +				break; +			case DISEQC_POLARIZATION_UNCHANGED: +				break; +			} +		} + +		// do frequency adjustment +		if (lof) { +			memcpy(&localparams, params, sizeof(struct dvbfe_parameters)); +			int tmpfreq = localparams.frequency - lof; + +			if (tmpfreq < 0) +				tmpfreq *= -1; +			localparams.frequency = (uint32_t) tmpfreq; +			topass = &localparams; +		} +	} + +	// set the frontend! +	return dvbfe_set(fe, topass, timeout); +} + +int dvbsec_std_sequence(struct dvbfe_handle *fe, +			   enum dvbsec_diseqc_oscillator oscillator, +			   enum dvbsec_diseqc_polarization polarization, +			   enum dvbsec_diseqc_switch sat_pos, +			   enum dvbsec_diseqc_switch switch_option) +{ +	dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF); + +	switch(polarization) { +	case DISEQC_POLARIZATION_V: +	case DISEQC_POLARIZATION_R: +		dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13); +		break; +	case DISEQC_POLARIZATION_H: +	case DISEQC_POLARIZATION_L: +		dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18); +		break; +	default: +		return -EINVAL; +	} + +	dvbsec_diseqc_set_committed_switches(fe, +					    DISEQC_ADDRESS_ANY_DEVICE, +					    oscillator, +					    polarization, +					    sat_pos, +					    switch_option); + +	usleep(15000); + +	switch(sat_pos) { +	case DISEQC_SWITCH_A: +		dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A); +		break; +	case DISEQC_SWITCH_B: +		dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B); +		break; +	default: +		break; +	} + +	if (sat_pos != DISEQC_SWITCH_UNCHANGED) +		usleep(15000); + +	switch(oscillator) { +	case DISEQC_OSCILLATOR_LOW: +		dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF); +		break; +	case DISEQC_OSCILLATOR_HIGH: +		dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON); +		break; +	default: +		break; +	} + +	return 0; +} + +int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe, +			   enum dvbsec_diseqc_address address, +			   enum dvbsec_diseqc_reset state) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x00 }; + +	if (state == DISEQC_RESET_CLEAR) +		data[2] = 0x01; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_power(struct dvbfe_handle *fe, +			   enum dvbsec_diseqc_address address, +			   enum dvbsec_diseqc_power state) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x02 }; + +	if (state == DISEQC_POWER_ON) +		data[2] = 0x03; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe, +			    enum dvbsec_diseqc_address address, +			    enum dvbsec_diseqc_listen state) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x30 }; + +	if (state == DISEQC_LISTEN_AWAKE) +		data[2] = 0x31; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe, +					enum dvbsec_diseqc_address address, +					enum dvbsec_diseqc_oscillator oscillator, +					enum dvbsec_diseqc_polarization polarization, +					enum dvbsec_diseqc_switch sat_pos, +					enum dvbsec_diseqc_switch switch_option) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x38, 0x00 }; + +	switch(oscillator) { +	case DISEQC_OSCILLATOR_LOW: +		data[3] |= 0x10; +		break; +	case DISEQC_OSCILLATOR_HIGH: +		data[3] |= 0x11; +		break; +	case DISEQC_OSCILLATOR_UNCHANGED: +		break; +	} +	switch(polarization) { +	case DISEQC_POLARIZATION_V: +	case DISEQC_POLARIZATION_R: +		data[3] |= 0x20; +		break; +	case DISEQC_POLARIZATION_H: +	case DISEQC_POLARIZATION_L: +		data[3] |= 0x22; +		break; +	default: +		break; +	} +	switch(sat_pos) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x40; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x44; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} +	switch(switch_option) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x80; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x88; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} + +	if (data[3] == 0) +		return 0; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe, +					  enum dvbsec_diseqc_address address, +					  enum dvbsec_diseqc_switch s1, +					  enum dvbsec_diseqc_switch s2, +					  enum dvbsec_diseqc_switch s3, +					  enum dvbsec_diseqc_switch s4) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x39, 0x00 }; + +	switch(s1) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x10; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x11; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} +	switch(s2) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x20; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x22; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} +	switch(s3) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x40; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x44; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} +	switch(s4) { +	case DISEQC_SWITCH_A: +		data[3] |= 0x80; +		break; +	case DISEQC_SWITCH_B: +		data[3] |= 0x88; +		break; +	case DISEQC_SWITCH_UNCHANGED: +		break; +	} + +	if (data[3] == 0) +		return 0; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe, +				  enum dvbsec_diseqc_address address, +				  enum dvbsec_diseqc_analog_id id, +				  uint8_t value) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x48, value }; + +	if (id == DISEQC_ANALOG_ID_A1) +		data[2] = 0x49; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe, +			       enum dvbsec_diseqc_address address, +			       uint32_t frequency) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x58, 0x00, 0x00, 0x00 }; +	int len = 5; + +	uint32_t bcdval = 0; +	int i; +	for(i=0; i<=24;i+=4) { +		bcdval |= ((frequency % 10) << i); +		frequency /= 10; +	} + +	data[3] = bcdval >> 16; +	data[4] = bcdval >> 8; +	if (bcdval & 0xff) { +		data[5] = bcdval; +		len++; +	} + +	return dvbfe_do_diseqc_command(fe, data, len); +} + +int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe, +			     enum dvbsec_diseqc_address address, +			     uint16_t channel) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x59, 0x00, 0x00}; + +	data[3] = channel >> 8; +	data[4] = channel; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe, +			     enum dvbsec_diseqc_address address) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x60}; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe, +				       enum dvbsec_diseqc_address address) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x63}; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe, +				  enum dvbsec_diseqc_address address, +				  enum dvbsec_diseqc_direction direction) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x66}; + +	if (direction == DISEQC_DIRECTION_WEST) +		data[2] = 0x67; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe, +				    enum dvbsec_diseqc_address address, +				    enum dvbsec_diseqc_direction direction, +				    enum dvbsec_diseqc_drive_mode mode, +				    uint8_t value) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x68, 0x00}; + +	if (direction == DISEQC_DIRECTION_WEST) +		data[2] = 0x69; + +	switch(mode) { +	case DISEQC_DRIVE_MODE_STEPS: +		data[3] = (value & 0x7f) | 0x80; +		break; +	case DISEQC_DRIVE_MODE_TIMEOUT: +		data[3] = value & 0x7f; +		break; +	} + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe, +				     enum dvbsec_diseqc_address address, +				     uint8_t id) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6A, id}; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe, +				    enum dvbsec_diseqc_address address, +				    uint8_t id) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6B, id}; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe, +					      enum dvbsec_diseqc_address address, +					      int val1, +					      int val2) +{ +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6F, 0x00, 0x00}; +	int len = 3; + +	if (val1 != -1) { +		data[3] = val1; +		len++; +	} +	if (val2 != -1) { +		data[4] = val2; +		len = 5; +	} + +	return dvbfe_do_diseqc_command(fe, data, len); +} + +int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe, +				      enum dvbsec_diseqc_address address, +				      float angle) +{ +	int integer = (int) angle; +	uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6e, 0x00, 0x00}; + +	// transform the fraction into the correct representation +	int fraction = (int) (((angle - integer) * 16.0) + 0.9) & 0x0f; +	switch(fraction) { +	case 1: +	case 4: +	case 7: +	case 9: +	case 12: +	case 15: +		fraction--; +		break; +	} + +	// generate the command +	if (integer < -256) { +		return -EINVAL; +	} else if (integer < 0) { +		integer = -integer; +		data[3] = 0xf0; +	} else if (integer < 256) { +		data[3] = 0x00; +	} else if (integer < 512) { +		integer -= 256; +		data[3] = 0x10; +	} else { +		return -EINVAL; +	} +	data[3] |= ((integer / 16) & 0x0f); +	integer = integer % 16; +	data[4] |= ((integer & 0x0f) << 4) | fraction; + +	return dvbfe_do_diseqc_command(fe, data, sizeof(data)); +} + +static int skipwhite(char **line, char *end) +{ +	while(**line) { +		if (end && (*line >= end)) +			return -1; +		if (!isspace(**line)) +			return 0; +		(*line)++; +	} + +	return -1; +} + +static int getstringupto(char **line, char *end, char *matches, char **ptrdest, int *ptrlen) +{ +	char *start = *line; + +	while(**line) { +		if (end && (*line >= end)) +			break; +		if (strchr(matches, **line)) { +			*ptrdest = start; +			*ptrlen = *line - start; +			return 0; +		} +		(*line)++; +	} + +	*ptrdest = start; +	*ptrlen = *line - start; +	return 0; +} + +static int parsefunction(char **line, +			 char **nameptr, int *namelen, +			 char **argsptr, int *argslen) +{ +	if (skipwhite(line, NULL)) +		return -1; + +	if (getstringupto(line, NULL, "(", nameptr, namelen)) +		return -1; +	if ((*line) == 0) +		return -1; +	(*line)++; // skip the '(' +	if (getstringupto(line, NULL, ")", argsptr, argslen)) +		return -1; +	if ((*line) == 0) +		return -1; +	(*line)++; // skip the ')' + +	return 0; +} + +static int parseintarg(char **args, char *argsend, int *result) +{ +	char tmp[32]; +	char *arg; +	int arglen; + +	// skip whitespace +	if (skipwhite(args, argsend)) +		return -1; + +	// get the arg +	if (getstringupto(args, argsend, ",", &arg, &arglen)) +		return -1; +	if ((**args) == ',') +		(*args)++; // skip the ',' if present +	if (arglen > 31) +		arglen = 31; +	strncpy(tmp, arg, arglen); +	tmp[arglen] = 0; + +	if (sscanf(tmp, "%i", result) != 1) +		return -1; + +	return 0; +} + +static int parsechararg(char **args, char *argsend, int *result) +{ +	char *arg; +	int arglen; + +	// skip whitespace +	if (skipwhite(args, argsend)) +		return -1; + +	// get the arg +	if (getstringupto(args, argsend, ",", &arg, &arglen)) +		return -1; +	if ((**args) == ',') +		(*args)++; // skip the ',' if present +	if (arglen > 0) +		*result = arg[0]; + +	return 0; +} + +static int parsefloatarg(char **args, char *argsend, float *result) +{ +	char tmp[32]; +	char *arg; +	int arglen; + +	// skip whitespace +	if (skipwhite(args, argsend)) +		return -1; + +	// get the arg +	if (getstringupto(args, argsend, ",", &arg, &arglen)) +		return -1; +	if ((**args) == ',') +		(*args)++; // skip the ',' if present +	if (arglen > 31) +		arglen = 31; +	strncpy(tmp, arg, arglen); +	arg[arglen] = 0; + +	if (sscanf(tmp, "%f", result) != 1) +		return -1; + +	return 0; +} + +static enum dvbsec_diseqc_switch parse_switch(int c) +{ +	switch(toupper(c)) { +	case 'A': +		return DISEQC_SWITCH_A; +	case 'B': +		return DISEQC_SWITCH_B; +	default: +		return DISEQC_SWITCH_UNCHANGED; +	} +} + +int dvbsec_command(struct dvbfe_handle *fe, char *command) +{ +	char *name; +	char *args; +	int namelen; +	int argslen; +	int address; +	int iarg; +	int iarg2; +	int iarg3; +	int iarg4; +	float farg; + +	while(!parsefunction(&command, &name, &namelen, &args, &argslen)) { +		char *argsend = args+argslen; + +		if (!strncasecmp(name, "tone", namelen)) { +			if (parsechararg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("tone: %c\n", iarg); +#else +			if (toupper(iarg) == 'B') { +				dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON); +			} else { +				dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF); +			} +#endif +		} else if (!strncasecmp(name, "voltage", namelen)) { +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("voltage: %i\n", iarg); +#else +			switch(iarg) { +			case 0: +				dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_OFF); +				break; +			case 13: +				dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13); +				break; +			case 18: +				dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18); +				break; +			default: +				return -1; +			} +#endif +		} else if (!strncasecmp(name, "toneburst", namelen)) { +			if (parsechararg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("toneburst: %c\n", iarg); +#else +			if (toupper(iarg) == 'B') { +				dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B); +			} else { +				dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A); +			} +#endif +		} else if (!strncasecmp(name, "highvoltage", namelen)) { +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("highvoltage: %i\n", iarg); +#else +			dvbfe_set_high_lnb_voltage(fe, iarg ? 1 : 0); +#endif +		} else if (!strncasecmp(name, "dishnetworks", namelen)) { +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("dishnetworks: %i\n", iarg); +#else +			dvbfe_do_dishnetworks_legacy_command(fe, iarg); +#endif +		} else if (!strncasecmp(name, "wait", namelen)) { +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("wait: %i\n", iarg); +#else +			if (iarg) +				usleep(iarg * 1000); +#endif +		} else if (!strncasecmp(name, "Dreset", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dreset: %i %i\n", address, iarg); +#else +			if (iarg) { +				dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET); +			} else { +				dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET_CLEAR); +			} +#endif +		} else if (!strncasecmp(name, "Dpower", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dpower: %i %i\n", address, iarg); +#else +			if (iarg) { +				dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_ON); +			} else { +				dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_OFF); +			} +#endif +		} else if (!strncasecmp(name, "Dcommitted", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parsechararg(&args, argsend, &iarg)) +				return -1; +			if (parsechararg(&args, argsend, &iarg2)) +				return -1; +			if (parsechararg(&args, argsend, &iarg3)) +				return -1; +			if (parsechararg(&args, argsend, &iarg4)) +				return -1; + +			enum dvbsec_diseqc_oscillator oscillator; +			switch(toupper(iarg)) { +			case 'H': +				oscillator = DISEQC_OSCILLATOR_HIGH; +				break; +			case 'L': +				oscillator = DISEQC_OSCILLATOR_LOW; +				break; +			default: +				oscillator = DISEQC_OSCILLATOR_UNCHANGED; +				break; +			} + +			int polarization = -1; +			switch(toupper(iarg2)) { +			case 'H': +				polarization = DISEQC_POLARIZATION_H; +				break; +			case 'V': +				polarization = DISEQC_POLARIZATION_V; +				break; +			case 'L': +				polarization = DISEQC_POLARIZATION_L; +				break; +			case 'R': +				polarization = DISEQC_POLARIZATION_R; +				break; +			default: +				polarization = -1; +				break; +			} + +#ifdef TEST_SEC_COMMAND +			printf("Dcommitted: %i %i %i %i %i\n", address, +			       oscillator, +			       polarization, +			       parse_switch(iarg3), +			       parse_switch(iarg4)); +#else +			dvbsec_diseqc_set_committed_switches(fe, address, +							    oscillator, +							    polarization, +							    parse_switch(iarg3), +							    parse_switch(iarg4)); +#endif +		} else if (!strncasecmp(name, "Duncommitted", namelen)) { +			if (parsechararg(&args, argsend, &address)) +				return -1; +			if (parsechararg(&args, argsend, &iarg)) +				return -1; +			if (parsechararg(&args, argsend, &iarg2)) +				return -1; +			if (parsechararg(&args, argsend, &iarg3)) +				return -1; +			if (parsechararg(&args, argsend, &iarg4)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Duncommitted: %i %i %i %i %i\n", address, +			       parse_switch(iarg), +			       parse_switch(iarg2), +			       parse_switch(iarg3), +			       parse_switch(iarg4)); +#else +			dvbsec_diseqc_set_uncommitted_switches(fe, address, +					parse_switch(iarg), +					parse_switch(iarg2), +					parse_switch(iarg3), +					parse_switch(iarg4)); +#endif +		} else if (!strncasecmp(name, "Dfrequency", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dfrequency: %i %i\n", address, iarg); +#else +			dvbsec_diseqc_set_frequency(fe, address, iarg); +#endif +		} else if (!strncasecmp(name, "Dchannel", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dchannel: %i %i\n", address, iarg); +#else +			dvbsec_diseqc_set_channel(fe, address, iarg); +#endif +		} else if (!strncasecmp(name, "Dgotopreset", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parseintarg(&args, argsend, &iarg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dgotopreset: %i %i\n", address, iarg); +#else +			dvbsec_diseqc_goto_satpos_preset(fe, address, iarg); +#endif +		} else if (!strncasecmp(name, "Dgotobearing", namelen)) { +			if (parseintarg(&args, argsend, &address)) +				return -1; +			if (parsefloatarg(&args, argsend, &farg)) +				return -1; + +#ifdef TEST_SEC_COMMAND +			printf("Dgotobearing: %i %f\n", address, farg); +#else +			dvbsec_diseqc_goto_rotator_bearing(fe, address, farg); +#endif +		} else { +			return -1; +		} +	} + +	return 0; +} diff --git a/lib/libdvbsec/dvbsec_api.h b/lib/libdvbsec/dvbsec_api.h new file mode 100644 index 0000000..7e454d7 --- /dev/null +++ b/lib/libdvbsec/dvbsec_api.h @@ -0,0 +1,436 @@ +/* +	libdvbsec - an SEC library + +	Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com> +	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 DVBSEC_API_H +#define DVBSEC_API_H 1 + +#include <stdint.h> + +struct dvbfe_handle; +struct dvbfe_parameters; + +enum dvbsec_diseqc_framing { +	DISEQC_FRAMING_MASTER_NOREPLY		= 0xE0, +	DISEQC_FRAMING_MASTER_NOREPLY_REPEAT	= 0xE1, +	DISEQC_FRAMING_MASTER_REPLY		= 0xE2, +	DISEQC_FRAMING_MASTER_REPLY_REPEAT	= 0xE3, +	DISEQC_FRAMING_SLAVE_OK			= 0xE4, +	DISEQC_FRAMING_SLAVE_UNSUPPORTED	= 0xE5, +	DISEQC_FRAMING_SLAVE_PARITY_ERROR	= 0xE6, +	DISEQC_FRAMING_SLAVE_UNRECOGNISED 	= 0xE7, +}; + +enum dvbsec_diseqc_address { +	DISEQC_ADDRESS_ANY_DEVICE		= 0x00, + +	DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV	= 0x10, +	DISEQC_ADDRESS_LNB			= 0x11, +	DISEQC_ADDRESS_LNB_WITH_LOOP		= 0x12, +	DISEQC_ADDRESS_SWITCHER			= 0x14, +	DISEQC_ADDRESS_SWITCHER_WITH_LOOP	= 0x15, +	DISEQC_ADDRESS_SMATV			= 0x18, + +	DISEQC_ADDRESS_ANY_POLARISER		= 0x20, +	DISEQC_ADDRESS_LINEAR_POLARISER		= 0x21, + +	DISEQC_ADDRESS_ANY_POSITIONER		= 0x30, +	DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER	= 0x31, +	DISEQC_ADDRESS_ELEVATION_POSITIONER	= 0x32, + +	DISEQC_ADDRESS_ANY_INSTALLER_AID	= 0x40, +	DISEQC_ADDRESS_SIGNAL_STRENGTH		= 0x41, + +	DISEQC_ADDRESS_ANY_INTERFACE		= 0x70, +	DISEQC_ADDRESS_HEADEND_INTERFACE	= 0x71, + +	DISEQC_ADDRESS_REALLOC_BASE		= 0x60, +	DISEQC_ADDRESS_OEM_BASE			= 0xf0, +}; + +enum dvbsec_diseqc_reset { +	DISEQC_RESET, +	DISEQC_RESET_CLEAR, +}; + +enum dvbsec_diseqc_power { +	DISEQC_POWER_OFF, +	DISEQC_POWER_ON, +}; + +enum dvbsec_diseqc_listen { +	DISEQC_LISTEN_SLEEP, +	DISEQC_LISTEN_AWAKE, +}; + +enum dvbsec_diseqc_polarization { +	DISEQC_POLARIZATION_UNCHANGED = 0, +	DISEQC_POLARIZATION_H = 'h', +	DISEQC_POLARIZATION_V = 'v', +	DISEQC_POLARIZATION_L = 'l', +	DISEQC_POLARIZATION_R = 'r', +}; + +enum dvbsec_diseqc_oscillator { +	DISEQC_OSCILLATOR_UNCHANGED = 0, +	DISEQC_OSCILLATOR_LOW, +	DISEQC_OSCILLATOR_HIGH, +}; + +enum dvbsec_diseqc_switch { +	DISEQC_SWITCH_UNCHANGED = 0, +	DISEQC_SWITCH_A, +	DISEQC_SWITCH_B, +}; + +enum dvbsec_diseqc_analog_id { +	DISEQC_ANALOG_ID_A0, +	DISEQC_ANALOG_ID_A1, +}; + +enum dvbsec_diseqc_drive_mode { +	DISEQC_DRIVE_MODE_STEPS, +	DISEQC_DRIVE_MODE_TIMEOUT, +}; + +enum dvbsec_diseqc_direction { +	DISEQC_DIRECTION_EAST, +	DISEQC_DIRECTION_WEST, +}; + +enum dvbsec_config_type { +	DVBSEC_CONFIG_NONE = 0, +	DVBSEC_CONFIG_POWER, +	DVBSEC_CONFIG_STANDARD, +	DVBSEC_CONFIG_ADVANCED, +}; + + +#define MAX_SEC_CMD_LEN 100 + +struct dvbsec_config +{ +	char id[32]; /* ID of this SEC config structure */ +	uint32_t switch_frequency; /* switching frequency - supply 0 for none. */ +	uint32_t lof_lo_v; /* frequency to subtract for V + LOW band channels - or for switch_frequency == 0 */ +	uint32_t lof_lo_h; /* frequency to subtract for H + LOW band channels - or for switch_frequency == 0 */ +	uint32_t lof_lo_l; /* frequency to subtract for L + LOW band channels - or for switch_frequency == 0 */ +	uint32_t lof_lo_r; /* frequency to subtract for R + LOW band channels - or for switch_frequency == 0 */ +	uint32_t lof_hi_v; /* frequency to subtract for V + HIGH band channels */ +	uint32_t lof_hi_h; /* frequency to subtract for H + HIGH band channels */ +	uint32_t lof_hi_l; /* frequency to subtract for L + HIGH band channels */ +	uint32_t lof_hi_r; /* frequency to subtract for R + HIGH band channels */ + +	/** +	 * The SEC control to be used depends on the type: +	 * +	 * NONE - no SEC commands will be issued. (Frequency adjustment will still be performed). +	 * +	 * POWER - only the SEC power will be turned on. +	 * +	 * STANDARD - the standard DISEQC back compatable sequence is used. +	 * +	 * ADVANCED - SEC strings are supplied by the user describing the exact sequence +	 * of operations to use. +	 */ +	enum dvbsec_config_type config_type; + +	/* stuff for type == dvbsec_config_ADVANCED */ +	char adv_cmd_lo_h[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for LOW/H. */ +	char adv_cmd_lo_v[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for LOW/V. */ +	char adv_cmd_lo_l[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for LOW/L. */ +	char adv_cmd_lo_r[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for LOW/R. */ +	char adv_cmd_hi_h[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for HI/H. */ +	char adv_cmd_hi_v[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for HI/V. */ +	char adv_cmd_hi_l[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for HI/L. */ +	char adv_cmd_hi_r[MAX_SEC_CMD_LEN];			/* ADVANCED SEC command to use for HI/R. */ +}; + +/** + * Helper function for tuning adapters with SEC support. This function will do + * everything required, including frequency adjustment based on the parameters + * in sec_config. + * + * Note: Since the SEC configuration structure can be set to disable any SEC + * operations, this function can be reused for ALL DVB style devices (just + * set all LOF=0,type=dvbsec_config_NONE for devices which do not require + * SEC control). + * + * The sec configuration structures can be looked up using the dvbcfg_sec library. + * + * @param fe Frontend concerned. + * @param sec_config SEC configuration structure. May be NULL to disable SEC/frequency adjustment. + * @param polarization Polarization of signal. + * @param sat_pos Satellite position - only used if type == DISEQC_SEC_CONFIG_STANDARD. + * @param switch_option Switch option - only used if type == DISEQC_SEC_CONFIG_STANDARD. + * @param params Tuning parameters. + * @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 dvbsec_set(struct dvbfe_handle *fe, +			  struct dvbsec_config *sec_config, +			  enum dvbsec_diseqc_polarization polarization, +			  enum dvbsec_diseqc_switch sat_pos, +			  enum dvbsec_diseqc_switch switch_option, +			  struct dvbfe_parameters *params, +			  int timeout); + +/** + * This will issue the standardised back-compatable DISEQC/SEC command + * sequence as defined in the DISEQC spec: + * + * i.e. tone off, set voltage, wait15, DISEQC, wait15, toneburst, wait15, set tone. + * + * @param fe Frontend concerned. + * @param oscillator Value to set the lo/hi switch to. + * @param polarization Value to set the polarisation switch to. + * @param sat_pos Value to set the satellite position switch to. + * @param switch_option Value to set the "swtch option" switch to. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_std_sequence(struct dvbfe_handle *fe, +				  enum dvbsec_diseqc_oscillator oscillator, +				  enum dvbsec_diseqc_polarization polarization, +				  enum dvbsec_diseqc_switch sat_pos, +				  enum dvbsec_diseqc_switch switch_option); + +/** + * Execute an SEC command string on the provided frontend. Please see the documentation + * in dvbsec_cfg.h on the command format, + * + * @param fe Frontend concerned. + * @param command The command to execute. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_command(struct dvbfe_handle *fe, char *command); + +/** + * Control the reset status of an attached DISEQC device. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param state The state to set. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe, +				  enum dvbsec_diseqc_address address, +				  enum dvbsec_diseqc_reset state); + +/** + * Control the power status of an attached DISEQC peripheral. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param state The state to set. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_power(struct dvbfe_handle *fe, +				  enum dvbsec_diseqc_address address, +				  enum dvbsec_diseqc_power state); + +/** + * Control the listening status of an attached DISEQC peripheral. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param state The state to set. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe, +				   enum dvbsec_diseqc_address address, +				   enum dvbsec_diseqc_listen state); + +/** + * Set the state of the committed switches of a DISEQC device. + * These are switches which are defined to have a standard name. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param oscillator Value to set the lo/hi switch to. + * @param polarization Value to set the polarization switch to. + * @param sat_pos Value to set the satellite position switch to. + * @param switch_option Value to set the switch option switch to. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe, +					       enum dvbsec_diseqc_address address, +					       enum dvbsec_diseqc_oscillator oscillator, +					       enum dvbsec_diseqc_polarization polarization, +					       enum dvbsec_diseqc_switch sat_pos, +					       enum dvbsec_diseqc_switch switch_option); + +/** + * Set the state of the uncommitted switches of a DISEQC device. + * These provide another four switching possibilities. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param s1 Value to set the S1 switch to. + * @param s2 Value to set the S2 switch to. + * @param s3 Value to set the S3 switch to. + * @param s3 Value to set the S4 switch to. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe, +						 enum dvbsec_diseqc_address address, +						 enum dvbsec_diseqc_switch s1, +						 enum dvbsec_diseqc_switch s2, +						 enum dvbsec_diseqc_switch s3, +						 enum dvbsec_diseqc_switch s4); + +/** + * Set an analogue value. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param id The id of the analogue value to set. + * @param value The value to set. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe, +					 enum dvbsec_diseqc_address address, +					 enum dvbsec_diseqc_analog_id id, +					 uint8_t value); + +/** + * Set the desired frequency. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param frequency The frequency to set in GHz. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe, +				      enum dvbsec_diseqc_address address, +				      uint32_t frequency); + +/** + * Set the desired channel. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param channel ID of the channel to set. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe, +				    enum dvbsec_diseqc_address address, +				    uint16_t channel); + +/** + * Halt the satellite positioner. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe, +				    enum dvbsec_diseqc_address address); + +/** + * Disable satellite positioner limits. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe, +					      enum dvbsec_diseqc_address address); + +/** + * Set satellite positioner limits. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe, +					 enum dvbsec_diseqc_address address, +					 enum dvbsec_diseqc_direction direction); + +/** + * Drive satellite positioner motor. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param direction Direction to drive in. + * @param mode Drive mode to use + * 	       (TIMEOUT=>value is a timeout in seconds, or STEPS=>value is a count of steps to use) + * @param value Value associated with the drive mode (range 0->127) + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe, +					   enum dvbsec_diseqc_address address, +					   enum dvbsec_diseqc_direction direction, +					   enum dvbsec_diseqc_drive_mode mode, +					   uint8_t value); + +/** + * Store satellite positioner preset id at current position. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param id ID of the preset. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe, +					    enum dvbsec_diseqc_address address, +					    uint8_t id); + +/** + * Send a satellite positioner to a pre-set position. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param id ID of the preset. + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe, +					   enum dvbsec_diseqc_address address, +					   uint8_t id); + +/** + * Recalculate satellite positions based on the current position, using + * magic positioner specific values. + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param val1 value1 (range 0->255, pass -1 to ignore). + * @param val2 value2 (range 0->255, pass -1 to ignore). + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe, +						     enum dvbsec_diseqc_address address, +						     int val1, +						     int val2); + +/** + * Send a terrestrial aerial rotator to a particular bearing + * (0 degrees = north, fractional angles allowed). + * + * @param fe Frontend concerned. + * @param address Address of the device. + * @param angle Angle to rotate to (-256.0 -> 512.0) + * @return 0 on success, or nonzero on error. + */ +extern int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe, +					     enum dvbsec_diseqc_address address, +					     float angle); + +#endif diff --git a/lib/libdvbsec/dvbsec_cfg.c b/lib/libdvbsec/dvbsec_cfg.c new file mode 100644 index 0000000..4b05a32 --- /dev/null +++ b/lib/libdvbsec/dvbsec_cfg.c @@ -0,0 +1,366 @@ +/** + * dvbsec_cfg (i.e. linuxtv sec format) configuration file support. + * + * Copyright (c) 2005 by 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <linux/types.h> +#include "dvbsec_cfg.h" + +int dvbcfg_issection(char* line, char* sectionname) +{ +	int len; + +	len = strlen(line); +	if (len < 2) +		return 0; + +	if ((line[0] != '[') || (line[len-1] != ']')) +		return 0; + +	line++; +	while(isspace(*line)) +		line++; + +	if (strncmp(line, sectionname, strlen(sectionname))) +		return 0; + +	return 1; +} + +char* dvbcfg_iskey(char* line, char* keyname) +{ +	int len = strlen(keyname); + +	/* does the key match? */ +	if (strncmp(line, keyname, len)) +		return NULL; + +	/* skip keyname & any whitespace */ +	line += len; +	while(isspace(*line)) +		line++; + +	/* should be the '=' sign */ +	if (*line != '=') +		return 0; + +	/* more whitespace skipping */ +	line++; +	while(isspace(*line)) +		line++; + +	/* finally, return the value */ +	return line; +} + +int dvbsec_cfg_load(FILE *f, +		    void *arg, +		    dvbsec_cfg_callback cb) +{ +	struct dvbsec_config tmpsec; +	char *linebuf = NULL; +	size_t line_size = 0; +	int len; +	int insection = 0; +	char *value; + +	/* process each line */ +	while((len = getline(&linebuf, &line_size, f)) > 0) { +		char *line = linebuf; + +		/* chop any comments */ +		char *hashpos = strchr(line, '#'); +		if (hashpos) +			*hashpos = 0; +		char *lineend = line + strlen(line); + +		/* trim the line */ +		while(*line && isspace(*line)) +			line++; +		while((lineend != line) && isspace(*(lineend-1))) +			lineend--; +		*lineend = 0; + +		/* skip blank lines */ +		if (*line == 0) +			continue; + +		if (dvbcfg_issection(line, "sec")) { +			if (insection) { +				if (cb(arg, &tmpsec)) +					return 0; +			} +			insection = 1; +			memset(&tmpsec, 0, sizeof(tmpsec)); + +		} else if ((value = dvbcfg_iskey(line, "name")) != NULL) { +			strncpy(tmpsec.id, value, sizeof(tmpsec.id)); +		} else if ((value = dvbcfg_iskey(line, "switch-frequency")) != NULL) { +			tmpsec.switch_frequency = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-lo-v")) != NULL) { +			tmpsec.lof_lo_v = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-lo-h")) != NULL) { +			tmpsec.lof_lo_h = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-lo-l")) != NULL) { +			tmpsec.lof_lo_l = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-lo-r")) != NULL) { +			tmpsec.lof_lo_r = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-hi-v")) != NULL) { +			tmpsec.lof_hi_v = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-hi-h")) != NULL) { +			tmpsec.lof_hi_h = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-hi-l")) != NULL) { +			tmpsec.lof_hi_l = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "lof-hi-r")) != NULL) { +			tmpsec.lof_hi_r = atoi(value); +		} else if ((value = dvbcfg_iskey(line, "config-type")) != NULL) { +			if (!strcasecmp(value, "none")) { +				tmpsec.config_type = DVBSEC_CONFIG_NONE; +			} else if (!strcasecmp(value, "power")) { +				tmpsec.config_type = DVBSEC_CONFIG_POWER; +			} else if (!strcasecmp(value, "standard")) { +				tmpsec.config_type = DVBSEC_CONFIG_STANDARD; +			} else if (!strcasecmp(value, "advanced")) { +				tmpsec.config_type = DVBSEC_CONFIG_ADVANCED; +			} else { +				insection = 0; +			} +		} else if ((value = dvbcfg_iskey(line, "cmd-lo-v")) != NULL) { +			strncpy(tmpsec.adv_cmd_lo_v, value, sizeof(tmpsec.adv_cmd_lo_v)); +		} else if ((value = dvbcfg_iskey(line, "cmd-lo-h")) != NULL) { +			strncpy(tmpsec.adv_cmd_lo_h, value, sizeof(tmpsec.adv_cmd_lo_h)); +		} else if ((value = dvbcfg_iskey(line, "cmd-lo-r")) != NULL) { +			strncpy(tmpsec.adv_cmd_lo_r, value, sizeof(tmpsec.adv_cmd_lo_r)); +		} else if ((value = dvbcfg_iskey(line, "cmd-lo-l")) != NULL) { +			strncpy(tmpsec.adv_cmd_lo_l, value, sizeof(tmpsec.adv_cmd_lo_l)); +		} else if ((value = dvbcfg_iskey(line, "cmd-hi-v")) != NULL) { +			strncpy(tmpsec.adv_cmd_hi_v, value, sizeof(tmpsec.adv_cmd_hi_v)); +		} else if ((value = dvbcfg_iskey(line, "cmd-hi-h")) != NULL) { +			strncpy(tmpsec.adv_cmd_hi_h, value, sizeof(tmpsec.adv_cmd_hi_h)); +		} else if ((value = dvbcfg_iskey(line, "cmd-hi-r")) != NULL) { +			strncpy(tmpsec.adv_cmd_hi_r, value, sizeof(tmpsec.adv_cmd_hi_r)); +		} else if ((value = dvbcfg_iskey(line, "cmd-hi-l")) != NULL) { +			strncpy(tmpsec.adv_cmd_hi_l, value, sizeof(tmpsec.adv_cmd_hi_l)); +		} else { +			insection = 0; +		} +	} + +	// output the final section if there is one +	if (insection) { +		if (cb(arg, &tmpsec)) +			return 0; +	} + +	if (linebuf) +		free(linebuf); +	return 0; +} + +static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec); +static int dvbsec_cfg_find_default(const char *sec_id, struct dvbsec_config *sec); + +struct findparams { +	const char *sec_id; +	struct dvbsec_config *sec_dest; +}; + +int dvbsec_cfg_find(const char *config_file, +		    const char *sec_id, +		    struct dvbsec_config *sec) +{ +	struct findparams findp; + +	// clear the structure +	memset(sec, 0, sizeof(struct dvbsec_config)); + +	// open the file +	if (config_file != NULL) { +		FILE *f = fopen(config_file, "r"); +		if (f == NULL) +			return -EIO; + +		// parse each entry +		findp.sec_id = sec_id; +		findp.sec_dest = sec; +		dvbsec_cfg_load(f, &findp, dvbsec_cfg_find_callback); + +		// done +		fclose(f); + +		// find it? +		if (sec->id[0]) +			return 0; +	} + +	return dvbsec_cfg_find_default(sec_id, sec); +} + +static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec) +{ +	struct findparams *findp = arg; + +	if (strcmp(findp->sec_id, sec->id)) +		return 0; + +	memcpy(findp->sec_dest, sec, sizeof(struct dvbsec_config)); +	return 1; +} + +int dvbsec_cfg_save(FILE *f, +		    struct dvbsec_config *secs, +		    int count) +{ +	int i; + +	for(i=0; i<count; i++) { +		char *config_type = ""; +		switch(secs[i].config_type) { +		case DVBSEC_CONFIG_NONE: +			config_type = "none"; +			break; +		case DVBSEC_CONFIG_POWER: +			config_type = "power"; +			break; +		case DVBSEC_CONFIG_STANDARD: +			config_type = "standard"; +			break; +		case DVBSEC_CONFIG_ADVANCED: +			config_type = "advanced"; +			break; +		} + +		fprintf(f, "[lnb]\n"); +		fprintf(f, "switch-frequency=%i\n", secs[i].switch_frequency); +		if (secs[i].lof_lo_v) +			fprintf(f, "lof-lo-v=%i\n", secs[i].lof_lo_v); +		if (secs[i].lof_lo_h) +			fprintf(f, "lof-lo-h=%i\n", secs[i].lof_lo_h); +		if (secs[i].lof_lo_l) +			fprintf(f, "lof-lo-l=%i\n", secs[i].lof_lo_l); +		if (secs[i].lof_lo_r) +			fprintf(f, "lof-lo-r=%i\n", secs[i].lof_lo_r); +		if (secs[i].lof_hi_v) +			fprintf(f, "lof-hi-v=%i\n", secs[i].lof_hi_v); +		if (secs[i].lof_hi_h) +			fprintf(f, "lof-hi-h=%i\n", secs[i].lof_hi_h); +		if (secs[i].lof_hi_l) +			fprintf(f, "lof-hi-l=%i\n", secs[i].lof_hi_l); +		if (secs[i].lof_hi_r) +			fprintf(f, "lof-hi-r=%i\n", secs[i].lof_hi_r); +		fprintf(f, "config-type=%s\n", config_type); + +		if (secs[i].config_type == DVBSEC_CONFIG_ADVANCED) { +			if (secs[i].adv_cmd_lo_h[0]) +				fprintf(f, "cmd-lo-h=%s\n", secs[i].adv_cmd_lo_h); +			if (secs[i].adv_cmd_lo_v[0]) +				fprintf(f, "cmd-lo-v=%s\n", secs[i].adv_cmd_lo_v); +			if (secs[i].adv_cmd_lo_r[0]) +				fprintf(f, "cmd-lo-r=%s\n", secs[i].adv_cmd_lo_r); +			if (secs[i].adv_cmd_lo_l[0]) +				fprintf(f, "cmd-lo-l=%s\n", secs[i].adv_cmd_lo_l); +			if (secs[i].adv_cmd_hi_h[0]) +				fprintf(f, "cmd-hi-h=%s\n", secs[i].adv_cmd_hi_h); +			if (secs[i].adv_cmd_hi_v[0]) +				fprintf(f, "cmd-hi-v=%s\n", secs[i].adv_cmd_hi_v); +			if (secs[i].adv_cmd_hi_r[0]) +				fprintf(f, "cmd-hi-r=%s\n", secs[i].adv_cmd_hi_r); +			if (secs[i].adv_cmd_hi_l[0]) +				fprintf(f, "cmd-hi-l=%s\n", secs[i].adv_cmd_hi_l); +		} + +		fprintf(f, "\n"); +	} + +	return 0; +} + +static struct dvbsec_config defaults[] = { + +	{ +		.id = "NULL", +		.config_type = DVBSEC_CONFIG_STANDARD, +	}, +	{ +		.id = "UNIVERSAL", +		.switch_frequency = 11700000, +		.lof_lo_v = 9750000, +		.lof_lo_h = 9750000, +		.lof_hi_v = 10600000, +		.lof_hi_h = 10600000, +		.config_type = DVBSEC_CONFIG_STANDARD, +	}, +	{ +		.id = "DBS", +		.switch_frequency = 0, +		.lof_lo_v = 11250000, +		.lof_lo_h = 11250000, +		.config_type = DVBSEC_CONFIG_STANDARD, +	}, +	{ +		.id = "STANDARD", +		.switch_frequency = 0, +		.lof_lo_v = 10000000, +		.lof_lo_h = 10000000, +		.config_type = DVBSEC_CONFIG_STANDARD, +	}, +	{ +		.id = "ENHANCED", +		.switch_frequency = 0, +		.lof_lo_v = 9750000, +		.lof_lo_h = 9750000, +		.config_type = DVBSEC_CONFIG_STANDARD, +	}, +	{ +		.id = "C-BAND", +		.switch_frequency = 0, +		.lof_lo_v = 5150000, +		.lof_lo_h = 5150000, +		.config_type = DVBSEC_CONFIG_POWER, +	}, +	{ +		.id = "C-MULTI", +		.switch_frequency = 0, +		.lof_lo_v = 5150000, +		.lof_lo_h = 5750000, +		.config_type = DVBSEC_CONFIG_POWER, +	}, +}; +#define defaults_count (sizeof(defaults) / sizeof(struct dvbsec_config)) + +static int dvbsec_cfg_find_default(const char *sec_id, +				   struct dvbsec_config *sec) +{ +	unsigned int i; + +	for(i=0; i< defaults_count; i++) { +		if (!strncmp(sec_id, defaults[i].id, sizeof(defaults[i].id))) { +			memcpy(sec, &defaults[i], sizeof(struct dvbsec_config)); +			return 0; +		} +	} + +	return -1; +} diff --git a/lib/libdvbsec/dvbsec_cfg.h b/lib/libdvbsec/dvbsec_cfg.h new file mode 100644 index 0000000..d4546de --- /dev/null +++ b/lib/libdvbsec/dvbsec_cfg.h @@ -0,0 +1,203 @@ +/** + * dvbsec_cfg (i.e. linuxtv SEC format) configuration file support. + * + * Copyright (c) 2006 by 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA + */ + +/** + * This library allows SEC (Satellite Equipment Control) configurations + * to be retrieved. Each configuration is identified by a unique satellite_id. + * + * In order to make things as easy as possible for users, there are a set of + * defaults hardcoded into the library covering the majority of LNB types. When + * these are used, the standard back-compatable sequence defined in the DISEQC + * standard will be used - this will suffice for _most_ situations. + * + * UNIVERSAL - Europe, 10800 to 11800 MHz and 11600 to 12700 Mhz, Dual LO, loband 9750, hiband 10600 MHz. + * DBS - Expressvu, North America, 12200 to 12700 MHz, Single LO, 11250 MHz. + * STANDARD - 10945 to 11450 Mhz, Single LO, 10000Mhz. + * ENHANCED - Astra, 10700 to 11700 MHz, Single LO, 9750MHz. + * C-BAND - Big Dish, 3700 to 4200 MHz, Single LO, 5150Mhz. + * C-MULTI - Big Dish - Multipoint LNBf, 3700 to 4200 MHz, Dual LO, H:5150MHz, V:5750MHz. + * + * However, for the power user with a more complex setup, these simple defaults + * are not enough. Therefore, it is also possible to define additional SEC + * configurations in an external configuration file. This file consists of multiple + * entries in the following format: + * + * [sec] + * name=<sec_id> + * switch-frequency=<switching frequency (SLOF)> + * lof-lo-v=<low band + V + frequency> + * lof-lo-h=<low band + H + frequency> + * lof-lo-l=<low band + L + frequency> + * lof-lo-r=<low band + R + frequency> + * lof-hi-v=<high band + V + frequency> + * lof-hi-h=<high band + H + frequency> + * lof-hi-l=<high band + L + frequency> + * lof-hi-r=<high band + R + frequency> + * config-type=<none|power|standard|advanced> + * cmd-lo-v=<sec sequence> + * cmd-lo-h=<sec sequence> + * cmd-lo-r=<sec sequence> + * cmd-lo-l=<sec sequence> + * cmd-hi-v=<sec sequence> + * cmd-hi-h=<sec sequence> + * cmd-hi-r=<sec sequence> + * cmd-hi-l=<sec sequence> + * + * The sec_id is whatever unique value you wish. If it is the same as one of the hardcoded defaults, the configuration + * 	details from the file will be used instead of the hardcoded ones. + * The switch-frequency (or SLOF) indicates the point seperating low band frequencies from high band frequencies. + * 	Set this value to 0 if there is only one frequency band. + * The lof-lo-v is the frequency adjustment for V + low band (i.e. less than SLOF), or is used if switch-frequency==0. + * The lof-lo-h is the frequency adjustment for H + low band (i.e. less than SLOF), or is used if switch-frequency==0. + * The lof-lo-l is the frequency adjustment for L + low band (i.e. less than SLOF), or is used if switch-frequency==0. + * The lof-lo-r is the frequency adjustment for R + low band (i.e. less than SLOF), or is used if switch-frequency==0. + * The lof-hi-v is the frequency adjustment for V + high band (unused if switch-frequency==0). + * The lof-hi-h is the frequency adjustment for H + high band (unused if switch-frequency==0). + * The lof-hi-l is the frequency adjustment for L + high band (unused if switch-frequency==0). + * The lof-hi-r is the frequency adjustment for R + high band (unused if switch-frequency==0). + * + * config-type indicates the desired type of SEC command to use, it may be: + * 	none - No SEC commands will be issued (frequency adjustment will still be performed). + * 	power - Only the SEC power is turned on. + * 	standard - The standard DISEQC back compatable sequence will be issued. + * 	advanced - The DISEQC sequence described in the appropriate sec cmd string will be used. + * + * The cmd-<lo|hi>-<v|h|l|r> describes the SEC cmd string to use in advanced mode for each of the possible combinations of + * frequency band and polarisation. If a certain combination is not required, it may be omitted. It consists of a + * space seperated combination of commands - those available are as follows: + * + *	tone(<0|1>)  - control the 22kHz tone 0:off, 1:on + *	voltage(<0|13|18>) - control the LNB voltage 0v, 13v, or 18v + * 	toneburst(<a|b>) - issue a toneburst (mini command) for position A or B. + *	highvoltage(<0|1>) - control high lnb voltage for long cable runs 0: normal, 1:add 1v to LNB voltage. + *	dishnetworks(<integer>) - issue a dishnetworks legacy command. + *	wait(<integer>) - wait for the given number of milliseconds. + *	Dreset(<address>, <0|1>) - control the reset state of a DISEC device, 0:disable reset, 1:enable reset. + *	Dpower(<address>, <0|1>) - control the power of a DISEC device, 0:off, 1:on. + *	Dcommitted(<address>, <h|l|x>, <v|h|l|r|x>, <a|b|x>, <a|b|x>) - Write to the committed switches of a DISEC device. + * 		The parameters are for band, polarisation, satelliteposition, switchoption: + * 			band - h:high band, l:low band + * 			polarisation - v: vertical, h:horizontal,r:right,l:left + * 			satelliteposition - a:position A, b: position B + * 			switchoption - a:position A, b: position B + * 		The special value 'x' means "no change to this switch". + * + *	Duncommitted(<address>, <a|b|x>, <a|b|x>, <a|b|x>, <a|b|x>) - Write to the uncommitted switches of the a DISEC device. + * 		The parameters are for switch1, switch2, switch3, switch4, and may be set to position a or b. + * 		The special value 'x' means "no change to this switch". + * + * 	Dfrequency(<address>, <frequency in GHz>) - set the frequency of a DISEC device. + * 	Dchannel(<address>, <channel id>) - set the desired channel id of a DISEC device. + * 	Dgotopreset(<address>, <preset id>) - tell a DISEC satellite positioner to move to the given preset id. + * 	Dgotobearing(<address>, <bearing in degrees>) - tell a DISEQC terrestrial rotator to go to the + *		given bearing (range -256.0 -> 512.0 degrees, fractions allowed). + * + * 	In the above DISEQC commands, <address> is the integer (normally in hex format) address of the + * 		diseqc device to communicate with. A list of possiblities is as follows: + * + * 	DISEQC_ADDRESS_ANY_DEVICE		= 0x00 + * + *	DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV	= 0x10 + *	DISEQC_ADDRESS_LNB			= 0x11 + *	DISEQC_ADDRESS_LNB_WITH_LOOP		= 0x12 + *	DISEQC_ADDRESS_SWITCHER			= 0x14 + *	DISEQC_ADDRESS_SWITCHER_WITH_LOOP	= 0x15 + *	DISEQC_ADDRESS_SMATV			= 0x18 + * + *	DISEQC_ADDRESS_ANY_POLARISER		= 0x20 + *	DISEQC_ADDRESS_LINEAR_POLARISER		= 0x21 + * + *	DISEQC_ADDRESS_ANY_POSITIONER		= 0x30 + *	DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER	= 0x31 + *	DISEQC_ADDRESS_ELEVATION_POSITIONER	= 0x32 + * + *	DISEQC_ADDRESS_ANY_INSTALLER_AID	= 0x40 + *	DISEQC_ADDRESS_SIGNAL_STRENGTH		= 0x41 + * + *	DISEQC_ADDRESS_ANY_INTERFACE		= 0x70 + *	DISEQC_ADDRESS_HEADEND_INTERFACE	= 0x71 + * + *	DISEQC_ADDRESS_REALLOC_BASE		= 0x60 + *	DISEQC_ADDRESS_OEM_BASE			= 0xf0 + */ + +#ifndef DVBSEC_CFG_H +#define DVBSEC_CFG_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdio.h> +#include <stdint.h> +#include <libdvbsec/dvbsec_api.h> + +/** + * Callback function used in dvbsec_cfg_load(). + * + * @param arg Private information to caller. + * @param channel The current channel details. + * @return 0 to continue, 1 to stop loading. + */ +typedef int (*dvbsec_cfg_callback)(void *arg, struct dvbsec_config *sec); + +/** + * Load an SEC file. + * + * @param f File to load from. + * @param arg Value to pass to 'arg' in callback above. + * @param cb Callback function called for each sec loaded from the file. + * @return 0 on success, or nonzero error code on failure. + */ +extern int dvbsec_cfg_load(FILE *f, void *arg, +			   dvbsec_cfg_callback cb); + +/** + * Convenience function to parse an SEC config file. This will also consult the set + * of hardcoded defaults if no config file was supplied, or a match was not found in + * the config file. + * + * @param config_file Config filename to load, or NULL to just check defaults. + * @param sec_id ID of SEC configuration. + * @param sec Where to put the details if found. + * @return 0 on success, nonzero on error. + */ +extern int dvbsec_cfg_find(const char *config_file, +			   const char *sec_id, +			   struct dvbsec_config *sec); + +/** + * Save SEC format config file. + * + * @param f File to save to. + * @param secs Pointer to array of SECs to save. + * @param count Number of entries in the above array. + * @return 0 on success, or nonzero error code on failure. + */ +extern int dvbsec_cfg_save(FILE *f, +			   struct dvbsec_config *secs, +			   int count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/Makefile b/lib/libesg/Makefile new file mode 100644 index 0000000..abb9d4f --- /dev/null +++ b/lib/libesg/Makefile @@ -0,0 +1,27 @@ +# Makefile for linuxtv.org dvb-apps/lib/libesg + +includes = types.h + +objects  = types.o + +lib_name = libesg + +CPPFLAGS += -I../../lib + +.PHONY: all + +all: library + +include bootstrap/Makefile +include encapsulation/Makefile +include representation/Makefile +include transport/Makefile + +.PHONY: $(sub-install) + +install:: $(sub-install) + +$(sub-install): +	$(MAKE) -C $@ install + +include ../../Make.rules diff --git a/lib/libesg/TODO b/lib/libesg/TODO new file mode 100644 index 0000000..952215a --- /dev/null +++ b/lib/libesg/TODO @@ -0,0 +1,18 @@ +*** General +- Add enums for constants + +*** EncodingVersion +- GZIP : use zlib +- BiM : ??? + +*** BOOTSTRAP +- ESGProviderDiscoveryDescriptor : XML parsing with libexpat ? + +*** TRANSPORT +- Indexation + +*** ENCAPSULATION +- Auxiliary Data + +*** REPRESENTATION +- BiM Decoder Init diff --git a/lib/libesg/bootstrap/Makefile b/lib/libesg/bootstrap/Makefile new file mode 100644 index 0000000..16a2457 --- /dev/null +++ b/lib/libesg/bootstrap/Makefile @@ -0,0 +1,24 @@ +# Makefile for linuxtv.org dvb-apps/lib/libesg/bootstrap + +.PHONY: sub-error-bootstrap + +sub-error-bootstrap: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += bootstrap/access_descriptor.o \ +           bootstrap/provider_discovery_descriptor.o + +sub-install += bootstrap + +else + +includes = access_descriptor.h \ +           provider_discovery_descriptor.h + +include ../../../Make.rules + +lib_name = libesg/bootstrap + +endif diff --git a/lib/libesg/bootstrap/access_descriptor.c b/lib/libesg/bootstrap/access_descriptor.c new file mode 100644 index 0000000..e8f89a3 --- /dev/null +++ b/lib/libesg/bootstrap/access_descriptor.c @@ -0,0 +1,115 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/bootstrap/access_descriptor.h> + +struct esg_access_descriptor *esg_access_descriptor_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_access_descriptor *access_descriptor; +	struct esg_entry *entry; +	struct esg_entry *last_entry; +	uint32_t entry_length; +	uint16_t entry_index; +	uint8_t ip_index; + +	if ((buffer == NULL) || (size <= 2)) { +		return NULL; +	} + +	pos = 0; + +	access_descriptor = (struct esg_access_descriptor *) malloc(sizeof(struct esg_access_descriptor)); +	memset(access_descriptor, 0, sizeof(struct esg_access_descriptor)); +	access_descriptor->entry_list = NULL; + +	access_descriptor->n_o_entries = (buffer[pos] << 8) | buffer[pos+1]; +	pos += 2; + +    last_entry = NULL; +	for (entry_index = 0; entry_index < access_descriptor->n_o_entries; entry_index++) { +		entry = (struct esg_entry *) malloc(sizeof(struct esg_entry)); +		memset(entry, 0, sizeof(struct esg_entry)); +		entry->_next = NULL; + +		if (last_entry == NULL) { +			access_descriptor->entry_list = entry; +		} else { +			last_entry->_next = entry; +		} +		last_entry = entry; + +		entry->version = buffer[pos]; +		pos += 1; + +		pos += vluimsbf8(buffer + pos, size - pos, &entry_length); + +		if (size < pos + entry_length) { +			esg_access_descriptor_free(access_descriptor); +			return NULL; +		} + +		entry->multiple_stream_transport = (buffer[pos] & 0x80) ? 1 : 0; +		entry->ip_version_6 = (buffer[pos] & 0x40) ? 1 : 0; +		pos += 1; + +		entry->provider_id = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		if (entry->ip_version_6) { +			for (ip_index = 0; ip_index < 16; ip_index++) { +				entry->source_ip.ipv6[ip_index] = buffer[pos+ip_index]; +				entry->destination_ip.ipv6[ip_index] = buffer[pos+16+ip_index]; +			} +			pos += 32; +		} else { +			for (ip_index = 0; ip_index < 4; ip_index++) { +				entry->source_ip.ipv4[ip_index] = buffer[pos+ip_index]; +				entry->destination_ip.ipv4[ip_index] = buffer[pos+4+ip_index]; +			} +			pos += 8; +		} +		entry->port = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		entry->tsi = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; +	} + +	return access_descriptor; +} + +void esg_access_descriptor_free(struct esg_access_descriptor *access_descriptor) { +	struct esg_entry *entry; +	struct esg_entry *next_entry; + +	if (access_descriptor == NULL) { +		return; +    } + +	for(entry = access_descriptor->entry_list; entry; entry = next_entry) { +		next_entry = entry->_next; +		free(entry); +	} + +	free(access_descriptor); +} diff --git a/lib/libesg/bootstrap/access_descriptor.h b/lib/libesg/bootstrap/access_descriptor.h new file mode 100644 index 0000000..49aec46 --- /dev/null +++ b/lib/libesg/bootstrap/access_descriptor.h @@ -0,0 +1,86 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_BOOTSTRAP_ACCESS_DESCRIPTOR_H +#define _ESG_BOOTSTRAP_ACCESS_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libesg/types.h> + +/** + * esg_entry structure. + */ +struct esg_entry { +	uint8_t version; +	uint8_t multiple_stream_transport; +	uint8_t ip_version_6; +	uint16_t provider_id; +	union esg_ip_address source_ip; +	union esg_ip_address destination_ip; +	uint16_t port; +	uint16_t tsi; + +	struct esg_entry *_next; +}; + +/** + * esg_access_descriptor structure. + */ +struct esg_access_descriptor { +	uint16_t n_o_entries; +	struct esg_entry *entry_list; +}; + +/** + * Process an esg_access_descriptor. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_access_descriptor structure, or NULL on error. + */ +extern struct esg_access_descriptor *esg_access_descriptor_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_access_descriptor. + * + * @param esg Pointer to an esg_access_descriptor structure. + */ +extern void esg_access_descriptor_free(struct esg_access_descriptor *access_descriptor); + +/** + * Convenience iterator for esg_entry_list field of an esg_access_descriptor. + * + * @param access_descriptor The esg_access_descriptor pointer. + * @param entry Variable holding a pointer to the current esg_entry. + */ +#define esg_access_descriptor_entry_list_for_each(access_descriptor, entry) \ +	for ((entry) = (access_descriptor)->entry_list; \ +	     (entry); \ +	     (entry) = (entry)->_next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/bootstrap/provider_discovery_descriptor.c b/lib/libesg/bootstrap/provider_discovery_descriptor.c new file mode 100644 index 0000000..833a038 --- /dev/null +++ b/lib/libesg/bootstrap/provider_discovery_descriptor.c @@ -0,0 +1,50 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/bootstrap/provider_discovery_descriptor.h> + +struct esg_provider_discovery_descriptor *esg_esg_provider_discovery_descriptor_decode(uint8_t *buffer, uint32_t size) { +	struct esg_provider_discovery_descriptor *provider; + +	provider = (struct esg_provider_discovery_descriptor *) malloc(sizeof(struct esg_provider_discovery_descriptor)); +	memset(provider, 0, sizeof(struct esg_provider_discovery_descriptor)); + +	provider->xml = (uint8_t *) malloc(size); +	memcpy(provider->xml, buffer, size); + +	provider->size = size; + +	return provider; +} + +void esg_provider_discovery_descriptor_free(struct esg_provider_discovery_descriptor *provider) { +	if (provider == NULL) { +		return; +	} + +	if (provider->xml) { +		free(provider->xml); +	} + +	free(provider); +} diff --git a/lib/libesg/bootstrap/provider_discovery_descriptor.h b/lib/libesg/bootstrap/provider_discovery_descriptor.h new file mode 100644 index 0000000..36065ec --- /dev/null +++ b/lib/libesg/bootstrap/provider_discovery_descriptor.h @@ -0,0 +1,59 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_BOOTSTRAP_PROVIDER_DISCOVERY_DESCRIPTOR_H +#define _ESG_BOOTSTRAP_PROVIDER_DISCOVERY_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_provider_discovery_descriptor structure. + */ +struct esg_provider_discovery_descriptor { +	uint8_t *xml; +	uint32_t size; +}; + +/** + * Process an esg_provider_discovery_descriptor. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_provider_discovery_descriptor structure, or NULL on error. + */ +extern struct esg_provider_discovery_descriptor *esg_esg_provider_discovery_descriptor_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_provider_discovery_descriptor. + * + * @param esg Pointer to an esg_provider_discovery_descriptor structure. + */ +extern void esg_provider_discovery_descriptor_free(struct esg_provider_discovery_descriptor *provider); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/encapsulation/Makefile b/lib/libesg/encapsulation/Makefile new file mode 100644 index 0000000..2f222ed --- /dev/null +++ b/lib/libesg/encapsulation/Makefile @@ -0,0 +1,28 @@ +# Makefile for linuxtv.org dvb-apps/lib/libesg/encapsulation + +.PHONY: sub-error-encapsulation + +sub-error-encapsulation: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += encapsulation/container.o \ +           encapsulation/fragment_management_information.o \ +           encapsulation/data_repository.o \ +           encapsulation/string_repository.o + +sub-install += encapsulation + +else + +includes = container.h \ +           fragment_management_information.h \ +           data_repository.h \ +           string_repository.h + +include ../../../Make.rules + +lib_name = libesg/encapsulation + +endif diff --git a/lib/libesg/encapsulation/auxiliary_data.h b/lib/libesg/encapsulation/auxiliary_data.h new file mode 100644 index 0000000..e05b241 --- /dev/null +++ b/lib/libesg/encapsulation/auxiliary_data.h @@ -0,0 +1,62 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_ENCAPSULATION_AUXILIARY_DATA_H +#define _ESG_ENCAPSULATION_AUXILIARY_DATA_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_any_attribute structure. + */ +struct esg_any_attribute { +	uint8_t version_id; +	uint8_t *extension; + +	struct esg_any_attribure *_next; +}; + +/** + * esg_binary_header structure. + */ +struct esg_binary_header { +	uint16_t encoding_metadatauri_mimetype; +	struct esg_any_attribute *any_attribute_list; +}; + +/** + * esg_encapsulated_aux_data struct. + */ +struct esg_encapsulated_aux_data { +	struct esg_binary_header *binary_header; +	uint32_t aux_data_length; +	uint8_t aux_data; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/encapsulation/container.c b/lib/libesg/encapsulation/container.c new file mode 100644 index 0000000..15b17bf --- /dev/null +++ b/lib/libesg/encapsulation/container.c @@ -0,0 +1,206 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/encapsulation/container.h> +#include <libesg/encapsulation/fragment_management_information.h> +#include <libesg/encapsulation/data_repository.h> +#include <libesg/encapsulation/string_repository.h> +#include <libesg/representation/init_message.h> +#include <libesg/transport/session_partition_declaration.h> + +struct esg_container *esg_container_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_container *container; +	struct esg_container_structure *structure; +	struct esg_container_structure *last_structure; +	uint8_t structure_index; + +	if ((buffer == NULL) || (size <= 1)) { +		return NULL; +	} + +	pos = 0; + +	container = (struct esg_container *) malloc(sizeof(struct esg_container)); +	memset(container, 0, sizeof(struct esg_container)); + +	// Container header +	container->header = (struct esg_container_header *) malloc(sizeof(struct esg_container_header)); +	memset(container->header, 0, sizeof(struct esg_container_header)); + +	container->header->num_structures = buffer[pos]; +	pos += 1; + +	if (size < pos + (container->header->num_structures * 8)) { +		esg_container_free(container); +		return NULL; +	} + +	last_structure = NULL; +	for (structure_index = 0; structure_index < container->header->num_structures; structure_index++) { +		structure = (struct esg_container_structure *) malloc(sizeof(struct esg_container_structure)); +		memset(structure, 0, sizeof(struct esg_container_structure)); +		structure->_next = NULL; + +		if (last_structure == NULL) { +			container->header->structure_list = structure; +		} else { +			last_structure->_next = structure; +		} +		last_structure = structure; + +		structure->type = buffer[pos]; +		pos += 1; + +		structure->id = buffer[pos]; +		pos += 1; + +		structure->ptr = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2]; +		pos += 3; + +		structure->length = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2]; +		pos += 3; + +		if (size < (structure->ptr + structure->length)) { +			esg_container_free(container); +			return NULL; +		} + +		// Decode structure +		switch (structure->type) { +			case 0x01: { +				switch (structure->id) { +					case 0x00: { +						structure->data = (void *) esg_encapsulation_structure_decode(buffer + structure->ptr, structure->length); +						break; +					} +					default: { +						esg_container_free(container); +						return NULL; +					} +				} +				break; +			} +			case 0x02: { +				switch (structure->id) { +					case 0x00: { +						structure->data = (void *) esg_string_repository_decode(buffer + structure->ptr, structure->length); +						break; +					} +					default: { +						esg_container_free(container); +						return NULL; +					} +				} +				break; +			} +			case 0x03: { +				//TODO +				break; +			} +			case 0x04: { +				//TODO +				break; +			} +			case 0x05: { +				//TODO +				break; +			} +			case 0xE0: { +				switch (structure->id) { +					case 0x00: { +						structure->data = (void *) esg_data_repository_decode(buffer + structure->ptr, structure->length); +						break; +					} +					default: { +						esg_container_free(container); +						return NULL; +					} +				} +				break; +			} +			case 0xE1: { +				switch (structure->id) { +					case 0xFF: { +						structure->data = (void *) esg_session_partition_declaration_decode(buffer + structure->ptr, structure->length); +						break; +					} +					default: { +						esg_container_free(container); +						return NULL; +					} +				} +				break; +			} +			case 0xE2: { +				switch (structure->id) { +					case 0x00: { +						structure->data = (void *) esg_init_message_decode(buffer + structure->ptr, structure->length); +						break; +					} +					default: { +						esg_container_free(container); +						return NULL; +					} +				} +				break; +			} +			default: { +				esg_container_free(container); +				return NULL; +			} +		} +	} + +	// Container structure body +	container->structure_body_ptr = pos; +	container->structure_body_length = size - pos; +	container->structure_body = (uint8_t *) malloc(size - pos); +	memcpy(container->structure_body, buffer + pos, size - pos); + +	return container; +} + +void esg_container_free(struct esg_container *container) { +	struct esg_container_structure *structure; +	struct esg_container_structure *next_structure; + +	if (container == NULL) { +		return; +    } + +	if (container->header) { +		for(structure = container->header->structure_list; structure; structure = next_structure) { +			next_structure = structure->_next; +			free(structure); +		} + +		free(container->header); +	} + +	if (container->structure_body) { +		free(container->structure_body); +	} + +	free(container); +} diff --git a/lib/libesg/encapsulation/container.h b/lib/libesg/encapsulation/container.h new file mode 100644 index 0000000..dc54ef2 --- /dev/null +++ b/lib/libesg/encapsulation/container.h @@ -0,0 +1,94 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_ENCAPSULATION_CONTAINER_H +#define _ESG_ENCAPSULATION_CONTAINER_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_container_structure structure. + */ +struct esg_container_structure { +	uint8_t type; +	uint8_t id; +	uint32_t ptr; +	uint32_t length; + +	void *data; + +	struct esg_container_structure *_next; +}; + +/** + * esg_container_header structure. + */ +struct esg_container_header { +	uint8_t num_structures; +	struct esg_container_structure *structure_list; +}; + +/** + * esg_container structure + */ +struct esg_container { +	struct esg_container_header *header; +	uint32_t structure_body_ptr; +	uint32_t structure_body_length; +	uint8_t *structure_body; +}; + +/** + * Process an esg_container. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_container structure, or NULL on error. + */ +extern struct esg_container *esg_container_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_container. + * + * @param container Pointer to an esg_container structure. + */ +extern void esg_container_free(struct esg_container *container); + +/** + * Convenience iterator for structure_list field of an esg_container_header. + * + * @param container The esg_container_header pointer. + * @param structure Variable holding a pointer to the current esg_container_structure. + */ +#define esg_container_header_structure_list_for_each(header, structure) \ +	for ((structure) = (header)->structure_list; \ +	     (structure); \ +	     (structure) = (structure)->_next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/encapsulation/data_repository.c b/lib/libesg/encapsulation/data_repository.c new file mode 100644 index 0000000..629e5ea --- /dev/null +++ b/lib/libesg/encapsulation/data_repository.c @@ -0,0 +1,53 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/encapsulation/data_repository.h> + +struct esg_data_repository *esg_data_repository_decode(uint8_t *buffer, uint32_t size) { +	struct esg_data_repository *data_repository; + +	if ((buffer == NULL) || (size <= 0)) { +		return NULL; +	} + +	data_repository = (struct esg_data_repository *) malloc(sizeof(struct esg_data_repository)); +	memset(data_repository, 0, sizeof(struct esg_data_repository)); + +	data_repository->length = size; +	data_repository->data = (uint8_t *) malloc(size); +	memcpy(data_repository->data, buffer, size); + +	return data_repository; +} + +void esg_data_repository_free(struct esg_data_repository *data_repository) { +	if (data_repository == NULL) { +		return; +	} + +	if (data_repository->data) { +		free(data_repository->data); +	} + +	free(data_repository); +} diff --git a/lib/libesg/encapsulation/data_repository.h b/lib/libesg/encapsulation/data_repository.h new file mode 100644 index 0000000..4c691cf --- /dev/null +++ b/lib/libesg/encapsulation/data_repository.h @@ -0,0 +1,59 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_ENCAPSULATION_DATA_REPOSITORY_H +#define _ESG_ENCAPSULATION_DATA_REPOSITORY_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_data_repository structure. + */ +struct esg_data_repository { +	uint32_t length; +	uint8_t *data; +}; + +/** + * Process an esg_data_repository. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_data_repository structure, or NULL on error. + */ +extern struct esg_data_repository *esg_data_repository_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_data_repository. + * + * @param data_repository Pointer to an esg_data_repository structure. + */ +extern void esg_data_repository_free(struct esg_data_repository *data_repository); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/encapsulation/fragment_management_information.c b/lib/libesg/encapsulation/fragment_management_information.c new file mode 100644 index 0000000..b08265d --- /dev/null +++ b/lib/libesg/encapsulation/fragment_management_information.c @@ -0,0 +1,118 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/encapsulation/fragment_management_information.h> + +struct esg_encapsulation_structure *esg_encapsulation_structure_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_encapsulation_structure *structure; +	struct esg_encapsulation_entry *entry; +	struct esg_encapsulation_entry *last_entry; + +	if ((buffer == NULL) || (size <= 2)) { +		return NULL; +	} + +	pos = 0; + +	structure = (struct esg_encapsulation_structure *) malloc(sizeof(struct esg_encapsulation_structure)); +	memset(structure, 0, sizeof(struct esg_encapsulation_structure)); +	structure->entry_list = NULL; + +	// Encapsulation header +	structure->header = (struct esg_encapsulation_header *) malloc(sizeof(struct esg_encapsulation_header)); +	// buffer[pos] reserved +	structure->header->fragment_reference_format = buffer[pos+1]; +	pos += 2; + +	// Encapsulation entry list +	last_entry = NULL; +	while (size > pos) { +		entry = (struct esg_encapsulation_entry *) malloc(sizeof(struct esg_encapsulation_entry)); +		memset(entry, 0, sizeof(struct esg_encapsulation_entry)); +		entry->_next = NULL; + +		if (last_entry == NULL) { +			structure->entry_list = entry; +		} else { +			last_entry->_next = entry; +		} +		last_entry = entry; + +		// Fragment reference +		switch (structure->header->fragment_reference_format) { +			case 0x21: { +				entry->fragment_reference = (struct esg_fragment_reference *) malloc(sizeof(struct esg_fragment_reference)); +				memset(entry->fragment_reference, 0, sizeof(struct esg_fragment_reference)); + +				entry->fragment_reference->fragment_type = buffer[pos]; +				pos += 1; + +				entry->fragment_reference->data_repository_offset = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2]; +				pos += 3; + +				break; +			} +			default: { +				esg_encapsulation_structure_free(structure); +				return NULL; +			} +		} + +		// Fragment version & id +		entry->fragment_version = buffer[pos]; +		pos += 1; + +		entry->fragment_id = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2]; +		pos += 3; +	} + +	return structure; +} + +void esg_encapsulation_structure_free(struct esg_encapsulation_structure *structure) { +	struct esg_encapsulation_entry *entry; +	struct esg_encapsulation_entry *next_entry; + +	if (structure == NULL) { +		return; +    } + +	if (structure->header) { +		free(structure->header); +	} + +	if (structure->entry_list) { +		for(entry = structure->entry_list; entry; entry = next_entry) { +			next_entry = entry->_next; +			if (entry->fragment_reference) { +				free(entry->fragment_reference); +			} +			free(entry); +		} + +		free(structure->entry_list); +	} + +	free(structure); +} diff --git a/lib/libesg/encapsulation/fragment_management_information.h b/lib/libesg/encapsulation/fragment_management_information.h new file mode 100644 index 0000000..04050b5 --- /dev/null +++ b/lib/libesg/encapsulation/fragment_management_information.h @@ -0,0 +1,96 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_ENCAPSULATION_FRAGMENT_MANAGEMENT_INFORMATION_H +#define _ESG_ENCAPSULATION_FRAGMENT_MANAGEMENT_INFORMATION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_encapsulation_header structure. + */ +struct esg_encapsulation_header { +	uint8_t fragment_reference_format; +}; + +/** + * esg_fragment_reference structure. + */ +struct esg_fragment_reference { +	uint8_t fragment_type; +	uint32_t data_repository_offset; +}; + +/** + * esg_encapsulation_entry structure. + */ +struct esg_encapsulation_entry { +	struct esg_fragment_reference *fragment_reference; +	uint8_t fragment_version; +	uint32_t fragment_id; + +	struct esg_encapsulation_entry *_next; +}; + +/** + * esg_encapsulation_structure structure. + */ +struct esg_encapsulation_structure { +	struct esg_encapsulation_header *header; +	struct esg_encapsulation_entry *entry_list; +}; + +/** + * Process an esg_encapsulation_structure. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_encapsulation_structure structure, or NULL on error. + */ +extern struct esg_encapsulation_structure *esg_encapsulation_structure_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_encapsulation_structure. + * + * @param container Pointer to an esg_container structure. + */ +extern void esg_encapsulation_structure_free(struct esg_encapsulation_structure *structure); + +/** + * Convenience iterator for entry_list field of an esg_encapsulation_structure. + * + * @param structure The esg_encapsulation_structure pointer. + * @param entry Variable holding a pointer to the current esg_encapsulation_entry. + */ +#define esg_encapsulation_structure_entry_list_for_each(structure, entry) \ +	for ((entry) = (structure)->entry_list; \ +	     (entry); \ +	     (entry) = (entry)->_next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/encapsulation/string_repository.c b/lib/libesg/encapsulation/string_repository.c new file mode 100644 index 0000000..3b88742 --- /dev/null +++ b/lib/libesg/encapsulation/string_repository.c @@ -0,0 +1,54 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/encapsulation/string_repository.h> + +struct esg_string_repository *esg_string_repository_decode(uint8_t *buffer, uint32_t size) { +	struct esg_string_repository *string_repository; + +	if ((buffer == NULL) || (size <= 1)) { +		return NULL; +	} + +	string_repository = (struct esg_string_repository *) malloc(sizeof(struct esg_string_repository)); +	memset(string_repository, 0, sizeof(struct esg_string_repository)); + +	string_repository->encoding_type = buffer[0]; +	string_repository->length = size-1; +	string_repository->data = (uint8_t *) malloc(size-1); +	memcpy(string_repository->data, buffer+1, size-1); + +	return string_repository; +} + +void esg_string_repository_free(struct esg_string_repository *string_repository) { +	if (string_repository == NULL) { +		return; +	} + +	if (string_repository->data) { +		free(string_repository->data); +	} + +	free(string_repository); +} diff --git a/lib/libesg/encapsulation/string_repository.h b/lib/libesg/encapsulation/string_repository.h new file mode 100644 index 0000000..0cf64c2 --- /dev/null +++ b/lib/libesg/encapsulation/string_repository.h @@ -0,0 +1,60 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_ENCAPSULATION_STRING_REPOSITORY_H +#define _ESG_ENCAPSULATION_STRING_REPOSITORY_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_string_repository structure. + */ +struct esg_string_repository { +	uint8_t encoding_type; +	uint32_t length; +	uint8_t *data; +}; + +/** + * Process an esg_string_repository. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_string_repository structure, or NULL on error. + */ +extern struct esg_string_repository *esg_string_repository_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_string_repository. + * + * @param data_repository Pointer to an esg_string_repository structure. + */ +extern void esg_string_repository_free(struct esg_string_repository *string_repository); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/representation/Makefile b/lib/libesg/representation/Makefile new file mode 100644 index 0000000..059f8bd --- /dev/null +++ b/lib/libesg/representation/Makefile @@ -0,0 +1,26 @@ +# Makefile for linuxtv.org dvb-apps/lib/libesg/representation + +.PHONY: sub-error-representation + +sub-error-representation: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += representation/encapsulated_textual_esg_xml_fragment.o \ +           representation/init_message.o \ +           representation/textual_decoder_init.o + +sub-install += representation + +else + +includes = encapsulated_textual_esg_xml_fragment.h \ +           init_message.h \ +           textual_decoder_init.h + +include ../../../Make.rules + +lib_name = libesg/representation + +endif diff --git a/lib/libesg/representation/bim_decoder_init.h b/lib/libesg/representation/bim_decoder_init.h new file mode 100644 index 0000000..4860da9 --- /dev/null +++ b/lib/libesg/representation/bim_decoder_init.h @@ -0,0 +1,40 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_REPRESENTATION_BIM_DECODER_INIT_H +#define _ESG_REPRESENTATION_BIM_DECODER_INIT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * esg_bim_decoder_init structure. + */ +struct esg_bim_decoder_init { +// TODO +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h b/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h new file mode 100644 index 0000000..8ab39dd --- /dev/null +++ b/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h @@ -0,0 +1,40 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_REPRESENTATION_ENCAPSULATED_BIM_ESG_XML_FRAGMENT_H +#define _ESG_REPRESENTATION_ENCAPSULATED_BIM_ESG_XML_FRAGMENT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * esg_encapsulated_bim_esg_xml_fragment structure. + */ +struct esg_encapsulated_bim_esg_xml_fragment { +	//TODO +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c new file mode 100644 index 0000000..199c857 --- /dev/null +++ b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c @@ -0,0 +1,70 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/types.h> +#include <libesg/representation/encapsulated_textual_esg_xml_fragment.h> + +struct esg_encapsulated_textual_esg_xml_fragment *esg_encapsulated_textual_esg_xml_fragment_decode(uint8_t *buffer, uint32_t size) { +	struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment; +	uint32_t pos; +	uint32_t length; +	uint8_t offset_pos; + +	if ((buffer == NULL) || (size <= 0)) { +		return NULL; +	} + +	pos = 0; + +	esg_xml_fragment = (struct esg_encapsulated_textual_esg_xml_fragment *) malloc(sizeof(struct esg_encapsulated_textual_esg_xml_fragment)); +	memset(esg_xml_fragment, 0, sizeof(struct esg_encapsulated_textual_esg_xml_fragment)); + +	offset_pos = vluimsbf8(buffer+pos+2, size-pos-2, &length); + +	if (size-pos-2 < offset_pos+length) { +		esg_encapsulated_textual_esg_xml_fragment_free(esg_xml_fragment); +		return NULL; +	} + +	esg_xml_fragment->esg_xml_fragment_type = (buffer[pos] << 8) | buffer[pos+1]; +	pos += 2+offset_pos; + +	esg_xml_fragment->data_length = length; +	esg_xml_fragment->data = (uint8_t *) malloc(length); +	memcpy(esg_xml_fragment->data, buffer+pos, length); +	pos += length; + +	return esg_xml_fragment; +} + +void esg_encapsulated_textual_esg_xml_fragment_free(struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment) { +	if (esg_xml_fragment == NULL) { +		return; +	} + +	if (esg_xml_fragment->data) { +		free(esg_xml_fragment->data); +	} + +	free(esg_xml_fragment); +} diff --git a/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h new file mode 100644 index 0000000..ee8aba1 --- /dev/null +++ b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h @@ -0,0 +1,60 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_REPRESENTATION_ENCAPSULATED_TEXTUAL_ESG_XML_FRAGMENT_H +#define _ESG_REPRESENTATION_ENCAPSULATED_TEXTUAL_ESG_XML_FRAGMENT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_encapsulated_textual_esg_xml_fragment structure. + */ +struct esg_encapsulated_textual_esg_xml_fragment { +	uint16_t esg_xml_fragment_type; +	uint32_t data_length; +	uint8_t *data; +}; + +/** + * Process an esg_encapsulated_textual_esg_xml_fragment. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_encapsulated_textual_esg_xml_fragment structure, or NULL on error. + */ +extern struct esg_encapsulated_textual_esg_xml_fragment *esg_encapsulated_textual_esg_xml_fragment_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_encapsulated_textual_esg_xml_fragment. + * + * @param data_repository Pointer to an esg_encapsulated_textual_esg_xml_fragment structure. + */ +extern void esg_encapsulated_textual_esg_xml_fragment_free(struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/representation/init_message.c b/lib/libesg/representation/init_message.c new file mode 100644 index 0000000..0038607 --- /dev/null +++ b/lib/libesg/representation/init_message.c @@ -0,0 +1,112 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/representation/init_message.h> +#include <libesg/representation/textual_decoder_init.h> +#include <libesg/representation/bim_decoder_init.h> + +struct esg_init_message *esg_init_message_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_init_message *init_message; + +	if ((buffer == NULL) || (size <= 3)) { +		return NULL; +	} + +	pos = 0; + +	init_message = (struct esg_init_message *) malloc(sizeof(struct esg_init_message)); +	memset(init_message, 0, sizeof(struct esg_init_message)); + +	init_message->encoding_version = buffer[pos]; +	pos += 1; + +	init_message->indexing_flag = (buffer[pos] & 0x80) >> 7; +	pos += 1; + +	init_message->decoder_init_ptr = buffer[pos]; +	pos += 1; + +	if (init_message->indexing_flag) { +		init_message->indexing_version = buffer[pos]; +		pos += 1; +	} + +	switch (init_message->encoding_version) { +		case 0xF1: { +			struct esg_bim_encoding_parameters *encoding_parameters = (struct esg_bim_encoding_parameters *) malloc(sizeof(struct esg_bim_encoding_parameters)); +			memset(encoding_parameters, 0, sizeof(struct esg_bim_encoding_parameters)); +			init_message->encoding_parameters = (void *) encoding_parameters; + +			encoding_parameters->buffer_size_flag = (buffer[pos] & 0x80) >> 7; +			encoding_parameters->position_code_flag = (buffer[pos] & 0x40) >> 6; +			pos += 1; + +			encoding_parameters->character_encoding = buffer[pos]; +			pos += 1; + +			if (encoding_parameters->buffer_size_flag) { +				encoding_parameters->buffer_size = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2]; +				pos += 3; +			} + +// TODO +//			init_message->decoder_init = (void *) esg_bim_decoder_init_decode(buffer + init_message->decoder_init_ptr, size - init_message->decoder_init_ptr); +			break; +		} +		case 0xF2: +		case 0xF3: { +			struct esg_textual_encoding_parameters *encoding_parameters = (struct esg_textual_encoding_parameters *) malloc(sizeof(struct esg_textual_encoding_parameters)); +			memset(encoding_parameters, 0, sizeof(struct esg_textual_encoding_parameters)); +			init_message->encoding_parameters = (void *) encoding_parameters; + +			encoding_parameters->character_encoding = buffer[pos]; +			pos += 1; + +			init_message->decoder_init = (void *) esg_textual_decoder_init_decode(buffer + init_message->decoder_init_ptr, size - init_message->decoder_init_ptr); +			break; +		} +		default: { +			esg_init_message_free(init_message); +			return NULL; +		} +	} + +	return init_message; +} + +void esg_init_message_free(struct esg_init_message *init_message) { +	if (init_message == NULL) { +		return; +	} + +	if (init_message->encoding_parameters) { +		free(init_message->encoding_parameters); +	} + +	if (init_message->decoder_init) { +		free(init_message->decoder_init); +	} + +	free(init_message); +} diff --git a/lib/libesg/representation/init_message.h b/lib/libesg/representation/init_message.h new file mode 100644 index 0000000..a525495 --- /dev/null +++ b/lib/libesg/representation/init_message.h @@ -0,0 +1,80 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_REPRESENTATION_INIT_MESSAGE_H +#define _ESG_REPRESENTATION_INIT_MESSAGE_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_textual_encoding_parameters structure. + */ +struct esg_textual_encoding_parameters { +	uint8_t character_encoding; +}; + +/** + * esg_bim_encoding_parameters structure. + */ +struct esg_bim_encoding_parameters { +	uint8_t buffer_size_flag; +	uint8_t position_code_flag; +	uint8_t character_encoding; +	uint32_t buffer_size; // if buffer_size_flag +}; + +/** + * esg_init_message structure. + */ +struct esg_init_message { +	uint8_t encoding_version; +	uint8_t indexing_flag; +	uint8_t decoder_init_ptr; +	uint8_t indexing_version; // if indexing_flag +	void *encoding_parameters; +	void *decoder_init; +}; + +/** + * Process an esg_init_message. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_string_repository structure, or NULL on error. + */ +extern struct esg_init_message *esg_init_message_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_init_message. + * + * @param init_message Pointer to an esg_init_message structure. + */ +extern void esg_init_message_free(struct esg_init_message *init_message); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/representation/textual_decoder_init.c b/lib/libesg/representation/textual_decoder_init.c new file mode 100644 index 0000000..c797d0e --- /dev/null +++ b/lib/libesg/representation/textual_decoder_init.c @@ -0,0 +1,128 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/types.h> +#include <libesg/representation/textual_decoder_init.h> + +struct esg_textual_decoder_init *esg_textual_decoder_init_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_textual_decoder_init *decoder_init; +	struct esg_namespace_prefix *namespace_prefix; +	struct esg_namespace_prefix *last_namespace_prefix; +	struct esg_xml_fragment_type *xml_fragment_type; +	struct esg_xml_fragment_type *last_xml_fragment_type; +	uint32_t decoder_init_length; +	uint8_t num_index; + +	if ((buffer == NULL) || (size <= 1)) { +		return NULL; +	} + +	pos = 0; + +	decoder_init = (struct esg_textual_decoder_init *) malloc(sizeof(struct esg_textual_decoder_init)); +	memset(decoder_init, 0, sizeof(struct esg_textual_decoder_init)); +	decoder_init->namespace_prefix_list = NULL; +	decoder_init->xml_fragment_type_list = NULL; + +	decoder_init->version = buffer[pos]; +	pos += 1; + +	pos += vluimsbf8(buffer+pos, size-pos, &decoder_init_length); + +	if (size < pos + decoder_init_length) { +		esg_textual_decoder_init_free(decoder_init); +		return NULL; +	} + +	decoder_init->num_namespace_prefixes = buffer[pos]; +	pos += 1; + +	last_namespace_prefix = NULL; +	for (num_index = 0; num_index < decoder_init->num_namespace_prefixes; num_index++) { +		namespace_prefix = (struct esg_namespace_prefix *) malloc(sizeof(struct esg_namespace_prefix)); +		memset(namespace_prefix, 0, sizeof(struct esg_namespace_prefix)); +		namespace_prefix->_next = NULL; + +		if (last_namespace_prefix == NULL) { +			decoder_init->namespace_prefix_list = namespace_prefix; +		} else { +			last_namespace_prefix->_next = namespace_prefix; +		} +		last_namespace_prefix = namespace_prefix; + +		namespace_prefix->prefix_string_ptr = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		namespace_prefix->namespace_uri_ptr = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; +	} + +	decoder_init->num_fragment_types = buffer[pos]; +	pos += 1; + +	last_xml_fragment_type = NULL; +	for (num_index = 0; num_index < decoder_init->num_fragment_types; num_index++) { +		xml_fragment_type = (struct esg_xml_fragment_type *) malloc(sizeof(struct esg_xml_fragment_type)); +		memset(xml_fragment_type, 0, sizeof(struct esg_xml_fragment_type)); +		xml_fragment_type->_next = NULL; + +		if (last_xml_fragment_type == NULL) { +			decoder_init->xml_fragment_type_list = xml_fragment_type; +		} else { +			last_xml_fragment_type->_next = xml_fragment_type; +		} +		last_xml_fragment_type = xml_fragment_type; + +		xml_fragment_type->xpath_ptr = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		xml_fragment_type->xml_fragment_type = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; +	} + +	return decoder_init; +} + +void esg_textual_decoder_init_free(struct esg_textual_decoder_init *decoder_init) { +	struct esg_namespace_prefix *namespace_prefix; +	struct esg_namespace_prefix *next_namespace_prefix; +	struct esg_xml_fragment_type *xml_fragment_type; +	struct esg_xml_fragment_type *next_xml_fragment_type; + +	if (decoder_init == NULL) { +		return; +    } + +	for(namespace_prefix = decoder_init->namespace_prefix_list; namespace_prefix; namespace_prefix = next_namespace_prefix) { +		next_namespace_prefix = namespace_prefix->_next; +		free(namespace_prefix); +	} + +	for(xml_fragment_type = decoder_init->xml_fragment_type_list; xml_fragment_type; xml_fragment_type = next_xml_fragment_type) { +		next_xml_fragment_type = xml_fragment_type->_next; +		free(xml_fragment_type); +	} + +	free(decoder_init); +} diff --git a/lib/libesg/representation/textual_decoder_init.h b/lib/libesg/representation/textual_decoder_init.h new file mode 100644 index 0000000..c1352cc --- /dev/null +++ b/lib/libesg/representation/textual_decoder_init.h @@ -0,0 +1,104 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_REPRESENTATION_TEXTUAL_DECODER_INIT_H +#define _ESG_REPRESENTATION_TEXTUAL_DECODER_INIT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_namespace_prefix structure. + */ +struct esg_namespace_prefix { +	uint16_t prefix_string_ptr; +	uint16_t namespace_uri_ptr; + +	struct esg_namespace_prefix *_next; +}; + +/** + * esg_fragment_type structure. + */ +struct esg_xml_fragment_type { +	uint16_t xpath_ptr; +	uint16_t xml_fragment_type; + +	struct esg_xml_fragment_type *_next; +}; + +/** + * esg_textual_decoder_init structure. + */ +struct esg_textual_decoder_init { +	uint8_t version; +	uint8_t num_namespace_prefixes; +	struct esg_namespace_prefix *namespace_prefix_list; +	uint8_t num_fragment_types; +	struct esg_xml_fragment_type *xml_fragment_type_list; +}; + +/** + * Process an esg_textual_decoder_init. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_textual_decoder_init structure, or NULL on error. + */ +extern struct esg_textual_decoder_init *esg_textual_decoder_init_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_textual_decoder_init. + * + * @param decoder_init Pointer to an esg_textual_decoder_init structure. + */ +extern void esg_textual_decoder_init_free(struct esg_textual_decoder_init *decoder_init); + +/** + * Convenience iterator for namespace_prefix_list field of an esg_textual_decoder_init. + * + * @param decoder_init The esg_textual_decoder_init pointer. + * @param namespace_prefix Variable holding a pointer to the current esg_namespace_prefix. + */ +#define esg_textual_decoder_namespace_prefix_list_for_each(decoder_init, namespace_prefix) \ +	for ((namespace_prefix) = (decoder_init)->namespace_prefix_list; \ +	     (namespace_prefix); \ +	     (namespace_prefix) = (namespace_prefix)->_next) + +/** + * Convenience iterator for xml_fragment_type_list field of an esg_textual_decoder_init. + * + * @param decoder_init The esg_textual_decoder_init pointer. + * @param xml_fragment_type Variable holding a pointer to the current esg_xml_fragment_type. + */ +#define esg_textual_decoder_xml_fragment_type_list_for_each(decoder_init, xml_fragment_type) \ +	for ((xml_fragment_type) = (decoder_init)->xml_fragment_type_list; \ +	     (xml_fragment_type); \ +	     (xml_fragment_type) = (xml_fragment_type)->_next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/transport/Makefile b/lib/libesg/transport/Makefile new file mode 100644 index 0000000..7900770 --- /dev/null +++ b/lib/libesg/transport/Makefile @@ -0,0 +1,22 @@ +# Makefile for linuxtv.org dvb-apps/lib/libesg/transport + +.PHONY: sub-error-transport + +sub-error-transport: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += transport/session_partition_declaration.o + +sub-install += transport + +else + +includes = session_partition_declaration.h + +include ../../../Make.rules + +lib_name = libesg/transport + +endif diff --git a/lib/libesg/transport/session_partition_declaration.c b/lib/libesg/transport/session_partition_declaration.c new file mode 100644 index 0000000..d590bd3 --- /dev/null +++ b/lib/libesg/transport/session_partition_declaration.c @@ -0,0 +1,253 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <stdlib.h> +#include <string.h> + +#include <libesg/transport/session_partition_declaration.h> + +struct esg_session_partition_declaration *esg_session_partition_declaration_decode(uint8_t *buffer, uint32_t size) { +	uint32_t pos; +	struct esg_session_partition_declaration *partition; +	struct esg_session_field *field; +	struct esg_session_field *last_field; +	uint8_t field_index; +	struct esg_session_ip_stream *ip_stream; +	struct esg_session_ip_stream *last_ip_stream; +	uint8_t ip_stream_index; +	uint8_t ip_index; +	struct esg_session_ip_stream_field *ip_stream_field; +	struct esg_session_ip_stream_field *last_ip_stream_field; +	uint8_t *field_buffer; +	uint32_t field_length; +	union esg_session_ip_stream_field_value *field_value; + +	if ((buffer == NULL) || (size <= 2)) { +		return NULL; +	} + +	pos = 0; + +	partition = (struct esg_session_partition_declaration *) malloc(sizeof(struct esg_session_partition_declaration)); +	memset(partition, 0, sizeof(struct esg_session_partition_declaration)); +	partition->field_list = NULL; +	partition->ip_stream_list = NULL; + +	partition->num_fields = buffer[pos]; +	pos += 1; + +	partition->overlapping = (buffer[pos] & 0x80) ? 1 : 0; +	pos += 1; + +	if (size < (pos + 5*(partition->num_fields))) { +		esg_session_partition_declaration_free(partition); +		return NULL; +	} + +	last_field = NULL; +	for (field_index = 0; field_index < partition->num_fields; field_index++) { +		field = (struct esg_session_field *) malloc(sizeof(struct esg_session_field)); +		memset(field, 0, sizeof(struct esg_session_field)); +		field->_next = NULL; + +		if (last_field == NULL) { +			partition->field_list = field; +		} else { +			last_field->_next = field; +		} +		last_field = field; + +		field->identifier = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		field->encoding = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		field->length = buffer[pos]; +		pos += 1; +	} + +	partition->n_o_ip_streams = buffer[pos]; +	pos += 1; + +	partition->ip_version_6 = (buffer[pos] & 0x80) ? 1 : 0; +	pos += 1; + +	last_ip_stream = NULL; +	for (ip_stream_index = 0; ip_stream_index < partition->n_o_ip_streams; ip_stream_index++) { +		ip_stream = (struct esg_session_ip_stream *) malloc(sizeof(struct esg_session_ip_stream)); +		memset(ip_stream, 0, sizeof(struct esg_session_ip_stream)); +		ip_stream->_next = NULL; + +		if (last_ip_stream == NULL) { +			partition->ip_stream_list = ip_stream; +		} else { +			last_ip_stream->_next = ip_stream; +		} +		last_ip_stream = ip_stream; + +		ip_stream->id = buffer[pos]; +		pos += 1; + +		if (partition->ip_version_6) { +			for (ip_index = 0; ip_index < 16; ip_index++) { +				ip_stream->source_ip.ipv6[ip_index] = buffer[pos+ip_index]; +				ip_stream->destination_ip.ipv6[ip_index] = buffer[pos+16+ip_index]; +			} +			pos += 32; +		} else { +			for (ip_index = 0; ip_index < 4; ip_index++) { +				ip_stream->source_ip.ipv4[ip_index] = buffer[pos+ip_index]; +				ip_stream->destination_ip.ipv4[ip_index] = buffer[pos+4+ip_index]; +			} +			pos += 8; +		} +		ip_stream->port = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		ip_stream->session_id = (buffer[pos] << 8) | buffer[pos+1]; +		pos += 2; + +		last_ip_stream_field = NULL; +		esg_session_partition_declaration_field_list_for_each(partition, field) { +			ip_stream_field = (struct esg_session_ip_stream_field *) malloc(sizeof(struct esg_session_ip_stream_field)); +			memset(ip_stream_field, 0, sizeof(struct esg_session_ip_stream_field)); +			ip_stream_field->_next = NULL; +			ip_stream_field->start_field_value = NULL; +			ip_stream_field->end_field_value = NULL; + +			if (last_ip_stream_field == NULL) { +				ip_stream->field_list = ip_stream_field; +			} else { +				last_ip_stream_field->_next = ip_stream_field; +			} +			last_ip_stream_field = ip_stream_field; + +			field_length = field->length; +			if (field->length != 0) { +				field_length = field->length; +			} else { +				pos += vluimsbf8(buffer + pos, size - pos, &field_length); +			} + +			switch (field->encoding) { +				case 0x0000: { +					if (partition->overlapping == 1) { +						field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value)); +						memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value)); +						ip_stream_field->start_field_value = field_value; + +						field_buffer = (uint8_t *) malloc(field_length); +						memset(field_buffer, 0, field_length); +						memcpy(field_buffer, buffer + pos, field_length); + +						ip_stream_field->start_field_value->string = field_buffer; +						pos += field_length; +					} +					field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value)); +					memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value)); +					ip_stream_field->end_field_value = field_value; + +					field_buffer = (uint8_t *) malloc(field_length); +					memset(field_buffer, 0, field_length); +					memcpy(field_buffer, buffer + pos, field_length); + +					ip_stream_field->end_field_value->string = field_buffer; +					pos += field_length; + +					break; +				} +				case 0x0101: { +					if (partition->overlapping == 1) { +						field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value)); +						memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value)); +						ip_stream_field->start_field_value = field_value; + +						ip_stream_field->start_field_value->unsigned_short = (buffer[pos] << 8) | buffer[pos+1]; +						pos += field_length; +					} +					field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value)); +					memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value)); +					ip_stream_field->end_field_value = field_value; + +					ip_stream_field->end_field_value->unsigned_short = (buffer[pos] << 8) | buffer[pos+1]; +					pos += field_length; + +					break; +				} +				default: { +					esg_session_partition_declaration_free(partition); +					return NULL; +				} +			} +		} +	} + +	return partition; +} + +void esg_session_partition_declaration_free(struct esg_session_partition_declaration *partition) { +	struct esg_session_field *field; +	struct esg_session_field *next_field; +	struct esg_session_ip_stream *ip_stream; +	struct esg_session_ip_stream *next_ip_stream; +	struct esg_session_ip_stream_field *ip_stream_field; +	struct esg_session_ip_stream_field *next_ip_stream_field; + +	if (partition == NULL) { +		return; +    } + +	for(ip_stream = partition->ip_stream_list; ip_stream; ip_stream = next_ip_stream) { +		next_ip_stream = ip_stream->_next; + +		field = partition->field_list; +		for(ip_stream_field = next_ip_stream->field_list; ip_stream_field; ip_stream_field = next_ip_stream_field) { +			next_ip_stream_field = ip_stream_field->_next; + +			switch (field->encoding) { +				case 0x0000: { +					if (ip_stream_field->start_field_value != NULL) { +						free(ip_stream_field->start_field_value->string); +					} +					free(ip_stream_field->end_field_value->string); +					break; +				} +				case 0x0101: { +					// Nothing to free +					break; +				} +			} + +			free(ip_stream_field); + +			field = field->_next; +		} + +		free(ip_stream); +	} + +	for(field = partition->field_list; field; field = next_field) { +		next_field = field->_next; +		free(field); +	} + +	free(partition); +} diff --git a/lib/libesg/transport/session_partition_declaration.h b/lib/libesg/transport/session_partition_declaration.h new file mode 100644 index 0000000..8f2fa1a --- /dev/null +++ b/lib/libesg/transport/session_partition_declaration.h @@ -0,0 +1,139 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_TRANSPORT_SESSION_PARTITION_DECLARATION_H +#define _ESG_TRANSPORT_SESSION_PARTITION_DECLARATION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libesg/types.h> + +/** + * esg_session_field structure. + */ +struct esg_session_field { +	uint16_t identifier; +	uint16_t encoding; +	uint8_t length; + +	struct esg_session_field *_next; +}; + +/** + * esg_session_ip_stream_field_value union. + */ +union esg_session_ip_stream_field_value { +	uint8_t *string; +	uint16_t unsigned_short; +}; + +/** + * esg_session_ip_stream_field structure. + */ +struct esg_session_ip_stream_field { +	union esg_session_ip_stream_field_value *start_field_value; +	union esg_session_ip_stream_field_value *end_field_value; + +	struct esg_session_ip_stream_field *_next; +}; + +/** + * esg_session_ip_stream structure. + */ +struct esg_session_ip_stream { +	uint8_t id; +	union esg_ip_address source_ip; +	union esg_ip_address destination_ip; +	uint16_t port; +	uint16_t session_id; +	struct esg_session_ip_stream_field *field_list; + +	struct esg_session_ip_stream *_next; +}; + +/** + * esg_session_partition_declaration structure. + */ +struct esg_session_partition_declaration { +	uint8_t num_fields; +	uint8_t overlapping; +	struct esg_session_field *field_list; +	uint8_t n_o_ip_streams; +	uint8_t ip_version_6; +	struct esg_session_ip_stream *ip_stream_list; +}; + +/** + * Process an esg_session_partition_declaration. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @return Pointer to an esg_session_partition_declaration structure, or NULL on error. + */ +extern struct esg_session_partition_declaration *esg_session_partition_declaration_decode(uint8_t *buffer, uint32_t size); + +/** + * Free an esg_session_partition_declaration. + * + * @param esg Pointer to an esg_session_partition_declaration structure. + */ +extern void esg_session_partition_declaration_free(struct esg_session_partition_declaration *partition); + +/** + * Convenience iterator for field_list field of an esg_session_partition_declaration. + * + * @param partition The esg_session_partition_declaration pointer. + * @param field Variable holding a pointer to the current esg_session_field. + */ +#define esg_session_partition_declaration_field_list_for_each(partition, field) \ +	for ((field) = (partition)->field_list; \ +	     (field); \ +	     (field) = (field)->_next) + +/** + * Convenience iterator for ip_stream_list field of an esg_session_partition_declaration. + * + * @param partition The esg_session_partition_declaration pointer. + * @param ip_stream Variable holding a pointer to the current esg_session_ip_stream. + */ +#define esg_session_partition_declaration_ip_stream_list_for_each(partition, ip_stream) \ +	for ((ip_stream) = (partition)->ip_stream_list; \ +	     (ip_stream); \ +	     (ip_stream) = (ip_stream)->_next) + +/** + * Convenience iterator for field_list field of an esg_session_ip_stream. + * + * @param ip_stream The esg_session_ip_stream pointer. + * @param field Variable holding a pointer to the current esg_session_ip_stream. + */ +#define esg_session_ip_stream_field_list_for_each(ip_stream, field) \ +	for ((field) = (ip_stream)->field_list; \ +	     (field); \ +	     (field) = (field)->_next) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/types.c b/lib/libesg/types.c new file mode 100644 index 0000000..51f1cbd --- /dev/null +++ b/lib/libesg/types.c @@ -0,0 +1,37 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 <libesg/types.h> + +uint8_t vluimsbf8(uint8_t *buffer, uint32_t size, uint32_t *length) { +	uint8_t offset = 0; +	*length = 0; + +	do { +		if (size < offset) { +			offset = 0; +			*length = 0; +			break; +		} +		*length = (*length << 7) + (buffer[offset] & 0x7F); +	} while (buffer[offset++] & 0x80); + +	return offset; +} diff --git a/lib/libesg/types.h b/lib/libesg/types.h new file mode 100644 index 0000000..b6725af --- /dev/null +++ b/lib/libesg/types.h @@ -0,0 +1,53 @@ +/* + * ESG parser + * + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _ESG_TYPES_H +#define _ESG_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +/** + * esg_ip_address + */ +union esg_ip_address { +	uint8_t ipv4[4]; +	uint8_t ipv6[16]; +}; + +/** + * Process a vluimsbf8 length. + * + * @param buffer Binary buffer to decode. + * @param size Binary buffer size. + * @param length Read length value + * @return vluimsbf8 size + */ +extern uint8_t vluimsbf8(uint8_t *buffer, uint32_t size, uint32_t *length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesg/xml/provider_discovery_descriptor.xsd b/lib/libesg/xml/provider_discovery_descriptor.xsd new file mode 100644 index 0000000..5956343 --- /dev/null +++ b/lib/libesg/xml/provider_discovery_descriptor.xsd @@ -0,0 +1,22 @@ +<schema targetNamespace="urn:dvb:ipdc:esgbs:2005" xmlns:bs="urn:dvb:ipdc:esgbs:2005" +	xmlns:mpeg7="urn:mpeg:mpeg7:schema:2001" xmlns="http://www.w3.org/2001/XMLSchema" +	elementFormDefault="qualified" attributeFormDefault="unqualified"> +	<import namespace="urn:mpeg:mpeg7:schema:2001" /> +	<complexType name="ESGProviderType"> +		<sequence> +			<element name="ProviderURI" type="anyURI"/> +			<element name="ProviderName" type="mpeg7:TextualType"/> +			<element name="ProviderLogo" type="mpeg7:TitleMediaType" minOccurs="0"/> +			<element name="ProviderID" type="positiveInteger"/> +			<element name="ProviderInformationURL" type="anyURI" minOccurs="0"/> +			<element name="PrivateAuxiliaryData" type="anyType" minOccurs="0"/> +		</sequence> +	</complexType> +	<element name="ESGProviderDiscovery"> +		<complexType> +			<sequence> +				<element name="ServiceProvider" type="bs:ESGProviderType" maxOccurs="unbounded"/> +			</sequence> +		</complexType> +	</element> +</schema> diff --git a/lib/libucsi/Makefile b/lib/libucsi/Makefile new file mode 100644 index 0000000..19ab268 --- /dev/null +++ b/lib/libucsi/Makefile @@ -0,0 +1,34 @@ +# Makefile for linuxtv.org dvb-apps/lib/libucsi + +includes = crc32.h            \ +           descriptor.h       \ +           endianops.h        \ +           section.h          \ +           section_buf.h      \ +           transport_packet.h \ +           types.h + +objects  = crc32.o            \ +           section_buf.o      \ +           transport_packet.o + +lib_name = libucsi + +CPPFLAGS += -I../../lib + +.PHONY: all + +all: library + +include atsc/Makefile +include dvb/Makefile +include mpeg/Makefile + +.PHONY: $(sub-install) + +install:: $(sub-install) + +$(sub-install): +	$(MAKE) -C $@ install + +include ../../Make.rules diff --git a/lib/libucsi/atsc/Makefile b/lib/libucsi/atsc/Makefile new file mode 100644 index 0000000..c3d8e6b --- /dev/null +++ b/lib/libucsi/atsc/Makefile @@ -0,0 +1,55 @@ +# Makefile for linuxtv.org dvb-apps/lib/libucsi/atsc + +.PHONY: sub-error-atsc + +sub-error-atsc: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += atsc/atsc_text.o      \ +           atsc/cvct_section.o   \ +           atsc/dccsct_section.o \ +           atsc/dcct_section.o   \ +           atsc/eit_section.o    \ +           atsc/ett_section.o    \ +           atsc/mgt_section.o    \ +           atsc/rrt_section.o    \ +           atsc/stt_section.o    \ +           atsc/tvct_section.o   \ +           atsc/types.o + +sub-install += atsc + +else + +includes = ac3_descriptor.h                   \ +           caption_service_descriptor.h       \ +           component_name_descriptor.h        \ +           content_advisory_descriptor.h      \ +           cvct_section.h                     \ +           dcc_arriving_request_descriptor.h  \ +           dcc_departing_request_descriptor.h \ +           dccsct_section.h                   \ +           dcct_section.h                     \ +           descriptor.h                       \ +           eit_section.h                      \ +           ett_section.h                      \ +           extended_channel_name_descriptor.h \ +           genre_descriptor.h                 \ +           mgt_section.h                      \ +           rc_descriptor.h                    \ +           rrt_section.h                      \ +           section.h                          \ +           service_location_descriptor.h      \ +           stt_section.h                      \ +           stuffing_descriptor.h              \ +           time_shifted_service_descriptor.h  \ +           tvct_section.h                     \ +           types.h + +include ../../../Make.rules + +lib_name = libucsi/atsc + +endif diff --git a/lib/libucsi/atsc/ac3_descriptor.h b/lib/libucsi/atsc/ac3_descriptor.h new file mode 100644 index 0000000..489695b --- /dev/null +++ b/lib/libucsi/atsc/ac3_descriptor.h @@ -0,0 +1,112 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_atsc@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 _UCSI_ATSC_AC3_DESCRIPTOR +#define _UCSI_ATSC_AC3_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +enum atsc_ac3_channels { +	ATSC_AC3_CHANNELS_1_PLUS_1	= 0x0, +	ATSC_AC3_CHANNELS_1_0		= 0x1, +	ATSC_AC3_CHANNELS_2_0		= 0x2, +	ATSC_AC3_CHANNELS_3_0		= 0x3, +	ATSC_AC3_CHANNELS_2_1		= 0x4, +	ATSC_AC3_CHANNELS_3_1 		= 0x5, +	ATSC_AC3_CHANNELS_2_2		= 0x6, +	ATSC_AC3_CHANNELS_3_2		= 0x7, +	ATSC_AC3_CHANNELS_1		= 0x8, +	ATSC_AC3_CHANNELS_LTEQ_2	= 0x9, +	ATSC_AC3_CHANNELS_LTEQ_3	= 0xa, +	ATSC_AC3_CHANNELS_LTEQ_4	= 0xb, +	ATSC_AC3_CHANNELS_LTEQ_5	= 0xc, +	ATSC_AC3_CHANNELS_LTEQ_6	= 0xd, +}; + +/** + * atsc_ac3_descriptor structure. + */ +struct atsc_ac3_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t sample_rate_code        : 3; , +	uint8_t bsid			: 5; ); +  EBIT2(uint8_t bit_rate_code	        : 6; , +	uint8_t surround_mode		: 2; ); +  EBIT3(uint8_t bsmod		        : 3; , +	uint8_t num_channels		: 4; , +	uint8_t full_svc		: 1; ); +	/* uint8_t additional_info[] */ +} __ucsi_packed; + +/** + * Process an atsc_ac3_descriptor. + * + * @param d Generic descriptor structure. + * @return atsc_ac3_descriptor pointer, or NULL on error. + */ +static inline struct atsc_ac3_descriptor* +	atsc_ac3_descriptor_codec(struct descriptor* d) +{ +	int pos = 0; + +	if (d->len < (pos+4)) +		return NULL; +	pos += 4; + +	return (struct atsc_ac3_descriptor*) d; +} + +/** + * Retrieve pointer to additional_info field of a atsc_ac3_descriptor. + * + * @param d atsc_ac3_descriptor pointer. + * @return Pointer to additional_info field. + */ +static inline uint8_t *atsc_ac3_descriptor_additional_info(struct atsc_ac3_descriptor *d) +{ +	int pos = sizeof(struct atsc_ac3_descriptor); + +	return ((uint8_t *) d) + pos; +} + +/** + * Determine length of additional_info field of a atsc_ac3_descriptor. + * + * @param d atsc_ac3_descriptor pointer. + * @return Length of field in bytes. + */ +static inline int atsc_ac3_descriptor_additional_info_length(struct atsc_ac3_descriptor* d) +{ +	return d->d.len - 3; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/atsc_text.c b/lib/libucsi/atsc/atsc_text.c new file mode 100644 index 0000000..d79c83f --- /dev/null +++ b/lib/libucsi/atsc/atsc_text.c @@ -0,0 +1,743 @@ +/* +* section and descriptor parser +* +* 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "libucsi/endianops.h" +#include "libucsi/atsc/types.h" + +#define HUFFTREE_LITERAL_MASK 0x80 +#define HUFFSTRING_END 0x00 +#define HUFFSTRING_ESCAPE 0x1b + +#define DEST_ALLOC_DELTA 20 + +struct hufftree_entry { +	uint8_t left_idx; +	uint8_t right_idx; +} __ucsi_packed; + +struct huffbuff { +	uint8_t *buf; +	uint32_t buf_len; + +	uint32_t cur_byte; +	uint8_t cur_bit; +}; + + +static struct hufftree_entry program_description_hufftree[][128] = { +	{ {0x14, 0x15}, {0x9b, 0xd6}, {0xc9, 0xcf}, {0xd7, 0xc7}, {0x01, 0xa2}, +	{0xce, 0xcb}, {0x02, 0x03}, {0xc5, 0xcc}, {0xc6, 0xc8}, {0x04, 0xc4}, +	{0x05, 0xc2}, {0x06, 0xc3}, {0xd2, 0x07}, {0xd3, 0x08}, {0xca, 0xd4}, +	{0x09, 0xcd}, {0xd0, 0x0a}, {0xc1, 0x0b}, {0x0c, 0x0d}, {0x0e, 0x0f}, +	{0x10, 0x11}, {0x12, 0x13}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x38, 0x39}, {0xad, 0xaf}, {0xb7, 0xda}, {0xa8, 0xb3}, {0xb5, 0x01}, +	{0x02, 0x9b}, {0xb4, 0xf1}, {0xa2, 0xd5}, {0xd6, 0xd9}, {0x03, 0x04}, +	{0x05, 0xcf}, {0x06, 0xc9}, {0xf9, 0xea}, {0xeb, 0xf5}, {0xf6, 0x07}, +	{0x08, 0x09}, {0xb2, 0xc5}, {0xc6, 0xb1}, {0x0a, 0xee}, {0xcb, 0x0b}, +	{0xd4, 0x0c}, {0xc4, 0xc8}, {0xd2, 0x0d}, {0x0e, 0x0f}, {0xc7, 0xca}, +	{0xce, 0xd0}, {0xd7, 0x10}, {0xc2, 0x11}, {0xcc, 0xec}, {0xe5, 0xe7}, +	{0x12, 0xcd}, {0x13, 0x14}, {0xc3, 0x15}, {0x16, 0x17}, {0xed, 0x18}, +	{0x19, 0xf2}, {0x1a, 0xd3}, {0x1b, 0x1c}, {0xe4, 0x1d}, {0xc1, 0xe3}, +	{0x1e, 0xe9}, {0xf0, 0xe2}, {0xf7, 0x1f}, {0xf3, 0xe6}, {0x20, 0x21}, +	{0x22, 0xe8}, {0xef, 0x23}, {0x24, 0x25}, {0x26, 0x27}, {0x28, 0x29}, +	{0x2a, 0xf4}, {0x2b, 0x2c}, {0x2d, 0x2e}, {0x2f, 0xe1}, {0x30, 0x31}, +	{0x32, 0x33}, {0x34, 0x35}, {0x36, 0x37}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x03, 0x04}, {0x80, 0xae}, {0xc8, 0xd4}, {0x01, 0x02}, {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0xf3}, {0xa0, 0xf4}, {0x9b, 0x01}, }, +	{ {0x9b, 0x9b}, }, +	{ {0xac, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x01, 0xa0}, {0x9b, 0xa2}, }, +	{ {0x07, 0x08}, {0xe2, 0xe4}, {0xe5, 0xe6}, {0xa0, 0xf2}, {0xe1, 0x01}, +	{0x02, 0xf3}, {0xe3, 0x03}, {0x04, 0x05}, {0x9b, 0x06}, }, +	{ {0x04, 0x80}, {0xca, 0xd3}, {0xa2, 0x01}, {0x9b, 0x02}, {0x03, 0xa0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x03, 0x04}, {0x9b, 0xb7}, {0xf4, 0xa0}, {0xb0, 0xf3}, {0x01, 0x02}, }, +	{ {0xb9, 0x02}, {0xb8, 0x9b}, {0xa0, 0x01}, }, +	{ {0xae, 0x02}, {0xb6, 0x9b}, {0x01, 0xa0}, }, +	{ {0xa0, 0x01}, {0x9b, 0xb0}, }, +	{ {0xae, 0x01}, {0x9b, 0xa0}, }, +	{ {0xae, 0x01}, {0xa0, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x01}, {0xac, 0xae}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0x03}, {0x9b, 0xa0}, {0xb5, 0xb6}, {0xb8, 0x01}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x08, 0x09}, {0xe6, 0xf5}, {0xf3, 0xf4}, {0x9b, 0xe4}, {0x01, 0xed}, +	{0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x06}, {0xec, 0xee}, {0x07, 0xa0}, }, +	{ {0x05, 0x06}, {0x9b, 0xec}, {0xf5, 0x01}, {0x02, 0xe1}, {0xef, 0xe5}, +	{0xe9, 0xf2}, {0x03, 0x04}, }, +	{ {0x06, 0x07}, {0x9b, 0xe9}, {0xf9, 0xf2}, {0xf5, 0x01}, {0x02, 0x03}, +	{0xec, 0xef}, {0xe1, 0x04}, {0xe8, 0x05}, }, +	{ {0x05, 0x06}, {0xf9, 0xf2}, {0xf5, 0x9b}, {0xe5, 0xef}, {0x01, 0x02}, +	{0xe9, 0xe1}, {0x03, 0x04}, }, +	{ {0x06, 0x07}, {0xe1, 0xe9}, {0xee, 0xf6}, {0xe4, 0xec}, {0xf3, 0x01}, +	{0x02, 0xf2}, {0x03, 0x04}, {0x9b, 0x05}, }, +	{ {0x02, 0x03}, {0xe5, 0xec}, {0x9b, 0xef}, {0x01, 0xf2}, }, +	{ {0x05, 0x06}, {0xf5, 0xef}, {0x9b, 0xec}, {0xe9, 0x01}, {0xe1, 0xf2}, +	{0x02, 0xe5}, {0x03, 0x04}, }, +	{ {0x03, 0x04}, {0x9b, 0xe5}, {0xe9, 0xf5}, {0xe1, 0x01}, {0xef, 0x02}, }, +	{ {0x04, 0x05}, {0xa0, 0xc9}, {0xf3, 0x9b}, {0xae, 0xf2}, {0x01, 0x02}, +	{0x03, 0xee}, }, +	{ {0xef, 0x05}, {0x9b, 0xae}, {0xe9, 0xe5}, {0x01, 0xf5}, {0x02, 0xe1}, +	{0x03, 0x04}, }, +	{ {0xe5, 0x03}, {0xe1, 0xe9}, {0xf2, 0x9b}, {0x01, 0x02}, }, +	{ {0x03, 0x04}, {0x9b, 0xe9}, {0xf5, 0x01}, {0xe5, 0x02}, {0xef, 0xe1}, }, +	{ {0xe1, 0x05}, {0x9b, 0xe3}, {0xef, 0x01}, {0xf5, 0xe5}, {0x02, 0x03}, +	{0xe9, 0x04}, }, +	{ {0xe5, 0x03}, {0x9b, 0xe9}, {0x01, 0xe1}, {0xef, 0x02}, }, +	{ {0x03, 0x04}, {0xa7, 0xee}, {0xec, 0xf2}, {0xf3, 0x01}, {0x9b, 0x02}, }, +	{ {0xe1, 0x06}, {0x9b, 0xe8}, {0xe9, 0x01}, {0xf2, 0xec}, {0x02, 0xef}, +	{0x03, 0xe5}, {0x04, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x03, 0x04}, {0x9b, 0xae}, {0x01, 0xe9}, {0x02, 0xe1}, {0xe5, 0xef}, }, +	{ {0x09, 0x0a}, {0xf6, 0xf9}, {0x01, 0xae}, {0xe3, 0xe9}, {0xf5, 0x9b}, +	{0xe5, 0xef}, {0x02, 0x03}, {0xe1, 0x04}, {0xe8, 0x05}, {0x06, 0xf4}, +	{0x07, 0x08}, }, +	{ {0xe8, 0x07}, {0xe5, 0xf7}, {0xd6, 0xe1}, {0x9b, 0xe9}, {0xf2, 0x01}, +	{0x02, 0x03}, {0x04, 0xef}, {0x05, 0x06}, }, +	{ {0xae, 0x01}, {0x9b, 0xee}, }, +	{ {0xe9, 0x02}, {0xe5, 0x9b}, {0xa0, 0x01}, }, +	{ {0x03, 0x04}, {0x9b, 0xe8}, {0xe5, 0xe1}, {0xef, 0x01}, {0xe9, 0x02}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xef}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x18, 0x19}, {0xe8, 0xef}, {0xf8, 0x9b}, {0xa7, 0xf7}, {0xfa, 0x01}, +	{0x02, 0x03}, {0x04, 0xe5}, {0xae, 0x05}, {0xe6, 0xe2}, {0x06, 0xf6}, +	{0xeb, 0xf5}, {0xe9, 0x07}, {0xf0, 0xf9}, {0xe7, 0x08}, {0x09, 0xe4}, +	{0x0a, 0xe3}, {0x0b, 0xed}, {0x0c, 0xf3}, {0x0d, 0x0e}, {0x0f, 0xec}, +	{0x10, 0xf4}, {0x11, 0x12}, {0xf2, 0xa0}, {0x13, 0x14}, {0x15, 0xee}, +	{0x16, 0x17}, }, +	{ {0x0b, 0x0c}, {0xe4, 0xf3}, {0x9b, 0xae}, {0xe2, 0x01}, {0x02, 0x03}, +	{0xec, 0xa0}, {0x04, 0xe9}, {0xf2, 0xf5}, {0x05, 0xf9}, {0xe1, 0x06}, +	{0xef, 0x07}, {0xe5, 0x08}, {0x09, 0x0a}, }, +	{ {0x0f, 0x10}, {0xf1, 0xae}, {0xc4, 0xf9}, {0xac, 0x01}, {0xe3, 0x02}, +	{0x9b, 0xf2}, {0x03, 0x04}, {0xa0, 0xec}, {0xf5, 0x05}, {0x06, 0xe9}, +	{0x07, 0xeb}, {0x08, 0xf4}, {0x09, 0xe5}, {0x0a, 0xef}, {0xe1, 0xe8}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, }, +	{ {0x13, 0x14}, {0xa7, 0xbb}, {0xe6, 0xed}, {0xf7, 0xe7}, {0xf6, 0x01}, +	{0x02, 0x9b}, {0xee, 0x03}, {0x04, 0xec}, {0x05, 0xf5}, {0x06, 0xac}, +	{0xe4, 0xf9}, {0xf2, 0x07}, {0x08, 0x09}, {0xae, 0x0a}, {0xef, 0x0b}, +	{0xe1, 0xf3}, {0x0c, 0xe9}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xe5, 0x11}, +	{0x12, 0xa0}, }, +	{ {0x1d, 0x1e}, {0xa9, 0xe8}, {0xf5, 0x9b}, {0x01, 0xad}, {0xbb, 0xeb}, +	{0xfa, 0x02}, {0xa7, 0xe6}, {0xe2, 0xe7}, {0x03, 0x04}, {0x05, 0x06}, +	{0xe9, 0xf8}, {0x07, 0xac}, {0xef, 0xf0}, {0x08, 0xed}, {0xf6, 0xf9}, +	{0x09, 0xf7}, {0x0a, 0x0b}, {0xae, 0x0c}, {0xe3, 0x0d}, {0xe5, 0xf4}, +	{0x0e, 0x0f}, {0xe4, 0x10}, {0xec, 0x11}, {0xe1, 0x12}, {0x13, 0x14}, +	{0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x18}, {0xf2, 0xa0}, {0x19, 0x1a}, +	{0x1b, 0x1c}, }, +	{ {0x09, 0x0a}, {0xae, 0x9b}, {0xec, 0x01}, {0xf5, 0x02}, {0xf4, 0xe6}, +	{0x03, 0xe1}, {0xe5, 0xe9}, {0x04, 0xf2}, {0xef, 0x05}, {0x06, 0x07}, +	{0xa0, 0x08}, }, +	{ {0x0e, 0x0f}, {0xad, 0xe7}, {0x9b, 0xa7}, {0xf9, 0x01}, {0xec, 0x02}, +	{0xac, 0xf2}, {0x03, 0xae}, {0xf3, 0xf5}, {0x04, 0x05}, {0xef, 0x06}, +	{0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0x0b}, {0xe5, 0x0c}, +	{0xa0, 0x0d}, }, +	{ {0x0d, 0x0e}, {0xa7, 0xac}, {0xf3, 0xad}, {0x01, 0x02}, {0x9b, 0xf9}, +	{0xf5, 0xae}, {0x03, 0xee}, {0x04, 0xf2}, {0x05, 0x06}, {0xf4, 0x07}, +	{0x08, 0x09}, {0xef, 0xe1}, {0xa0, 0x0a}, {0xe9, 0x0b}, {0x0c, 0xe5}, }, +	{ {0x14, 0x15}, {0xac, 0xe2}, {0xf8, 0x9b}, {0xae, 0xfa}, {0x01, 0xeb}, +	{0x02, 0xa0}, {0x03, 0x04}, {0xf0, 0x05}, {0x06, 0xe6}, {0xf6, 0x07}, +	{0xe4, 0xed}, {0xe7, 0x08}, {0xe1, 0xef}, {0xf2, 0x09}, {0x0a, 0x0b}, +	{0xec, 0x0c}, {0xe5, 0xe3}, {0x0d, 0xf4}, {0x0e, 0xf3}, {0x0f, 0x10}, +	{0x11, 0xee}, {0x12, 0x13}, }, +	{ {0x03, 0xef}, {0x9b, 0xe1}, {0xe5, 0xf5}, {0x01, 0x02}, }, +	{ {0x08, 0x09}, {0xec, 0xf9}, {0xa7, 0xee}, {0x01, 0xac}, {0x9b, 0xae}, +	{0x02, 0x03}, {0x04, 0xf3}, {0x05, 0xe9}, {0x06, 0xa0}, {0x07, 0xe5}, }, +	{ {0x16, 0x17}, {0xa7, 0xad}, {0xee, 0xe3}, {0xeb, 0xf2}, {0x9b, 0xe2}, +	{0x01, 0x02}, {0xf5, 0x03}, {0xf4, 0xac}, {0x04, 0x05}, {0xe6, 0xed}, +	{0xf6, 0x06}, {0xae, 0xf0}, {0x07, 0x08}, {0xf3, 0x09}, {0x0a, 0xe4}, +	{0x0b, 0x0c}, {0xf9, 0x0d}, {0xef, 0x0e}, {0xe1, 0x0f}, {0x10, 0xe9}, +	{0xec, 0x11}, {0xa0, 0xe5}, {0x12, 0x13}, {0x14, 0x15}, }, +	{ {0x0c, 0x0d}, {0xa7, 0xbb}, {0x9b, 0x01}, {0xf9, 0xae}, {0xe2, 0x02}, +	{0xed, 0xf3}, {0x03, 0xf5}, {0xef, 0xf0}, {0x04, 0x05}, {0xe9, 0x06}, +	{0x07, 0x08}, {0x09, 0xa0}, {0xe1, 0xe5}, {0x0a, 0x0b}, }, +	{ {0x19, 0x1a}, {0xad, 0xbb}, {0xe2, 0xea}, {0xed, 0xf2}, {0xfa, 0xe6}, +	{0xec, 0x01}, {0x02, 0x03}, {0x9b, 0xf5}, {0x04, 0xa7}, {0xf6, 0xf9}, +	{0x05, 0x06}, {0xeb, 0xef}, {0x07, 0x08}, {0x09, 0x0a}, {0xac, 0x0b}, +	{0x0c, 0xe3}, {0xae, 0x0d}, {0xee, 0xe9}, {0x0e, 0xe1}, {0x0f, 0xf3}, +	{0x10, 0x11}, {0xf4, 0x12}, {0xe7, 0xe5}, {0x13, 0x14}, {0xe4, 0x15}, +	{0x16, 0x17}, {0xa0, 0x18}, }, +	{ {0x1a, 0x1b}, {0xc2, 0x9b}, {0xad, 0xac}, {0xf8, 0x01}, {0xae, 0x02}, +	{0x03, 0xe5}, {0xe7, 0xe8}, {0xf9, 0xe9}, {0xeb, 0x04}, {0xe3, 0xe1}, +	{0x05, 0xf6}, {0x06, 0xe4}, {0x07, 0xe2}, {0xf0, 0x08}, {0x09, 0xf3}, +	{0xf4, 0xf7}, {0xef, 0x0a}, {0x0b, 0x0c}, {0x0d, 0xec}, {0x0e, 0x0f}, +	{0x10, 0xf5}, {0xed, 0x11}, {0xe6, 0xa0}, {0x12, 0xf2}, {0x13, 0x14}, +	{0x15, 0xee}, {0x16, 0x17}, {0x18, 0x19}, }, +	{ {0x0e, 0x0f}, {0xad, 0xed}, {0xf9, 0x9b}, {0xae, 0x01}, {0xf3, 0x02}, +	{0x03, 0xf5}, {0xf4, 0xf0}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0xe8}, +	{0xa0, 0xe1}, {0xec, 0x07}, {0xf2, 0x08}, {0xe5, 0x09}, {0x0a, 0x0b}, +	{0x0c, 0x0d}, }, +	{ {0x9b, 0xf5}, }, +	{ {0x19, 0x1a}, {0xa9, 0xbb}, {0xf6, 0xe6}, {0x01, 0x9b}, {0xad, 0xe2}, +	{0xf0, 0x02}, {0xa7, 0x03}, {0x04, 0x05}, {0xf5, 0xe3}, {0xac, 0xe7}, +	{0xf2, 0x06}, {0xeb, 0x07}, {0xec, 0xed}, {0xee, 0xf9}, {0x08, 0xae}, +	{0x09, 0x0a}, {0xe4, 0x0b}, {0x0c, 0xf4}, {0x0d, 0xf3}, {0x0e, 0x0f}, +	{0x10, 0xe1}, {0xef, 0x11}, {0xe9, 0x12}, {0x13, 0xe5}, {0x14, 0xa0}, +	{0x15, 0x16}, {0x17, 0x18}, }, +	{ {0xa0, 0x16}, {0xa2, 0xa7}, {0xe2, 0xeb}, {0xed, 0xee}, {0x9b, 0xf7}, +	{0x01, 0x02}, {0x03, 0xbb}, {0xf9, 0xf0}, {0x04, 0x05}, {0xec, 0x06}, +	{0x07, 0x08}, {0xf5, 0xe1}, {0x09, 0xac}, {0xe3, 0x0a}, {0xe8, 0x0b}, +	{0xe9, 0x0c}, {0xef, 0xf3}, {0xae, 0x0d}, {0x0e, 0xe5}, {0x0f, 0x10}, +	{0x11, 0xf4}, {0x12, 0x13}, {0x14, 0x15}, }, +	{ {0x14, 0x15}, {0xbb, 0xe2}, {0xad, 0xed}, {0x01, 0x9b}, {0xa7, 0xe3}, +	{0xac, 0xec}, {0xee, 0x02}, {0xf7, 0x03}, {0x04, 0xf9}, {0x05, 0x06}, +	{0x07, 0x08}, {0xf4, 0xae}, {0xf5, 0x09}, {0x0a, 0xf2}, {0xe1, 0xf3}, +	{0x0b, 0x0c}, {0x0d, 0xe9}, {0x0e, 0x0f}, {0xef, 0xe5}, {0x10, 0xa0}, +	{0xe8, 0x11}, {0x12, 0x13}, }, +	{ {0x11, 0x12}, {0xef, 0xf6}, {0x9b, 0xeb}, {0xf9, 0x01}, {0xa0, 0xe2}, +	{0x02, 0xe1}, {0x03, 0xed}, {0x04, 0xe3}, {0xe9, 0x05}, {0xe4, 0xe5}, +	{0xe7, 0x06}, {0xec, 0xf0}, {0x07, 0x08}, {0x09, 0x0a}, {0x0b, 0xf3}, +	{0x0c, 0xf4}, {0xee, 0x0d}, {0xf2, 0x0e}, {0x0f, 0x10}, }, +	{ {0x05, 0xe5}, {0xf3, 0xf9}, {0x9b, 0x01}, {0xef, 0x02}, {0x03, 0xe1}, +	{0x04, 0xe9}, }, +	{ {0x0a, 0x0b}, {0xae, 0x9b}, {0xec, 0xed}, {0x01, 0x02}, {0xf3, 0xee}, +	{0xf2, 0x03}, {0xe5, 0x04}, {0xe8, 0xa0}, {0xe1, 0x05}, {0xef, 0x06}, +	{0x07, 0x08}, {0xe9, 0x09}, }, +	{ {0x05, 0x06}, {0xa0, 0xac}, {0xad, 0xf4}, {0xe9, 0x01}, {0x02, 0xe1}, +	{0xe5, 0x03}, {0x9b, 0x04}, }, +	{ {0x11, 0xa0}, {0xbf, 0xe1}, {0xe2, 0xe6}, {0xed, 0xe4}, {0xe9, 0xf7}, +	{0xa7, 0x01}, {0x02, 0xbb}, {0x03, 0x04}, {0xec, 0x05}, {0x9b, 0xee}, +	{0x06, 0xef}, {0x07, 0xac}, {0xe5, 0xf3}, {0x08, 0x09}, {0x0a, 0xae}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, {0x0f, 0x10}, }, +	{ {0x06, 0x07}, {0xa0, 0xae}, {0xe1, 0xe5}, {0xec, 0xfa}, {0x9b, 0xef}, +	{0xe9, 0x01}, {0x02, 0x03}, {0x04, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +}; + +static struct hufftree_entry program_title_hufftree[][128] = { +	{ {0x1b, 0x1c}, {0xb4, 0xa4}, {0xb2, 0xb7}, {0xda, 0x01}, {0xd1, 0x02}, +	{0x03, 0x9b}, {0x04, 0xd5}, {0xd9, 0x05}, {0xcb, 0xd6}, {0x06, 0xcf}, +	{0x07, 0x08}, {0xca, 0x09}, {0xc9, 0xc5}, {0xc6, 0x0a}, {0xd2, 0xc4}, +	{0xc7, 0xcc}, {0xd0, 0xc8}, {0xd7, 0xce}, {0x0b, 0xc1}, {0x0c, 0xc2}, +	{0xcd, 0xc3}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xd3, 0x11}, {0xd4, 0x12}, +	{0x13, 0x14}, {0x15, 0x16}, {0x17, 0x18}, {0x19, 0x1a}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x29, 0x2a}, {0xd8, 0xe5}, {0xb9, 0x01}, {0xa7, 0xb1}, {0xec, 0xd1}, +	{0x02, 0xad}, {0xb2, 0xda}, {0xe3, 0xb3}, {0x03, 0xe4}, {0xe6, 0x04}, +	{0x9b, 0xe2}, {0x05, 0x06}, {0x07, 0x08}, {0x09, 0xd5}, {0x0a, 0xd6}, +	{0x0b, 0xd9}, {0x0c, 0xa6}, {0xe9, 0xcb}, {0xc5, 0xcf}, {0x0d, 0x0e}, +	{0xca, 0xc9}, {0x0f, 0xc7}, {0x10, 0x11}, {0xe1, 0x12}, {0x13, 0xc6}, +	{0xd2, 0xc8}, {0xce, 0xc1}, {0xc4, 0xd0}, {0xcc, 0x14}, {0x15, 0xef}, +	{0xc2, 0xd7}, {0x16, 0xcd}, {0x17, 0xf4}, {0xd4, 0x18}, {0x19, 0x1a}, +	{0xc3, 0xd3}, {0x1b, 0x1c}, {0x1d, 0x1e}, {0x1f, 0x20}, {0x21, 0x22}, +	{0x23, 0x24}, {0x25, 0x26}, {0x27, 0x28}, }, +	{ {0x01, 0x80}, {0xa0, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0xb1, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x04, 0xf3}, {0xe4, 0xb9}, {0x01, 0xf4}, {0xa0, 0x9b}, {0x02, 0x03}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x01, 0x02}, {0x9b, 0xc1}, {0xc8, 0xd3}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x07, 0x08}, {0xb1, 0xd2}, {0xd3, 0xd4}, {0xd5, 0xad}, {0xcd, 0xc1}, +	{0x01, 0x02}, {0x03, 0xa0}, {0x04, 0x9b}, {0x05, 0x06}, }, +	{ {0xa0, 0x05}, {0xc9, 0xd7}, {0xd3, 0x01}, {0x02, 0x9b}, {0xae, 0x80}, +	{0x03, 0x04}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0x03}, {0xad, 0x9b}, {0x01, 0x80}, {0xa0, 0xb0}, }, +	{ {0x04, 0x05}, {0x80, 0x9b}, {0xb1, 0xb2}, {0xa0, 0xb0}, {0xb9, 0x01}, +	{0x02, 0x03}, }, +	{ {0x02, 0x03}, {0xb1, 0xba}, {0x01, 0xb0}, {0x9b, 0x80}, }, +	{ {0x80, 0x01}, {0xb0, 0x9b}, }, +	{ {0x9b, 0xb8}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xb0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x02, 0x03}, {0xb1, 0xb3}, {0xb9, 0xb0}, {0x01, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x80}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x13, 0x14}, {0xaa, 0xad}, {0xae, 0xf6}, {0xe7, 0xf4}, {0xe2, 0xe9}, +	{0x01, 0x02}, {0xc2, 0xf0}, {0x9b, 0xf3}, {0xe3, 0xe6}, {0xf7, 0x03}, +	{0xf5, 0x04}, {0x05, 0x06}, {0xf2, 0x07}, {0x08, 0x09}, {0x0a, 0x0b}, +	{0x0c, 0xe4}, {0xa0, 0x0d}, {0xec, 0xee}, {0x0e, 0xed}, {0x0f, 0x10}, +	{0x11, 0x12}, }, +	{ {0x08, 0x09}, {0xc1, 0xd3}, {0x9b, 0x01}, {0xc3, 0x02}, {0xe9, 0xec}, +	{0x03, 0xf2}, {0xf5, 0x04}, {0xef, 0xe1}, {0x05, 0xe5}, {0x06, 0x07}, }, +	{ {0x0b, 0x0c}, {0xc1, 0xf9}, {0x01, 0xc2}, {0xcf, 0xe5}, {0xf5, 0x9b}, +	{0xe9, 0x02}, {0xa0, 0x03}, {0x04, 0x05}, {0xf2, 0x06}, {0xec, 0x07}, +	{0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0xef}, }, +	{ {0x05, 0x06}, {0xf9, 0x9b}, {0x01, 0xf5}, {0x02, 0xf2}, {0xe9, 0xe5}, +	{0xef, 0x03}, {0xe1, 0x04}, }, +	{ {0x0a, 0x0b}, {0xf1, 0xf5}, {0xf3, 0x01}, {0xed, 0xf9}, {0xc3, 0x02}, +	{0xec, 0xee}, {0xe4, 0xf8}, {0x03, 0x9b}, {0xf6, 0x04}, {0x05, 0xe1}, +	{0x06, 0x07}, {0x08, 0x09}, }, +	{ {0x07, 0x08}, {0xa0, 0x9b}, {0xcc, 0x01}, {0xe5, 0x02}, {0xec, 0xf5}, +	{0xef, 0x03}, {0xe9, 0xf2}, {0x04, 0x05}, {0xe1, 0x06}, }, +	{ {0x09, 0x0a}, {0xae, 0xec}, {0xf9, 0xc1}, {0xe8, 0x01}, {0x9b, 0x02}, +	{0x03, 0x04}, {0xe1, 0xf5}, {0xe9, 0x05}, {0xe5, 0x06}, {0xf2, 0xef}, +	{0x07, 0x08}, }, +	{ {0xef, 0x05}, {0x80, 0x9b}, {0xf5, 0x01}, {0x02, 0xe9}, {0xe1, 0x03}, +	{0xe5, 0x04}, }, +	{ {0xee, 0x0b}, {0xba, 0xd4}, {0xae, 0xf2}, {0xe3, 0x01}, {0xa0, 0x02}, +	{0x80, 0x9b}, {0xed, 0x03}, {0xc9, 0xf3}, {0xf4, 0x04}, {0x05, 0x06}, +	{0x07, 0x08}, {0x09, 0x0a}, }, +	{ {0x02, 0x03}, {0x9b, 0xf5}, {0x01, 0xe1}, {0xef, 0xe5}, }, +	{ {0x05, 0xe9}, {0xe1, 0xef}, {0xf5, 0xee}, {0x9b, 0xe5}, {0x01, 0x02}, +	{0x03, 0x04}, }, +	{ {0x04, 0x05}, {0xa0, 0x9b}, {0x01, 0xf5}, {0x02, 0xe5}, {0xef, 0x03}, +	{0xe1, 0xe9}, }, +	{ {0x08, 0x09}, {0xaa, 0xd4}, {0x01, 0x9b}, {0xe3, 0x02}, {0xf2, 0x03}, +	{0xe5, 0x04}, {0xf5, 0xf9}, {0xe9, 0x05}, {0xef, 0x06}, {0x07, 0xe1}, }, +	{ {0xe5, 0x08}, {0xce, 0xa0}, {0xc6, 0xf5}, {0x01, 0x02}, {0x9b, 0xc2}, +	{0x03, 0xe1}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0x07}, }, +	{ {0x09, 0x0a}, {0xe4, 0xf3}, {0xe6, 0xf6}, {0xf7, 0xf0}, {0xf2, 0x01}, +	{0xec, 0x02}, {0x03, 0xa0}, {0x9b, 0x04}, {0x05, 0xf5}, {0x06, 0x07}, +	{0xee, 0x08}, }, +	{ {0x0b, 0x0c}, {0xa0, 0xf3}, {0xf9, 0xae}, {0xd2, 0xc7}, {0x01, 0x9b}, +	{0x02, 0xf5}, {0x03, 0x04}, {0x05, 0xe9}, {0xec, 0x06}, {0xe5, 0x07}, +	{0xef, 0x08}, {0xe1, 0x09}, {0xf2, 0x0a}, }, +	{ {0x01, 0xf5}, {0x9b, 0xd6}, }, +	{ {0x04, 0x05}, {0xe8, 0x9b}, {0x01, 0xf5}, {0x02, 0xe1}, {0xe9, 0xef}, +	{0x03, 0xe5}, }, +	{ {0x10, 0x11}, {0xaa, 0xec}, {0xf1, 0xae}, {0xa0, 0xf7}, {0xed, 0xee}, +	{0x01, 0x02}, {0x9b, 0xeb}, {0x03, 0x04}, {0x05, 0x06}, {0xe3, 0x07}, +	{0xef, 0x08}, {0xe9, 0xf5}, {0x09, 0xe1}, {0xe5, 0xf0}, {0xe8, 0x0a}, +	{0x0b, 0x0c}, {0x0d, 0xf4}, {0x0e, 0x0f}, }, +	{ {0xe8, 0x0a}, {0xad, 0xce}, {0x9b, 0x01}, {0xd6, 0x02}, {0xf5, 0xf7}, +	{0x03, 0x04}, {0xe1, 0xe5}, {0xe9, 0x05}, {0xf2, 0x06}, {0xef, 0x07}, +	{0x08, 0x09}, }, +	{ {0xee, 0x03}, {0xec, 0xae}, {0x01, 0x9b}, {0x02, 0xf0}, }, +	{ {0x06, 0xe9}, {0xa0, 0xc3}, {0xef, 0x9b}, {0xe5, 0x01}, {0x80, 0x02}, +	{0x03, 0xe1}, {0x04, 0x05}, }, +	{ {0x06, 0x07}, {0xc6, 0xd7}, {0x01, 0x9b}, {0xf2, 0x02}, {0x03, 0xe8}, +	{0xe5, 0xe1}, {0x04, 0xe9}, {0xef, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0xef}, {0xe1, 0x9b}, {0x01, 0xe5}, }, +	{ {0x01, 0xef}, {0x9b, 0xe1}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x19, 0x1a}, {0x9b, 0xba}, {0xe5, 0xea}, {0xf8, 0x01}, {0x02, 0xe6}, +	{0xa7, 0x03}, {0xfa, 0xe8}, {0x04, 0xf7}, {0x05, 0xf5}, {0xe2, 0x06}, +	{0xeb, 0x07}, {0xf0, 0x08}, {0x80, 0xf6}, {0xe7, 0x09}, {0xe4, 0x0a}, +	{0xa0, 0xe9}, {0x0b, 0xe3}, {0xf9, 0x0c}, {0x0d, 0xed}, {0x0e, 0x0f}, +	{0xf3, 0x10}, {0x11, 0xec}, {0x12, 0xf4}, {0xf2, 0x13}, {0xee, 0x14}, +	{0x15, 0x16}, {0x17, 0x18}, }, +	{ {0x0a, 0x0b}, {0xf3, 0x9b}, {0xf5, 0xe2}, {0x01, 0x80}, {0xa0, 0x02}, +	{0xe5, 0xf2}, {0xe9, 0x03}, {0xec, 0x04}, {0xf9, 0x05}, {0xef, 0x06}, +	{0xe1, 0x07}, {0x08, 0x09}, }, +	{ {0x10, 0x11}, {0xc3, 0xcc}, {0xc7, 0x9b}, {0xe3, 0x01}, {0x80, 0xec}, +	{0xf9, 0x02}, {0xf3, 0x03}, {0xf5, 0x04}, {0x05, 0xf2}, {0x06, 0xe9}, +	{0xa0, 0x07}, {0x08, 0xef}, {0xf4, 0x09}, {0x0a, 0xe1}, {0x0b, 0xe8}, +	{0xeb, 0xe5}, {0x0c, 0x0d}, {0x0e, 0x0f}, }, +	{ {0x0e, 0x0f}, {0xae, 0xf5}, {0xf7, 0x01}, {0xec, 0x02}, {0xe4, 0xe7}, +	{0xf2, 0x03}, {0x9b, 0xef}, {0x04, 0xf6}, {0x05, 0x06}, {0xf9, 0xf3}, +	{0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0x80}, {0x0a, 0x0b}, {0xe5, 0x0c}, +	{0x0d, 0xa0}, }, +	{ {0x1e, 0x1f}, {0x9b, 0xa1}, {0xad, 0xe8}, {0xea, 0xf1}, {0xf5, 0xfa}, +	{0x01, 0x02}, {0x03, 0x04}, {0xba, 0xf8}, {0xa7, 0xe2}, {0xe9, 0x05}, +	{0x06, 0x07}, {0xe6, 0xed}, {0xe7, 0xeb}, {0x08, 0x09}, {0xf6, 0xf0}, +	{0x0a, 0xef}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0xf9}, {0x0f, 0xe4}, +	{0xec, 0x10}, {0xe5, 0x11}, {0xf4, 0xf7}, {0x12, 0x13}, {0xe1, 0x14}, +	{0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x80}, {0x18, 0x19}, {0xf2, 0x1a}, +	{0x1b, 0xa0}, {0x1c, 0x1d}, }, +	{ {0xa0, 0x0b}, {0xf5, 0x9b}, {0x01, 0xec}, {0xf3, 0xf2}, {0x80, 0xe1}, +	{0x02, 0x03}, {0xf4, 0xe9}, {0xef, 0xe6}, {0x04, 0x05}, {0x06, 0x07}, +	{0xe5, 0x08}, {0x09, 0x0a}, }, +	{ {0x0f, 0x10}, {0xba, 0xf9}, {0xa7, 0xf4}, {0x9b, 0x01}, {0xe7, 0xec}, +	{0x02, 0xee}, {0x03, 0xef}, {0xf5, 0x04}, {0xf2, 0x05}, {0x06, 0xe9}, +	{0x07, 0xf3}, {0xe1, 0x08}, {0x09, 0x0a}, {0x0b, 0xe5}, {0x80, 0x0c}, +	{0xe8, 0xa0}, {0x0d, 0x0e}, }, +	{ {0xe5, 0x0d}, {0xe2, 0xf5}, {0xf7, 0x9b}, {0xec, 0x01}, {0xf9, 0xee}, +	{0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x80}, {0x06, 0xa0}, {0xe1, 0xef}, +	{0x07, 0xf4}, {0xe9, 0x08}, {0x09, 0x0a}, {0x0b, 0x0c}, }, +	{ {0x15, 0x16}, {0xa1, 0xf8}, {0xe9, 0xeb}, {0x01, 0x80}, {0x9b, 0xfa}, +	{0xe2, 0x02}, {0x03, 0x04}, {0xa0, 0xf0}, {0x05, 0x06}, {0x07, 0xe1}, +	{0x08, 0xe6}, {0xf2, 0xed}, {0xf6, 0x09}, {0xe4, 0x0a}, {0xef, 0xf4}, +	{0xec, 0xf3}, {0xe7, 0xe5}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0x0f}, +	{0x10, 0x11}, {0x12, 0x13}, {0xee, 0x14}, }, +	{ {0xef, 0x01}, {0x9b, 0xe1}, }, +	{ {0x0b, 0x0c}, {0xd4, 0xef}, {0xe6, 0xec}, {0xf7, 0xe1}, {0x01, 0xba}, +	{0x02, 0x9b}, {0xf9, 0x03}, {0x04, 0x05}, {0xf3, 0x06}, {0x07, 0x08}, +	{0xe9, 0xa0}, {0x09, 0x80}, {0xe5, 0x0a}, }, +	{ {0x15, 0x16}, {0xa7, 0xba}, {0xe3, 0xf7}, {0xf2, 0xad}, {0xe2, 0x01}, +	{0x02, 0x9b}, {0xe6, 0x03}, {0xed, 0xf6}, {0x04, 0xeb}, {0x05, 0xf4}, +	{0x06, 0x07}, {0x08, 0xf3}, {0x09, 0xf5}, {0x0a, 0xef}, {0x0b, 0x0c}, +	{0x80, 0xf9}, {0xe1, 0x0d}, {0xe4, 0xe9}, {0xa0, 0x0e}, {0x0f, 0xec}, +	{0xe5, 0x10}, {0x11, 0x12}, {0x13, 0x14}, }, +	{ {0x0a, 0x0b}, {0xf9, 0x9b}, {0xf5, 0xf3}, {0x01, 0x02}, {0xe2, 0xed}, +	{0x80, 0x03}, {0xf0, 0xef}, {0x04, 0xa0}, {0x05, 0xe9}, {0x06, 0xe1}, +	{0x07, 0x08}, {0x09, 0xe5}, }, +	{ {0x18, 0x19}, {0xe2, 0xea}, {0xf2, 0xe8}, {0xec, 0xed}, {0xfa, 0x9b}, +	{0x01, 0xf5}, {0x02, 0x03}, {0xf6, 0x04}, {0xba, 0xe6}, {0x05, 0x06}, +	{0xeb, 0xef}, {0x07, 0xa7}, {0xf9, 0x08}, {0x09, 0x0a}, {0x0b, 0xe3}, +	{0x0c, 0xee}, {0xe1, 0x0d}, {0xf3, 0x0e}, {0xe9, 0x0f}, {0x10, 0xf4}, +	{0x80, 0xe4}, {0xe5, 0x11}, {0x12, 0xe7}, {0xa0, 0x13}, {0x14, 0x15}, +	{0x16, 0x17}, }, +	{ {0x1b, 0x1c}, {0xae, 0xfa}, {0xbf, 0x01}, {0xa7, 0x9b}, {0x02, 0xe9}, +	{0xf8, 0xf9}, {0x03, 0xe5}, {0xe8, 0x04}, {0xe1, 0xeb}, {0x05, 0xe2}, +	{0x06, 0x07}, {0xe3, 0x08}, {0xe7, 0xf4}, {0x09, 0x80}, {0xf6, 0xf0}, +	{0x0a, 0xe4}, {0x0b, 0xf3}, {0xf7, 0x0c}, {0x0d, 0xef}, {0xec, 0xa0}, +	{0x0e, 0x0f}, {0xed, 0xe6}, {0x10, 0xf5}, {0x11, 0x12}, {0x13, 0x14}, +	{0x15, 0xf2}, {0x16, 0xee}, {0x17, 0x18}, {0x19, 0x1a}, }, +	{ {0x0e, 0x0f}, {0xed, 0xa7}, {0x9b, 0xe4}, {0x01, 0xf9}, {0xf3, 0xf2}, +	{0xf4, 0x02}, {0xe8, 0x03}, {0xec, 0xf0}, {0x04, 0xe1}, {0xe9, 0x05}, +	{0x06, 0x80}, {0xa0, 0x07}, {0x08, 0x09}, {0x0a, 0xe5}, {0xef, 0x0b}, +	{0x0c, 0x0d}, }, +	{ {0x9b, 0xf5}, }, +	{ {0x18, 0x19}, {0xba, 0xac}, {0xf6, 0x9b}, {0xf0, 0xe2}, {0x01, 0xe6}, +	{0x02, 0xa7}, {0xae, 0xe7}, {0x03, 0xe3}, {0xf5, 0x04}, {0xed, 0x05}, +	{0x06, 0x07}, {0xeb, 0x08}, {0x09, 0xee}, {0xf2, 0x0a}, {0xe4, 0x0b}, +	{0xf9, 0xec}, {0x0c, 0x0d}, {0xf4, 0x80}, {0x0e, 0xef}, {0xf3, 0xa0}, +	{0xe1, 0x0f}, {0xe9, 0x10}, {0x11, 0xe5}, {0x12, 0x13}, {0x14, 0x15}, +	{0x16, 0x17}, }, +	{ {0x19, 0x1a}, {0xa7, 0xac}, {0xbf, 0xc3}, {0xc8, 0xe4}, {0xe6, 0xed}, +	{0xf2, 0xae}, {0xec, 0xee}, {0xf9, 0x01}, {0x02, 0x03}, {0x04, 0xba}, +	{0x05, 0x9b}, {0xf5, 0x06}, {0x07, 0x08}, {0x09, 0xeb}, {0xf0, 0x0a}, +	{0x0b, 0x0c}, {0xe1, 0xe3}, {0x0d, 0xe8}, {0x0e, 0x0f}, {0xef, 0x10}, +	{0x11, 0xf3}, {0x12, 0xe9}, {0x13, 0xe5}, {0x14, 0x15}, {0xf4, 0x16}, +	{0x17, 0xa0}, {0x18, 0x80}, }, +	{ {0x14, 0x15}, {0xba, 0xbf}, {0xe4, 0xf7}, {0x9b, 0xa7}, {0x01, 0xee}, +	{0x02, 0x03}, {0x04, 0xe3}, {0xe2, 0xed}, {0x05, 0xf9}, {0x06, 0xf4}, +	{0x07, 0xec}, {0x08, 0xf5}, {0xf2, 0x09}, {0xe1, 0xf3}, {0x0a, 0xef}, +	{0x0b, 0x0c}, {0x0d, 0xe9}, {0x80, 0xe5}, {0x0e, 0xa0}, {0x0f, 0xe8}, +	{0x10, 0x11}, {0x12, 0x13}, }, +	{ {0x11, 0x12}, {0xeb, 0xfa}, {0x80, 0xe6}, {0x9b, 0x01}, {0xa0, 0x02}, +	{0x03, 0xe9}, {0xe1, 0x04}, {0xe4, 0xf0}, {0xed, 0xe2}, {0xe3, 0xe7}, +	{0xec, 0x05}, {0xe5, 0x06}, {0x07, 0x08}, {0x09, 0xf4}, {0x0a, 0x0b}, +	{0x0c, 0xf3}, {0xee, 0x0d}, {0x0e, 0xf2}, {0x0f, 0x10}, }, +	{ {0x04, 0xe5}, {0xf3, 0xef}, {0x9b, 0x01}, {0xe1, 0x02}, {0x03, 0xe9}, }, +	{ {0x0b, 0x0c}, {0xa7, 0xe2}, {0xec, 0xe3}, {0xf2, 0x01}, {0x9b, 0x02}, +	{0x03, 0x04}, {0xe9, 0xef}, {0xee, 0xe5}, {0xe1, 0x80}, {0x05, 0xa0}, +	{0x06, 0x07}, {0x08, 0x09}, {0xf3, 0x0a}, }, +	{ {0x05, 0x06}, {0x9b, 0xa0}, {0xe1, 0xe5}, {0xe9, 0x01}, {0x80, 0xf0}, +	{0x02, 0xf4}, {0x03, 0x04}, }, +	{ {0xa0, 0x13}, {0xe3, 0xad}, {0xe4, 0xe9}, {0xee, 0xef}, {0xf0, 0xf4}, +	{0xf6, 0xa1}, {0xe1, 0xed}, {0x01, 0xe2}, {0x02, 0x03}, {0x04, 0xa7}, +	{0x05, 0x06}, {0xf7, 0x07}, {0x9b, 0xec}, {0x08, 0xe5}, {0x09, 0x0a}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, {0xf3, 0x0f}, {0x10, 0x11}, {0x80, 0x12}, }, +	{ {0x05, 0x06}, {0xe5, 0xfa}, {0xa0, 0xf9}, {0x9b, 0x01}, {0x80, 0xe9}, +	{0x02, 0xe1}, {0x03, 0x04}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +}; + + + +static inline void huffbuff_init(struct huffbuff *hbuf, uint8_t *buf, uint32_t buf_len) +{ +	memset(hbuf, 0, sizeof(struct huffbuff)); +	hbuf->buf = buf; +	hbuf->buf_len = buf_len; +} + +static inline int huffbuff_bits(struct huffbuff *hbuf, uint8_t nbits) +{ +	uint8_t result = 0; + +	if (nbits > 8) +		return -1; + +	while(nbits--) { +		if (hbuf->cur_byte >= hbuf->buf_len) { +			return -1; +		} + +		result <<= 1; +		if (hbuf->buf[hbuf->cur_byte] & (0x80 >> hbuf->cur_bit)) +			result |= 1; + +		if (++hbuf->cur_bit > 7) { +			hbuf->cur_byte++; +			hbuf->cur_bit = 0; +		} +	} + +	return result; +} + +static inline int append_unicode_char(uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos, +				      uint32_t c) +{ +	uint8_t tmp[3]; +	int tmplen = 0; + +	// encode the unicode character first of all +	if (c < 0x80) { +		tmp[0] = c; +		tmplen = 1; +	} else if (c < 0x800) { +		tmp[0] = 0xc0 | ((c >> 6) & 0x1f); +		tmp[1] = 0x80 | (c & 0x3f); +		tmplen = 2; +	} else if (c < 0x10000) { +		tmp[0] = 0xe0 | ((c >> 12) & 0x0f); +		tmp[1] = 0x80 | ((c >> 6) & 0x3f); +		tmp[2] = 0x80 | (c & 0x3f); +		tmplen = 3; +	} else { +		return -1; +	} + +	// do we have enough buffer space? +	if ((*destbufpos + tmplen) >= *destbuflen) { +		uint8_t *new_dest = realloc(*destbuf, *destbuflen + DEST_ALLOC_DELTA); +		if (new_dest == NULL) +			return -ENOMEM; +		*destbuf = new_dest; +		*destbuflen += DEST_ALLOC_DELTA; +	} + +	// copy it into position +	memcpy(*destbuf + *destbufpos, tmp, tmplen); +	*destbufpos += tmplen; + +	return 0; +} + +static inline int unicode_decode(uint8_t *srcbuf, size_t srcbuflen, int mode, +				 uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos) +{ +	size_t i; +	uint32_t msb = mode << 8; + +	for(i=0; i< srcbuflen; i++) { +		if (append_unicode_char(destbuf, destbuflen, destbufpos, msb + srcbuf[i])) +			return -1; +	} + +	return *destbufpos; +} + +static int huffman_decode_uncompressed(struct huffbuff *hbuf, +				       uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos) +{ +	int c; + +	while(hbuf->cur_byte < hbuf->buf_len) { +		// get next byte +		if ((c = huffbuff_bits(hbuf, 8)) < 0) +			return -1; + +		switch(c) { +		case HUFFSTRING_END: +			return 0; + +		case HUFFSTRING_ESCAPE: +			return HUFFSTRING_ESCAPE; + +		default: +			if (append_unicode_char(destbuf, destbuflen, destbufpos, c)) +				return -1; + +			// if it is 7 bit, we swap back to the compressed context +			if ((c & 0x80) == 0) +				return c; + +			// characters following an 8 bit uncompressed char are uncompressed as well +			break; +		} +	} + +	// ran out of string; pretend we saw an end of string char +	return HUFFSTRING_END; +} + +static int huffman_decode(uint8_t *src, size_t srclen, +			  uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos, +			  struct hufftree_entry hufftree[][128]) +{ +	struct huffbuff hbuf; +	int bit; +	struct hufftree_entry *tree = hufftree[0]; +	uint8_t treeidx = 0; +	uint8_t treeval; +	int tmp; + +	huffbuff_init(&hbuf, src, srclen); + +	while(hbuf.cur_byte < hbuf.buf_len) { +		// get the next bit +		if ((bit = huffbuff_bits(&hbuf, 1)) < 0) +			return *destbufpos; + +		if (!bit) { +			treeval = tree[treeidx].left_idx; +		} else { +			treeval = tree[treeidx].right_idx; +		} + +		if (treeval & HUFFTREE_LITERAL_MASK) { +			switch(treeval & ~HUFFTREE_LITERAL_MASK) { +			case HUFFSTRING_END: +				return 0; + +			case HUFFSTRING_ESCAPE: +				if ((tmp = +					huffman_decode_uncompressed(&hbuf, +							destbuf, destbuflen, destbufpos)) < 0) +					return tmp; +				if (tmp == 0) +					return *destbufpos; + +				tree = hufftree[tmp]; +				treeidx = 0; +				break; + +			default: +				// stash it +				if (append_unicode_char(destbuf, destbuflen, destbufpos, +				    			treeval & ~HUFFTREE_LITERAL_MASK)) +					return -1; +				tree = hufftree[treeval & ~HUFFTREE_LITERAL_MASK]; +				treeidx = 0; +				break; +			} +		} else { +			treeidx = treeval; +		} +	} + +	return *destbufpos; +} + +int atsc_text_segment_decode(struct atsc_text_string_segment *segment, +			     uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos) +{ +	if (segment->mode > ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX) +		return -1; + +	// mode==0 MUST be used for compressed text +	if ((segment->mode) && (segment->compression_type)) +		return -1; + +	uint8_t *buf = atsc_text_string_segment_bytes(segment); + +	switch(segment->compression_type) { +	case ATSC_TEXT_COMPRESS_NONE: +		return unicode_decode(buf, segment->number_bytes, segment->mode, +				      destbuf, destbufsize, destbufpos); + +	case ATSC_TEXT_COMPRESS_PROGRAM_TITLE: +		return huffman_decode(buf, segment->number_bytes, +				      destbuf, destbufsize, destbufpos, +				      program_title_hufftree); + +	case ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION: +		return huffman_decode(buf, segment->number_bytes, +				      destbuf, destbufsize, destbufpos, +				      program_description_hufftree); +	} + +	return -1; +} diff --git a/lib/libucsi/atsc/caption_service_descriptor.h b/lib/libucsi/atsc/caption_service_descriptor.h new file mode 100644 index 0000000..29d1794 --- /dev/null +++ b/lib/libucsi/atsc/caption_service_descriptor.h @@ -0,0 +1,137 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR +#define _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_caption_service_descriptor structure. + */ +struct atsc_caption_service_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t number_of_services	: 5; ); +	/* struct atsc_caption_service_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_caption_service_descriptor. + */ +struct atsc_caption_service_entry { +	iso639lang_t language_code; +  EBIT3(uint8_t digital_cc 		: 1; , +	uint8_t reserved		: 1; , +	uint8_t value			: 6; ); +  EBIT3(uint16_t easy_reader 		: 1; , +	uint16_t wide_aspect_ratio	: 1; , +	uint16_t reserved1		:14; ); +} __ucsi_packed; + +/** + * Process an atsc_caption_service_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_caption_service_descriptor pointer, or NULL on error. + */ +static inline struct atsc_caption_service_descriptor* +	atsc_caption_service_descriptor_codec(struct descriptor* d) +{ +	struct atsc_caption_service_descriptor *ret = +		(struct atsc_caption_service_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->number_of_services; idx++) { +		if (d->len < (pos + sizeof(struct atsc_caption_service_entry))) +			return NULL; + +		bswap16(buf+pos+4); + +		pos += sizeof(struct atsc_caption_service_entry); +	} + +	return (struct atsc_caption_service_descriptor*) d; +} + +/** + * Iterator for entries field of a atsc_caption_service_descriptor. + * + * @param d atsc_caption_service_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_caption_service_entry. + * @param idx Field iterator integer. + */ +#define atsc_caption_service_descriptor_entries_for_each(d, pos, idx) \ +	for ((pos) = atsc_caption_service_descriptor_entries_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_caption_service_descriptor_entries_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_caption_service_entry* +	atsc_caption_service_descriptor_entries_first(struct atsc_caption_service_descriptor *d) +{ +	if (d->number_of_services == 0) +		return NULL; + +	return (struct atsc_caption_service_entry *) +		((uint8_t*) d + sizeof(struct atsc_caption_service_descriptor)); +} + +static inline struct atsc_caption_service_entry* +	atsc_caption_service_descriptor_entries_next(struct atsc_caption_service_descriptor *d, +						     struct atsc_caption_service_entry *pos, +						     int idx) +{ +	if (idx >= d->number_of_services) +		return NULL; + +	return (struct atsc_caption_service_entry *) +		((uint8_t *) pos + sizeof(struct atsc_caption_service_entry)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/component_name_descriptor.h b/lib/libucsi/atsc/component_name_descriptor.h new file mode 100644 index 0000000..3b9cab7 --- /dev/null +++ b/lib/libucsi/atsc/component_name_descriptor.h @@ -0,0 +1,92 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR +#define _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_component_name_descriptor structure. + */ +struct atsc_component_name_descriptor { +	struct descriptor d; + +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_component_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_component_name_descriptor pointer, or NULL on error. + */ +static inline struct atsc_component_name_descriptor* +	atsc_component_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor); + +	if (atsc_text_validate(txt, d->len)) +		return NULL; + +	return (struct atsc_component_name_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_component_name_descriptor. + * + * @param d atsc_component_name_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_component_name_descriptor_text(struct atsc_component_name_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_component_name_descriptor_text. + * + * @param d atsc_component_name_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_component_name_descriptor_text_length(struct atsc_component_name_descriptor *d) +{ +	return d->d.len; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/content_advisory_descriptor.h b/lib/libucsi/atsc/content_advisory_descriptor.h new file mode 100644 index 0000000..da19813 --- /dev/null +++ b/lib/libucsi/atsc/content_advisory_descriptor.h @@ -0,0 +1,235 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR +#define _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_content_advisory_descriptor structure. + */ +struct atsc_content_advisory_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 2; , +	uint8_t rating_region_count	: 6; ); +	/* struct atsc_content_advisory_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_content_advisory_descriptor. + */ +struct atsc_content_advisory_entry { +	uint8_t rating_region; +	uint8_t rated_dimensions; +	/* struct atsc_content_advisory_entry_dimension dimensions[] */ +	/* struct atsc_content_advisory_entry_part2 part2 */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_content_advisory_descriptor. + */ +struct atsc_content_advisory_entry_dimension { +	uint8_t rating_dimension_j; +  EBIT2(uint8_t reserved		: 4; , +	uint8_t rating_value		: 4; ); +} __ucsi_packed; + +/** + * Part2 of an atsc_content_advisory_entry. + */ +struct atsc_content_advisory_entry_part2 { +	uint8_t rating_description_length; +	/* struct atsc_text description */ +} __ucsi_packed; + +/** + * Process an atsc_content_advisory_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_content_advisory_descriptor pointer, or NULL on error. + */ +static inline struct atsc_content_advisory_descriptor* +	atsc_content_advisory_descriptor_codec(struct descriptor* d) +{ +	struct atsc_content_advisory_descriptor *ret = +		(struct atsc_content_advisory_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->rating_region_count; idx++) { +		if (d->len < (pos + sizeof(struct atsc_content_advisory_entry))) +			return NULL; +		struct atsc_content_advisory_entry *entry = +			(struct atsc_content_advisory_entry *) (buf + pos); +		pos += sizeof(struct atsc_content_advisory_entry); + +		if (d->len < (pos + (sizeof(struct atsc_content_advisory_entry_dimension) * +				  entry->rated_dimensions))) +			return NULL; +		pos += sizeof(struct atsc_content_advisory_entry_dimension) * entry->rated_dimensions; + +		if (d->len < (pos + sizeof(struct atsc_content_advisory_entry_part2))) +			return NULL; +		struct atsc_content_advisory_entry_part2 *part2 = +				(struct atsc_content_advisory_entry_part2 *) (buf + pos); +		pos += sizeof(struct atsc_content_advisory_entry_part2); + +		if (d->len < (pos + part2->rating_description_length)) +			return NULL; + +		if (atsc_text_validate(buf+pos, part2->rating_description_length)) +			return NULL; + +		pos += part2->rating_description_length; +	} + +	return (struct atsc_content_advisory_descriptor*) d; +} + +/** + * Iterator for entries field of a atsc_content_advisory_descriptor. + * + * @param d atsc_content_advisory_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_content_advisory_entry. + * @param idx Integer used to count which entry we are in. + */ +#define atsc_content_advisory_descriptor_entries_for_each(d, pos, idx) \ +	for ((pos) = atsc_content_advisory_descriptor_entries_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_content_advisory_descriptor_entries_next(d, pos, ++idx)) + +/** + * Iterator for dimensions field of a atsc_content_advisory_entry. + * + * @param d atsc_content_advisory_entry pointer. + * @param pos Variable holding a pointer to the current atsc_content_advisory_entry_dimension. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_content_advisory_entry_dimensions_for_each(d, pos, idx) \ +	for ((pos) = atsc_content_advisory_entry_dimensions_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_content_advisory_entry_dimensions_next(d, pos, ++idx)) + +/** + * Accessor for the part2 field of an atsc_content_advisory_entry. + * + * @param entry atsc_content_advisory_entry pointer. + * @return struct atsc_content_advisory_entry_part2 pointer. + */ +static inline struct atsc_content_advisory_entry_part2 * +	atsc_content_advisory_entry_part2(struct atsc_content_advisory_entry *entry) +{ +	int pos = sizeof(struct atsc_content_advisory_entry); +	pos += entry->rated_dimensions * sizeof(struct atsc_content_advisory_entry_dimension); + +	return (struct atsc_content_advisory_entry_part2 *) (((uint8_t*) entry) + pos); +} + + +/** + * Accessor for the description field of an atsc_content_advisory_entry_part2. + * + * @param part2 atsc_content_advisory_entry_part2 pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_content_advisory_entry_part2_description(struct atsc_content_advisory_entry_part2 *part2) +{ +	uint8_t *txt = ((uint8_t*) part2) + sizeof(struct atsc_content_advisory_entry_part2); + +	return (struct atsc_text *) txt; +} + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_content_advisory_entry* +	atsc_content_advisory_descriptor_entries_first(struct atsc_content_advisory_descriptor *d) +{ +	if (d->rating_region_count == 0) +		return NULL; + +	return (struct atsc_content_advisory_entry *) +		((uint8_t*) d + sizeof(struct atsc_content_advisory_descriptor)); +} + +static inline struct atsc_content_advisory_entry* +	atsc_content_advisory_descriptor_entries_next(struct atsc_content_advisory_descriptor *d, +						      struct atsc_content_advisory_entry *pos, +						      int idx) +{ +	if (idx >= d->rating_region_count) +		return NULL; +	struct atsc_content_advisory_entry_part2 *part2 = +		atsc_content_advisory_entry_part2(pos); + +	return (struct atsc_content_advisory_entry *) +		((uint8_t *) part2 + +		 sizeof(struct atsc_content_advisory_entry_part2) + +		 part2->rating_description_length); +} + +static inline struct atsc_content_advisory_entry_dimension* +	atsc_content_advisory_entry_dimensions_first(struct atsc_content_advisory_entry *e) +{ +	if (e->rated_dimensions == 0) +		return NULL; + +	return (struct atsc_content_advisory_entry_dimension *) +		((uint8_t*) e + sizeof(struct atsc_content_advisory_entry)); +} + +static inline struct atsc_content_advisory_entry_dimension* +	atsc_content_advisory_entry_dimensions_next(struct atsc_content_advisory_entry *e, +				   		    struct atsc_content_advisory_entry_dimension *pos, +						    int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_content_advisory_entry_dimension); + +	if (idx >= e->rated_dimensions) +		return NULL; +	return (struct atsc_content_advisory_entry_dimension *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/cvct_section.c b/lib/libucsi/atsc/cvct_section.c new file mode 100644 index 0000000..6edbc03 --- /dev/null +++ b/lib/libucsi/atsc/cvct_section.c @@ -0,0 +1,77 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/cvct_section.h> + +struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_cvct_section)) +		return NULL; +	struct atsc_cvct_section *cvct = (struct atsc_cvct_section *) psip; + +	pos++; +	for(idx =0; idx < cvct->num_channels_in_section; idx++) { +		if ((pos + sizeof(struct atsc_cvct_channel)) > len) +			return NULL; +		struct atsc_cvct_channel *channel = (struct atsc_cvct_channel *) (buf+pos); + +		pos += 7*2; + +		bswap32(buf+pos); +		bswap32(buf+pos+4); +		bswap16(buf+pos+8); +		bswap16(buf+pos+10); +		bswap16(buf+pos+12); +		bswap16(buf+pos+14); +		bswap16(buf+pos+16); +		pos+=18; + +		if ((pos + channel->descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, channel->descriptors_length)) +			return NULL; + +		pos += channel->descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_cvct_section_part2)) > len) +		return NULL; +	struct atsc_cvct_section_part2 *part2 = (struct atsc_cvct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); +	pos+=2; + +	if ((pos + part2->descriptors_length) > len) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_cvct_section *) psip; +} diff --git a/lib/libucsi/atsc/cvct_section.h b/lib/libucsi/atsc/cvct_section.h new file mode 100644 index 0000000..c3d418a --- /dev/null +++ b/lib/libucsi/atsc/cvct_section.h @@ -0,0 +1,228 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_CVCT_SECTION_H +#define _UCSI_ATSC_CVCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +/** + * atsc_cvct_section structure. + */ +struct atsc_cvct_section { +	struct atsc_section_psip head; + +	uint8_t num_channels_in_section; +	/* struct atsc_cvct_channel channels[] */ + 	/* struct atsc_cvct_channel_part2 part2 */ +} __ucsi_packed; + +struct atsc_cvct_channel { +	uint16_t short_name[7]; // UTF-16 network ordered +  EBIT4(uint32_t reserved			: 4; , +	uint32_t major_channel_number		:10; , +  	uint32_t minor_channel_number		:10; , +	uint32_t modulation_mode		: 8; ); +	uint32_t carrier_frequency; +	uint16_t channel_TSID; +	uint16_t program_number; +  EBIT8(uint16_t ETM_location			: 2; , +	uint16_t access_controlled		: 1; , +	uint16_t hidden				: 1; , +	uint16_t path_select			: 1; , +	uint16_t out_of_band			: 1; , +	uint16_t hide_guide			: 1; , +	uint16_t reserved2			: 3; , +	uint16_t service_type			: 6; ); +	uint16_t source_id; +  EBIT2(uint16_t reserved3			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_cvct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_cvct_channel *atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct); +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct, struct atsc_cvct_channel *pos, int idx); + +/** + * Process a atsc_cvct_section. + * + * @param section Pointer to anj atsc_section_psip structure. + * @return atsc_cvct_section pointer, or NULL on error. + */ +struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the transport_stream_id field of a CVCT. + * + * @param cvdt CVDT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t atsc_cvct_section_transport_stream_id(struct atsc_cvct_section *cvct) +{ +	return cvct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the tables field in an atsc_cvct_section. + * + * @param mgt atsc_cvct_section pointer. + * @param pos Variable containing a pointer to the current atsc_cvct_channel. + * @param idx Integer used to count which table we in. + */ +#define atsc_cvct_section_channels_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_cvct_section_channels_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_cvct_section_channels_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_cvct_channel structure. + * + * @param table atsc_cvct_channel pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_cvct_channel_descriptors_for_each(table, pos) \ +	for ((pos) = atsc_cvct_channel_descriptors_first(table); \ +	     (pos); \ +	     (pos) = atsc_cvct_channel_descriptors_next(table, pos)) + +/** + * Accessor for the second part of an atsc_cvct_section. + * + * @param mgt atsc_cvct_section pointer. + * @return atsc_cvct_section_part2 pointer. + */ +static inline struct atsc_cvct_section_part2 * +	atsc_cvct_section_part2(struct atsc_cvct_section *mgt) +{ +	int pos = sizeof(struct atsc_cvct_section); + +	struct atsc_cvct_channel *cur_table; +	int idx; +	atsc_cvct_section_channels_for_each(mgt, cur_table, idx) { +		pos += sizeof(struct atsc_cvct_channel); +		pos += cur_table->descriptors_length; +	} + +	return (struct atsc_cvct_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_cvct_section structure. + * + * @param part2 atsc_cvct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_cvct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_cvct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_cvct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct) +{ +	size_t pos = sizeof(struct atsc_cvct_section); + +	if (cvct->num_channels_in_section == 0) +		return NULL; + +	return (struct atsc_cvct_channel*) (((uint8_t *) cvct) + pos); +} + +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct, +				     struct atsc_cvct_channel *pos, +				     int idx) +{ +	if (idx >= cvct->num_channels_in_section) +		return NULL; + +	return (struct atsc_cvct_channel *) +		(((uint8_t*) pos) + sizeof(struct atsc_cvct_channel) + pos->descriptors_length); +} + +static inline struct descriptor * +	atsc_cvct_channel_descriptors_first(struct atsc_cvct_channel *table) +{ +	size_t pos = sizeof(struct atsc_cvct_channel); + +	if (table->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) table) + pos); +} + +static inline struct descriptor * +	atsc_cvct_channel_descriptors_next(struct atsc_cvct_channel *table, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) table + sizeof(struct atsc_cvct_channel), +				table->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_cvct_section_part2_descriptors_first(struct atsc_cvct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_cvct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_cvct_section_part2_descriptors_next(struct atsc_cvct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_cvct_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcc_arriving_request_descriptor.h b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h new file mode 100644 index 0000000..af76eac --- /dev/null +++ b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h @@ -0,0 +1,107 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR +#define _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_dcc_arriving_request_type { +	DCC_ARRIVAL_TYPE_DEFER_10SEC	= 0x01, +	DCC_ARRIVAL_TYPE_DEFER		= 0x02, +}; + +/** + * atsc_dcc_arriving_request_descriptor structure. + */ +struct atsc_dcc_arriving_request_descriptor { +	struct descriptor d; + +	uint8_t dcc_arriving_request_type; +	uint8_t dcc_arriving_request_text_length; +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_dcc_arriving_request_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_dcc_arriving_request_descriptor pointer, or NULL on error. + */ +static inline struct atsc_dcc_arriving_request_descriptor* +	atsc_dcc_arriving_request_descriptor_codec(struct descriptor* d) +{ +	struct atsc_dcc_arriving_request_descriptor *ret = +		(struct atsc_dcc_arriving_request_descriptor *) d; + +	if (d->len < 2) +		return NULL; + +	if (d->len != 2 + ret->dcc_arriving_request_text_length) +		return NULL; + +	if (atsc_text_validate((uint8_t*) d + sizeof(struct atsc_dcc_arriving_request_descriptor), +	                       ret->dcc_arriving_request_text_length)) +		return NULL; + +	return (struct atsc_dcc_arriving_request_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_dcc_arriving_request_descriptor. + * + * @param d atsc_dcc_arriving_request_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_dcc_arriving_request_descriptor_text(struct atsc_dcc_arriving_request_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_arriving_request_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_dcc_arriving_request_descriptor. + * + * @param d atsc_dcc_arriving_request_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_dcc_arriving_request_descriptor_text_length(struct +		atsc_dcc_arriving_request_descriptor *d) +{ +	return d->d.len - 2; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcc_departing_request_descriptor.h b/lib/libucsi/atsc/dcc_departing_request_descriptor.h new file mode 100644 index 0000000..851f0cc --- /dev/null +++ b/lib/libucsi/atsc/dcc_departing_request_descriptor.h @@ -0,0 +1,108 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR +#define _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_dcc_departing_request_type { +	DCC_DEPART_TYPE_IMMEDIATE	= 0x01, +	DCC_DEPART_TYPE_DEFER_10SEC	= 0x02, +	DCC_DEPART_TYPE_DEFER		= 0x03, +}; + +/** + * atsc_dcc_departing_request_descriptor structure. + */ +struct atsc_dcc_departing_request_descriptor { +	struct descriptor d; + +	uint8_t dcc_departing_request_type; +	uint8_t dcc_departing_request_text_length; +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_dcc_departing_request_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_dcc_departing_request_descriptor pointer, or NULL on error. + */ +static inline struct atsc_dcc_departing_request_descriptor* +	atsc_dcc_departing_request_descriptor_codec(struct descriptor* d) +{ +	struct atsc_dcc_departing_request_descriptor *ret = +		(struct atsc_dcc_departing_request_descriptor *) d; + +	if (d->len < 2) +		return NULL; + +	if (d->len != 2 + ret->dcc_departing_request_text_length) +		return NULL; + +	if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor), +	    		       ret->dcc_departing_request_text_length)) +		return NULL; + +	return (struct atsc_dcc_departing_request_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_dcc_departing_request_descriptor. + * + * @param d atsc_dcc_departing_request_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_dcc_departing_request_descriptor_text(struct atsc_dcc_departing_request_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_dcc_departing_request_descriptor. + * + * @param d atsc_dcc_departing_request_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_dcc_departing_request_descriptor_text_length(struct +		atsc_dcc_departing_request_descriptor *d) +{ +	return d->d.len - 2; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dccsct_section.c b/lib/libucsi/atsc/dccsct_section.c new file mode 100644 index 0000000..59ad069 --- /dev/null +++ b/lib/libucsi/atsc/dccsct_section.c @@ -0,0 +1,109 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/dccsct_section.h> + +struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_dccsct_section)) +		return NULL; +	struct atsc_dccsct_section *dccsct = (struct atsc_dccsct_section *) psip; + +	pos += sizeof(struct atsc_dccsct_section); +	for(idx =0; idx < dccsct->updates_defined; idx++) { +		if (len < (pos + sizeof(struct atsc_dccsct_update))) +			return NULL; +		struct atsc_dccsct_update *update = (struct atsc_dccsct_update *) (buf+pos); + +		pos += sizeof(struct atsc_dccsct_update); +		if (len < (pos + update->update_data_length)) +			return NULL; + +		switch(update->update_type) { +		case ATSC_DCCST_UPDATE_NEW_GENRE: { +			int sublen = sizeof(struct atsc_dccsct_update_new_genre); +			if (update->update_data_length < sublen) +				return NULL; + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		case ATSC_DCCST_UPDATE_NEW_STATE: { +			int sublen = sizeof(struct atsc_dccsct_update_new_state); +			if (update->update_data_length < sublen) +				return NULL; + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		case ATSC_DCCST_UPDATE_NEW_COUNTY: { +			int sublen = sizeof(struct atsc_dccsct_update_new_county); +			if (update->update_data_length < sublen) +				return NULL; +			bswap16(buf+pos+1); + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		} + +		pos += update->update_data_length; +		if (len < (pos + sizeof(struct atsc_dccsct_update_part2))) +			return NULL; +		struct atsc_dccsct_update_part2 *part2 = (struct atsc_dccsct_update_part2 *) buf + pos; + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_dccsct_update_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; + +		pos += part2->descriptors_length; +	} + +	if (len < (pos + sizeof(struct atsc_dccsct_section_part2))) +		return NULL; +	struct atsc_dccsct_section_part2 *part2 = (struct atsc_dccsct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_dccsct_section_part2); +	if (len < (pos + part2->descriptors_length)) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_dccsct_section *) psip; +} diff --git a/lib/libucsi/atsc/dccsct_section.h b/lib/libucsi/atsc/dccsct_section.h new file mode 100644 index 0000000..f9f3522 --- /dev/null +++ b/lib/libucsi/atsc/dccsct_section.h @@ -0,0 +1,327 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_DCCSCT_SECTION_H +#define _UCSI_ATSC_DCCSCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +enum atsc_dccst_update_types { +	ATSC_DCCST_UPDATE_NEW_GENRE 	= 0x01, +	ATSC_DCCST_UPDATE_NEW_STATE 	= 0x02, +	ATSC_DCCST_UPDATE_NEW_COUNTY 	= 0x03, +}; + +/** + * atsc_dccsct_section structure. + */ +struct atsc_dccsct_section { +	struct atsc_section_psip head; + +	uint8_t updates_defined; +	/* struct atsc_dccsct_update updates */ +	/* struct atsc_dccsct_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_dccsct_update { +	uint8_t update_type; +	uint8_t update_data_length; +	/* struct atsc_dccsct_update_XXX data -- depends on update_type */ +	/* struct atsc_dccsct_update_part2 part2 */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_genre { +	uint8_t genre_category_code; +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_state { +	uint8_t dcc_state_location_code; +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_county { +	uint8_t state_code; +  EBIT2(uint16_t reserved			: 6; , +	uint16_t dcc_county_location_code	:10; ); +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dccsct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process an atsc_dccsct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_dccsct_section pointer, or NULL on error. + */ +struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the dccsct_type field of a dccsct. + * + * @param dccsct dccsct pointer. + * @return The dccsct_type. + */ +static inline uint16_t atsc_dccsct_section_dccsct_type(struct atsc_dccsct_section *dccsct) +{ +	return dccsct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the updates field in an atsc_dccsct_section. + * + * @param dccsct atsc_dccsct_section pointer. + * @param pos Variable containing a pointer to the current atsc_dccsct_update. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dccsct_section_updates_for_each(dccsct, pos, idx) \ +	for ((pos) = atsc_dccsct_section_updates_first(dccsct), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dccsct_section_updates_next(dccsct, pos, ++idx)) + +/** + * Accessor for the data field of a new genre atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_genre pointer. + */ +static inline struct atsc_dccsct_update_new_genre *atsc_dccsct_update_new_genre(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_GENRE) +		return NULL; + +	return (struct atsc_dccsct_update_new_genre *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_genre. + * + * @param update atsc_dccsct_update_new_genre pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_genre_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 1) == 0) +		return NULL; + +	return (struct atsc_text *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_genre)); +} + +/** + * Accessor for the data field of a new state atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_state pointer. + */ +static inline struct atsc_dccsct_update_new_state * +	atsc_dccsct_update_new_state(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_STATE) +		return NULL; + +	return (struct atsc_dccsct_update_new_state *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_state. + * + * @param update atsc_dccsct_update_new_state pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_state_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 1) == 0) +		return NULL; + +	return (struct atsc_text *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_state)); +} + +/** + * Accessor for the data field of a new county atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_county pointer. + */ +static inline struct atsc_dccsct_update_new_county * +	atsc_dccsct_update_new_county(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_COUNTY) +		return NULL; + +	return (struct atsc_dccsct_update_new_county *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_county. + * + * @param update atsc_dccsct_update_new_county pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_county_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 3) == 0) +		return NULL; + +	return (struct atsc_text*) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_county)); +} + +/** + * Accessor for the part2 field of an atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_test_part2 pointer. + */ +static inline struct atsc_dccsct_update_part2 *atsc_dccsct_update_part2(struct atsc_dccsct_update *update) +{ +	int pos = sizeof(struct atsc_dccsct_update); +	pos += update->update_data_length; + +	return (struct atsc_dccsct_update_part2 *) (((uint8_t*) update) + pos); +} + +/** + * Iterator for the descriptors field in an atsc_dccsct_update_part2 structure. + * + * @param part2 atsc_dccsct_update_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dccsct_update_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dccsct_update_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dccsct_update_part2_descriptors_next(part2, pos)) + +/** + * Iterator for the descriptors field in a atsc_dccsct_section_part2 structure. + * + * @param part2 atsc_dccsct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dccsct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dccsct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dccsct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_dccsct_update * +	atsc_dccsct_section_updates_first(struct atsc_dccsct_section *dccsct) +{ +	size_t pos = sizeof(struct atsc_dccsct_section); + +	if (dccsct->updates_defined == 0) +		return NULL; + +	return (struct atsc_dccsct_update*) (((uint8_t *) dccsct) + pos); +} + +static inline struct atsc_dccsct_update* +	atsc_dccsct_section_updates_next(struct atsc_dccsct_section *dccsct, +				         struct atsc_dccsct_update *pos, +				         int idx) +{ +	if (idx >= dccsct->updates_defined) +		return NULL; + +	struct atsc_dccsct_update_part2 *part2 = atsc_dccsct_update_part2(pos); +	int len = sizeof(struct atsc_dccsct_update_part2); +	len += part2->descriptors_length; + +	return (struct atsc_dccsct_update *) (((uint8_t*) part2) + len); +} + +static inline struct descriptor * +	atsc_dccsct_update_part2_descriptors_first(struct atsc_dccsct_update_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dccsct_update_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dccsct_update_part2_descriptors_next(struct atsc_dccsct_update_part2 *part2, +						  struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_update_part2), +				part2->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dccsct_section_part2_descriptors_first(struct atsc_dccsct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dccsct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dccsct_section_part2_descriptors_next(struct atsc_dccsct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_section_part2), +				part2->descriptors_length, +				pos); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcct_section.c b/lib/libucsi/atsc/dcct_section.c new file mode 100644 index 0000000..7d0b83b --- /dev/null +++ b/lib/libucsi/atsc/dcct_section.c @@ -0,0 +1,96 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/dcct_section.h> + +struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int testidx; +	int termidx; + +	if (len < sizeof(struct atsc_dcct_section)) +		return NULL; +	struct atsc_dcct_section *dcct = (struct atsc_dcct_section *) psip; + +	pos += sizeof(struct atsc_dcct_section); +	for(testidx =0; testidx < dcct->dcc_test_count; testidx++) { +		if (len < (pos + sizeof(struct atsc_dcct_test))) +			return NULL; +		struct atsc_dcct_test *test = (struct atsc_dcct_test *) (buf+pos); + +		bswap24(buf+pos); +		bswap24(buf+pos+3); +		bswap32(buf+pos+6); +		bswap32(buf+pos+10); + +		pos += sizeof(struct atsc_dcct_test); +		for(termidx =0; termidx < test->dcc_term_count; termidx++) { +			if (len < (pos + sizeof(struct atsc_dcct_term))) +				return NULL; +			struct atsc_dcct_term *term = (struct atsc_dcct_term *) (buf+pos); + +			bswap64(buf+pos+1); +			bswap16(buf+pos+9); + +			pos += sizeof(struct atsc_dcct_term); +			if (len < (pos + term->descriptors_length)) +				return NULL; +			if (verify_descriptors(buf + pos, term->descriptors_length)) +				return NULL; + +			pos += term->descriptors_length; +		} + +		if (len < (pos + sizeof(struct atsc_dcct_test_part2))) +			return NULL; +		struct atsc_dcct_test_part2 *part2 = (struct atsc_dcct_test_part2 *) (buf+pos); + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_dcct_test_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; +		pos += part2->descriptors_length; +	} + +	if (len < (pos + sizeof(struct atsc_dcct_section_part2))) +		return NULL; +	struct atsc_dcct_section_part2 *part2 = (struct atsc_dcct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_dcct_section_part2); +	if (len < (pos + part2->descriptors_length)) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_dcct_section *) psip; +} diff --git a/lib/libucsi/atsc/dcct_section.h b/lib/libucsi/atsc/dcct_section.h new file mode 100644 index 0000000..647bd4b --- /dev/null +++ b/lib/libucsi/atsc/dcct_section.h @@ -0,0 +1,380 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_DCCT_SECTION_H +#define _UCSI_ATSC_DCCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +enum atsc_dcc_context { +	ATSC_DCC_CONTEXT_TEMPORARY_RETUNE = 0, +	ATSC_DCC_CONTEXT_CHANNEL_REDIRECT = 1, +}; + +enum atsc_dcc_selection_type { +	ATSC_DCC_SELECTION_UNCONDITIONAL_CHANNEL_CHANGE = 0x00, +	ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_INCLUSION = 0x01, +	ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_INCLUSION = 0x02, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ONE_OR_MORE = 0x05, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ALL = 0x06, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_ONE_OR_MORE = 0x07, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_ALL = 0x08, +	ATSC_DCC_SELECTION_CANNOT_BE_AUTHORIZED = 0x09, +	ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_INCLUSION = 0x0c, +	ATSC_DCC_SELECTION_RATING_BLOCKED = 0x0d, +	ATSC_DCC_SELECTION_RETURN_TO_ORIGINAL_CHANNEL = 0x0f, +	ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_EXCLUSION = 0x11, +	ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_EXCLUSION = 0x12, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ONE_OR_MORE = 0x15, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ALL = 0x16, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ONE_OR_MORE = 0x17, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ALL = 0x18, +	ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_EXCLUSION = 0x1c, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_A = 0x20, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_B = 0x21, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_C = 0x22, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_D = 0x23, +}; + +/** + * atsc_dcct_section structure. + */ +struct atsc_dcct_section { +	struct atsc_section_psip head; + +	uint8_t dcc_test_count; +	/* struct atsc_dcct_test tests */ +	/* struct atsc_dcct_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_dcct_test { +  EBIT4(uint32_t dcc_context			: 1; , +	uint32_t reserved			: 3; , +	uint32_t dcc_from_major_channel_number	:10; , +	uint32_t dcc_from_minor_channel_number	:10; ); +  EBIT3(uint32_t reserved1			: 4; , +	uint32_t dcc_to_major_channel_number	:10; , +	uint32_t dcc_to_minor_channel_number	:10; ); +	atsctime_t start_time; +	atsctime_t end_time; +	uint8_t dcc_term_count; +	/* struct atsc_dcct_term terms */ +	/* struct atsc_dcct_test_part2 part2 */ +} __ucsi_packed; + +struct atsc_dcct_term { +	uint8_t dcc_selection_type; +	uint64_t dcc_selection_id; +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dcct_test_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dcct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct); +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct, +				     struct atsc_dcct_test *pos, +				     int idx); +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_first(struct atsc_dcct_test *test); +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_next(struct atsc_dcct_test *test, +				  struct atsc_dcct_term *pos, +				  int idx); + + +/** + * Process an atsc_dcct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_dcct_section pointer, or NULL on error. + */ +struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the dcc_subtype field of a dcct. + * + * @param dcct dcct pointer. + * @return The dcc_subtype. + */ +static inline uint8_t atsc_dcct_section_dcc_subtype(struct atsc_dcct_section *dcct) +{ +	return dcct->head.ext_head.table_id_ext >> 8; +} + +/** + * Accessor for the dcc_id field of a dcct. + * + * @param dcct dcct pointer. + * @return The dcc_id. + */ +static inline uint8_t atsc_dcct_section_dcc_id(struct atsc_dcct_section *dcct) +{ +	return dcct->head.ext_head.table_id_ext & 0xff; +} + +/** + * Iterator for the tests field in an atsc_dcct_section. + * + * @param dcct atsc_dcct_section pointer. + * @param pos Variable containing a pointer to the current atsc_dcct_test. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dcct_section_tests_for_each(dcct, pos, idx) \ +	for ((pos) = atsc_dcct_section_tests_first(dcct), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dcct_section_tests_next(dcct, pos, ++idx)) + +/** + * Iterator for the terms field in an atsc_dcct_test. + * + * @param test atsc_dcct_test pointer. + * @param pos Variable containing a pointer to the current atsc_dcct_term. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dcct_test_terms_for_each(test, pos, idx) \ +	for ((pos) = atsc_dcct_test_terms_first(test), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dcct_test_terms_next(test, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_dcct_term structure. + * + * @param term atsc_dcct_term pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_term_descriptors_for_each(term, pos) \ +	for ((pos) = atsc_dcct_term_descriptors_first(term); \ +	     (pos); \ +	     (pos) = atsc_dcct_term_descriptors_next(term, pos)) + +/** + * Accessor for the part2 field of an atsc_dcct_test. + * + * @param test atsc_dcct_test pointer. + * @return struct atsc_dcct_test_part2 pointer. + */ +static inline struct atsc_dcct_test_part2 *atsc_dcct_test_part2(struct atsc_dcct_test *test) +{ +	int pos = sizeof(struct atsc_dcct_test); + +	struct atsc_dcct_term *cur_term; +	int idx; +	atsc_dcct_test_terms_for_each(test, cur_term, idx) { +		pos += sizeof(struct atsc_dcct_term); +		pos += cur_term->descriptors_length; +	} + +	return (struct atsc_dcct_test_part2 *) (((uint8_t*) test) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_dcct_test_part2 structure. + * + * @param term atsc_dcct_test_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_test_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dcct_test_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dcct_test_part2_descriptors_next(part2, pos)) + +/** + * Accessor for the part2 field of an atsc_dcct_section. + * + * @param dcct atsc_dcct_section pointer. + * @return struct atsc_dcct_section_part2 pointer. + */ +static inline struct atsc_dcct_section_part2 *atsc_dcct_section_part2(struct atsc_dcct_section *dcct) +{ +	int pos = sizeof(struct atsc_dcct_section); + +	struct atsc_dcct_test *cur_test; +	int testidx; +	atsc_dcct_section_tests_for_each(dcct, cur_test, testidx) { +		struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(cur_test); +		pos += ((uint8_t*) part2 - (uint8_t*) cur_test); + +		pos += sizeof(struct atsc_dcct_test_part2); +		pos += part2->descriptors_length; +	} + +	return (struct atsc_dcct_section_part2 *) (((uint8_t*) dcct) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_dcct_section_part2 structure. + * + * @param part2 atsc_dcct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dcct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dcct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct) +{ +	size_t pos = sizeof(struct atsc_dcct_section); + +	if (dcct->dcc_test_count == 0) +		return NULL; + +	return (struct atsc_dcct_test*) (((uint8_t *) dcct) + pos); +} + +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct, +				     struct atsc_dcct_test *pos, +				     int idx) +{ +	if (idx >= dcct->dcc_test_count) +		return NULL; + +	struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(pos); +	int len = sizeof(struct atsc_dcct_test_part2); +	len += part2->descriptors_length; + +	return (struct atsc_dcct_test *) (((uint8_t*) part2) + len); +} + +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_first(struct atsc_dcct_test *test) +{ +	size_t pos = sizeof(struct atsc_dcct_test); + +	if (test->dcc_term_count == 0) +		return NULL; + +	return (struct atsc_dcct_term*) (((uint8_t *) test) + pos); +} + +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_next(struct atsc_dcct_test *test, +				  struct atsc_dcct_term *pos, +				  int idx) +{ +	if (idx >= test->dcc_term_count) +		return NULL; + +	int len = sizeof(struct atsc_dcct_term); +	len += pos->descriptors_length; + +	return (struct atsc_dcct_term *) (((uint8_t*) pos) + len); +} + +static inline struct descriptor * +	atsc_dcct_term_descriptors_first(struct atsc_dcct_term *term) +{ +	size_t pos = sizeof(struct atsc_dcct_term); + +	if (term->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) term) + pos); +} + +static inline struct descriptor * +	atsc_dcct_term_descriptors_next(struct atsc_dcct_term *term, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) term + sizeof(struct atsc_dcct_term), +				term->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dcct_test_part2_descriptors_first(struct atsc_dcct_test_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dcct_test_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dcct_test_part2_descriptors_next(struct atsc_dcct_test_part2 *part2, +					      struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_test_part2), +				part2->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dcct_section_part2_descriptors_first(struct atsc_dcct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dcct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dcct_section_part2_descriptors_next(struct atsc_dcct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_section_part2), +				part2->descriptors_length, +				pos); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/descriptor.h b/lib/libucsi/atsc/descriptor.h new file mode 100644 index 0000000..a57176a --- /dev/null +++ b/lib/libucsi/atsc/descriptor.h @@ -0,0 +1,68 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_DESCRIPTOR_H +#define _UCSI_ATSC_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/endianops.h> +#include <libucsi/atsc/stuffing_descriptor.h> +#include <libucsi/atsc/ac3_descriptor.h> +#include <libucsi/atsc/caption_service_descriptor.h> +#include <libucsi/atsc/component_name_descriptor.h> +#include <libucsi/atsc/content_advisory_descriptor.h> +#include <libucsi/atsc/dcc_arriving_request_descriptor.h> +#include <libucsi/atsc/dcc_departing_request_descriptor.h> +#include <libucsi/atsc/extended_channel_name_descriptor.h> +#include <libucsi/atsc/genre_descriptor.h> +#include <libucsi/atsc/rc_descriptor.h> +#include <libucsi/atsc/service_location_descriptor.h> +#include <libucsi/atsc/time_shifted_service_descriptor.h> + +/** + * Enumeration of ATSC descriptor tags. + */ +enum atsc_descriptor_tag { +	dtag_atsc_stuffing			= 0x80, +	dtag_atsc_ac3_audio			= 0x81, +	dtag_atsc_caption_service		= 0x86, +	dtag_atsc_content_advisory		= 0x87, +	dtag_atsc_extended_channel_name		= 0xa0, +	dtag_atsc_service_location		= 0xa1, +	dtag_atsc_time_shifted_service		= 0xa2, +	dtag_atsc_component_name		= 0xa3, +	dtag_atsc_dcc_departing_request		= 0xa8, +	dtag_atsc_dcc_arriving_request		= 0xa9, +	dtag_atsc_redistribution_control	= 0xaa, +	dtag_atsc_private_information		= 0xad, +	dtag_atsc_content_identifier		= 0xb6, +	dtag_atsc_genre				= 0xab, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/eit_section.c b/lib/libucsi/atsc/eit_section.c new file mode 100644 index 0000000..48cdda6 --- /dev/null +++ b/lib/libucsi/atsc/eit_section.c @@ -0,0 +1,71 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/eit_section.h> + +struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_eit_section)) +		return NULL; +	struct atsc_eit_section *eit = (struct atsc_eit_section *) psip; + +	pos += sizeof(struct atsc_eit_section); +	for(idx =0; idx < eit->num_events_in_section; idx++) { +		if (len < (pos + sizeof(struct atsc_eit_event))) +			return NULL; +		struct atsc_eit_event *event = (struct atsc_eit_event *) (buf+pos); + +		bswap16(buf+pos); +		bswap32(buf+pos+2); +		bswap32(buf+pos+6); + +		pos += sizeof(struct atsc_eit_event); +		if (len < (pos + event->title_length)) +			return NULL; +		if (atsc_text_validate(buf+pos, event->title_length)) +			return NULL; + +		pos += event->title_length; +		if (len < (pos + sizeof(struct atsc_eit_event_part2))) +			return NULL; +		struct atsc_eit_event_part2 *part2 = (struct atsc_eit_event_part2 *) (buf+pos); + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_eit_event_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; + +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; +		pos += part2->descriptors_length; +	} + +	if (pos != len) +		return NULL; + +	return (struct atsc_eit_section *) psip; +} diff --git a/lib/libucsi/atsc/eit_section.h b/lib/libucsi/atsc/eit_section.h new file mode 100644 index 0000000..84bef16 --- /dev/null +++ b/lib/libucsi/atsc/eit_section.h @@ -0,0 +1,191 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_EIT_SECTION_H +#define _UCSI_ATSC_EIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_eit_section structure. + */ +struct atsc_eit_section { +	struct atsc_section_psip head; + +	uint8_t num_events_in_section; +	/* struct atsc_eit_event events[] */ +} __ucsi_packed; + +struct atsc_eit_event { +  EBIT2(uint16_t reserved			: 2; , +	uint16_t event_id			:14; ); +	atsctime_t start_time; +  EBIT4(uint32_t reserved1			: 2; , +	uint32_t ETM_location			: 2; , +	uint32_t length_in_seconds		:20; , +	uint32_t title_length			: 8; ); +	/* struct atsc_text title_text */ +	/* struct atsc_eit_event_part2 part2 */ +} __ucsi_packed; + +struct atsc_eit_event_part2 { +  EBIT2(uint16_t reserved			: 4; , +	uint16_t descriptors_length		:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + + +/** + * Process a atsc_eit_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_eit_section pointer, or NULL on error. + */ +struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the source_id field of an EIT. + * + * @param eit EIT pointer. + * @return The source_id . + */ +static inline uint16_t atsc_eit_section_source_id(struct atsc_eit_section *eit) +{ +	return eit->head.ext_head.table_id_ext; +} + +/** + * Iterator for the events field in an atsc_eit_section. + * + * @param eit atsc_eit_section pointer. + * @param pos Variable containing a pointer to the current atsc_eit_event. + * @param idx Integer used to count which event we are in. + */ +#define atsc_eit_section_events_for_each(eit, pos, idx) \ +	for ((pos) = atsc_eit_section_events_first(eit), idx=0; \ +	     (pos); \ +	     (pos) = atsc_eit_section_events_next(eit, pos, ++idx)) + +/** + * Accessor for the title_text field of an atsc_eit_event. + * + * @param event atsc_eit_event pointer. + * @return struct atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text *atsc_eit_event_name_title_text(struct atsc_eit_event *event) +{ +	if (event->title_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) event) + sizeof(struct atsc_eit_event)); +} + +/** + * Accessor for the part2 field of an atsc_eit_event. + * + * @param event atsc_eit_event pointer. + * @return struct atsc_eit_event_part2 pointer. + */ +static inline struct atsc_eit_event_part2 *atsc_eit_event_part2(struct atsc_eit_event *event) +{ +	return (struct atsc_eit_event_part2 *) +		(((uint8_t*) event) + sizeof(struct atsc_eit_event) + event->title_length); +} + +/** + * Iterator for the descriptors field in a atsc_eit_section structure. + * + * @param part2 atsc_eit_event_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_eit_event_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_eit_event_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_eit_event_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_eit_event * +	atsc_eit_section_events_first(struct atsc_eit_section *eit) +{ +	size_t pos = sizeof(struct atsc_eit_section); + +	if (eit->num_events_in_section == 0) +		return NULL; + +	return (struct atsc_eit_event*) (((uint8_t *) eit) + pos); +} + +static inline struct atsc_eit_event * +	atsc_eit_section_events_next(struct atsc_eit_section *eit, +				     struct atsc_eit_event *pos, +				     int idx) +{ +	if (idx >= eit->num_events_in_section) +		return NULL; + +	struct atsc_eit_event_part2 *part2 = atsc_eit_event_part2(pos); +	int len = sizeof(struct atsc_eit_event_part2); +	len += part2->descriptors_length; + +	return (struct atsc_eit_event *) (((uint8_t*) part2) + len); +} + +static inline struct descriptor * +	atsc_eit_event_part2_descriptors_first(struct atsc_eit_event_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_eit_event_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_eit_event_part2_descriptors_next(struct atsc_eit_event_part2 *part2, +					      struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_eit_event_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/ett_section.c b/lib/libucsi/atsc/ett_section.c new file mode 100644 index 0000000..ab2ff9c --- /dev/null +++ b/lib/libucsi/atsc/ett_section.c @@ -0,0 +1,42 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/ett_section.h> +#include <libucsi/atsc/types.h> + +struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); + +	if (len < sizeof(struct atsc_ett_section)) +		return NULL; + +	bswap32(buf + pos); +	pos += 4; + +	if (atsc_text_validate(buf + pos, +	    		       section_ext_length(&psip->ext_head) - sizeof(struct atsc_ett_section))) +		return NULL; + +	return (struct atsc_ett_section *) psip; +} diff --git a/lib/libucsi/atsc/ett_section.h b/lib/libucsi/atsc/ett_section.h new file mode 100644 index 0000000..e2bb510 --- /dev/null +++ b/lib/libucsi/atsc/ett_section.h @@ -0,0 +1,91 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_ETT_SECTION_H +#define _UCSI_ATSC_ETT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +enum atsc_etm_type { +	ATSC_ETM_CHANNEL 	= 0x00, +	ATSC_ETM_EVENT 		= 0x02, +}; + +/** + * atsc_ett_section structure. + */ +struct atsc_ett_section { +	struct atsc_section_psip head; + +  EBIT3(uint32_t ETM_source_id			:16; , +	uint32_t ETM_sub_id			:14; , +	uint32_t ETM_type			: 2; ); +	/* struct atsc_text extended_text_message */ +} __ucsi_packed; + +/** + * Process a atsc_ett_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_ett_section pointer, or NULL on error. + */ +struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the extended_text_message part of an atsc_ett_section. + * + * @param ett atsc_ett_section pointer. + * @return atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text* +	atsc_ett_section_extended_text_message(struct atsc_ett_section *ett) +{ +	int pos = sizeof(struct atsc_ett_section); +	int len = section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section); + +	if (len == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) ett) + pos); +} + +/** + * Accessor for the extended_text_message part of an atsc_ett_section. + * + * @param ett atsc_ett_section pointer. + * @return The length. + */ +static inline int +	atsc_ett_section_extended_text_message_length(struct atsc_ett_section *ett) +{ +	return section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/extended_channel_name_descriptor.h b/lib/libucsi/atsc/extended_channel_name_descriptor.h new file mode 100644 index 0000000..d0b714b --- /dev/null +++ b/lib/libucsi/atsc/extended_channel_name_descriptor.h @@ -0,0 +1,92 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR +#define _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_extended_channel_name_descriptor structure. + */ +struct atsc_extended_channel_name_descriptor { +	struct descriptor d; + +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_extended_channel_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_extended_channel_name_descriptor pointer, or NULL on error. + */ +static inline struct atsc_extended_channel_name_descriptor* +	atsc_extended_channel_name_descriptor_codec(struct descriptor* d) +{ +	if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor), +	    		       d->len)) +		return NULL; + +	return (struct atsc_extended_channel_name_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_extended_channel_name_descriptor. + * + * @param d atsc_extended_channel_name_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_extended_channel_name_descriptor_text(struct atsc_extended_channel_name_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_extended_channel_name_descriptor. + * + * @param d atsc_extended_channel_name_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_extended_channel_name_descriptor_text_length(struct +							atsc_extended_channel_name_descriptor *d) +{ +	return d->d.len; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/genre_descriptor.h b/lib/libucsi/atsc/genre_descriptor.h new file mode 100644 index 0000000..a6fc542 --- /dev/null +++ b/lib/libucsi/atsc/genre_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_GENRE_DESCRIPTOR +#define _UCSI_ATSC_GENRE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_genre_descriptor structure. + */ +struct atsc_genre_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t attribute_count		: 5; ); +	/* uint8_t attributes[] */ +} __ucsi_packed; + +/** + * Process an atsc_genre_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_genre_descriptor pointer, or NULL on error. + */ +static inline struct atsc_genre_descriptor* +	atsc_genre_descriptor_codec(struct descriptor* d) +{ +	struct atsc_genre_descriptor *ret = +		(struct atsc_genre_descriptor *) d; + +	if (d->len < 1) +		return NULL; + +	if (d->len != (1 + ret->attribute_count)) +		return NULL; + +	return (struct atsc_genre_descriptor*) d; +} + +/** + * Accessor for the attributes field of an atsc_genre_descriptor. + * + * @param d atsc_genre_descriptor pointer. + * @return Pointer to the attributes. + */ +static inline uint8_t* +	atsc_genre_descriptor_attributes(struct atsc_genre_descriptor *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_genre_descriptor); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/mgt_section.c b/lib/libucsi/atsc/mgt_section.c new file mode 100644 index 0000000..bc6b3f2 --- /dev/null +++ b/lib/libucsi/atsc/mgt_section.c @@ -0,0 +1,76 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/mgt_section.h> + +struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	struct atsc_mgt_section *mgt = (struct atsc_mgt_section *) psip; +	int i; + +	if (len < sizeof(struct atsc_mgt_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	// we cannot use the tables_defined value here because of the braindead ATSC spec! +	for(i=0; i < mgt->tables_defined; i++) { +		// we think we're still in the tables - process as normal +		if ((pos + sizeof(struct atsc_mgt_table)) > len) +			return NULL; +		struct atsc_mgt_table *table = (struct atsc_mgt_table *) (buf+pos); + +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		bswap32(buf+pos+5); +		bswap16(buf+pos+9); + +		pos += sizeof(struct atsc_mgt_table); +		if ((pos + table->table_type_descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, table->table_type_descriptors_length)) +			return NULL; + +		pos += table->table_type_descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_mgt_section_part2)) > len) +		return NULL; +	struct atsc_mgt_section_part2 *part2 = (struct atsc_mgt_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_mgt_section_part2); +	if ((pos + part2->descriptors_length) > len) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; +	pos += part2->descriptors_length; + +	if (pos != len) +		return NULL; + +	return (struct atsc_mgt_section *) psip; +} diff --git a/lib/libucsi/atsc/mgt_section.h b/lib/libucsi/atsc/mgt_section.h new file mode 100644 index 0000000..3102a54 --- /dev/null +++ b/lib/libucsi/atsc/mgt_section.h @@ -0,0 +1,215 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_MGT_SECTION_H +#define _UCSI_ATSC_MGT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +enum atsc_mgt_section_table_type { +	ATSC_MGT_TABLE_TYPE_TVCT_CURRENT = 0, +	ATSC_MGT_TABLE_TYPE_TVCT_NEXT = 1, +	ATSC_MGT_TABLE_TYPE_CVCT_CURRENT = 2, +	ATSC_MGT_TABLE_TYPE_CVCT_NEXT = 3, +	ATSC_MGT_TABLE_TYPE_CHANNEL_ETT = 4, +	ATSC_MGT_TABLE_TYPE_DCCSCT = 5, +}; + +/** + * atsc_mgt_section structure. + */ +struct atsc_mgt_section { +	struct atsc_section_psip head; + +	uint16_t tables_defined; +	/* struct atsc_mgt_table tables[] */ +	/* struct atsc_mgt_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_mgt_table { +	uint16_t table_type; +  EBIT2(uint16_t reserved			: 3; , +	uint16_t table_type_PID			:13; ); +  EBIT2(uint8_t reserved1			: 3; , +	uint8_t table_type_version_number	: 5; ); +	uint32_t number_bytes; +  EBIT2(uint16_t reserved2			: 4; , +	uint16_t table_type_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_mgt_section_part2 { +  EBIT2(uint16_t reserved			: 4; , +	uint16_t descriptors_length		:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_mgt_table * atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt); +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt, struct atsc_mgt_table *pos, int idx); + +/** + * Process a atsc_mgt_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_mgt_section pointer, or NULL on error. + */ +struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *section); + +/** + * Iterator for the tables field in an atsc_mgt_section. + * + * @param mgt atsc_mgt_section pointer. + * @param pos Variable containing a pointer to the current atsc_mgt_table. + * @param idx Integer used to count which table we in. + */ +#define atsc_mgt_section_tables_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_mgt_section_tables_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_mgt_section_tables_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_mgt_table structure. + * + * @param table atsc_mgt_table pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_mgt_table_descriptors_for_each(table, pos) \ +	for ((pos) = atsc_mgt_table_descriptors_first(table); \ +	     (pos); \ +	     (pos) = atsc_mgt_table_descriptors_next(table, pos)) + +/** + * Accessor for the second part of an atsc_mgt_section. + * + * @param mgt atsc_mgt_section pointer. + * @return atsc_mgt_section_part2 pointer. + */ +static inline struct atsc_mgt_section_part2 * +	atsc_mgt_section_part2(struct atsc_mgt_section *mgt) +{ +	int pos = sizeof(struct atsc_mgt_section); + +	struct atsc_mgt_table *cur_table; +	int idx; +	atsc_mgt_section_tables_for_each(mgt, cur_table, idx) { +		pos += sizeof(struct atsc_mgt_table); +		pos += cur_table->table_type_descriptors_length; +	} + +	return (struct atsc_mgt_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_mgt_section structure. + * + * @param part2 atsc_mgt_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_mgt_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_mgt_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_mgt_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt) +{ +	size_t pos = sizeof(struct atsc_mgt_section); + +	if (mgt->tables_defined == 0) +		return NULL; + +	return (struct atsc_mgt_table*) (((uint8_t *) mgt) + pos); +} + +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt, +				     struct atsc_mgt_table *pos, +				     int idx) +{ +	if (idx >= mgt->tables_defined) +		return NULL; + +	return (struct atsc_mgt_table *) +		(((uint8_t*) pos) + sizeof(struct atsc_mgt_table) + pos->table_type_descriptors_length); +} + +static inline struct descriptor * +	atsc_mgt_table_descriptors_first(struct atsc_mgt_table *table) +{ +	size_t pos = sizeof(struct atsc_mgt_table); + +	if (table->table_type_descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) table) + pos); +} + +static inline struct descriptor * +	atsc_mgt_table_descriptors_next(struct atsc_mgt_table *table, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) table + sizeof(struct atsc_mgt_table), +				table->table_type_descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_mgt_section_part2_descriptors_first(struct atsc_mgt_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_mgt_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_mgt_section_part2_descriptors_next(struct atsc_mgt_section_part2 *part2, +						struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_mgt_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/rc_descriptor.h b/lib/libucsi/atsc/rc_descriptor.h new file mode 100644 index 0000000..4fb0e8e --- /dev/null +++ b/lib/libucsi/atsc/rc_descriptor.h @@ -0,0 +1,83 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_RC_DESCRIPTOR +#define _UCSI_ATSC_RC_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_rc_descriptor structure. + */ +struct atsc_rc_descriptor { +	struct descriptor d; + +	/* uint8_t info[] */ +} __ucsi_packed; + +/** + * Process an atsc_rc_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_rc_descriptor pointer, or NULL on error. + */ +static inline struct atsc_rc_descriptor* +	atsc_rc_descriptor_codec(struct descriptor* d) +{ +	return (struct atsc_rc_descriptor*) d; +} + +/** + * Accessor for the info field of an atsc_rc_descriptor. + * + * @param d atsc_rc_descriptor pointer. + * @return Pointer to the atsc_text data. + */ +static inline uint8_t* +	atsc_rc_descriptor_info(struct atsc_rc_descriptor *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_rc_descriptor); +} + +/** + * Accessor for the length of the info field of an atsc_rc_descriptor. + * + * @param d atsc_rc_descriptor pointer. + * @return The length + */ +static inline int +	atsc_rc_descriptor_info_length(struct atsc_rc_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/rrt_section.c b/lib/libucsi/atsc/rrt_section.c new file mode 100644 index 0000000..6e96c3a --- /dev/null +++ b/lib/libucsi/atsc/rrt_section.c @@ -0,0 +1,108 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/rrt_section.h> + +struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; +	int vidx; +	struct atsc_rrt_section *rrt = (struct atsc_rrt_section *) psip; + +	if (len < sizeof(struct atsc_rrt_section)) +		return NULL; +	pos += sizeof(struct atsc_rrt_section); + +	if (len < (pos + rrt->rating_region_name_length)) +		return NULL; +	if (atsc_text_validate(buf+pos, rrt->rating_region_name_length)) +		return NULL; + +	pos += rrt->rating_region_name_length; +	if (len < (pos + sizeof(struct atsc_rrt_section_part2))) +		return NULL; +	struct atsc_rrt_section_part2 *rrtpart2 = (struct atsc_rrt_section_part2 *) (buf+pos); + +	pos += sizeof(struct atsc_rrt_section_part2); +	for(idx =0; idx < rrtpart2->dimensions_defined; idx++) { +		if (len < (pos + sizeof(struct atsc_rrt_dimension))) +			return NULL; +		struct atsc_rrt_dimension *dimension = (struct atsc_rrt_dimension *) (buf+pos); + +		pos += sizeof(struct atsc_rrt_dimension); +		if (len < (pos + dimension->dimension_name_length)) +			return NULL; +		if (atsc_text_validate(buf+pos, dimension->dimension_name_length)) +			return NULL; + +		pos += dimension->dimension_name_length; +		if (len < (pos + sizeof(struct atsc_rrt_dimension_part2))) +			return NULL; +		struct atsc_rrt_dimension_part2 *dpart2 = (struct atsc_rrt_dimension_part2 *) (buf+pos); + +		pos += sizeof(struct atsc_rrt_dimension_part2); +		for(vidx =0; vidx < dpart2->values_defined; vidx++) { +			if (len < (pos + sizeof(struct atsc_rrt_dimension_value))) +				return NULL; +			struct atsc_rrt_dimension_value *value = (struct atsc_rrt_dimension_value *) (buf+pos); + +			pos += sizeof(struct atsc_rrt_dimension_value); +			if (len < (pos + value->abbrev_rating_value_length)) +				return NULL; +			if (atsc_text_validate(buf+pos, value->abbrev_rating_value_length)) +				return NULL; + +			pos += value->abbrev_rating_value_length; +			if (len < (pos + sizeof(struct atsc_rrt_dimension_value_part2))) +				return NULL; +			struct atsc_rrt_dimension_value_part2 *vpart2 = +				(struct atsc_rrt_dimension_value_part2 *) (buf+pos); + +			pos += sizeof(struct atsc_rrt_dimension_value_part2); +			if (len < (pos + vpart2->rating_value_length)) +				return NULL; +			if (atsc_text_validate(buf+pos, vpart2->rating_value_length)) +				return NULL; + +			pos+= vpart2->rating_value_length; +		} +	} + +	if (len < (pos + sizeof(struct atsc_rrt_section_part3))) +		return NULL; +	struct atsc_rrt_section_part3 *part3 = (struct atsc_rrt_section_part3 *) (buf+pos); + +	pos += sizeof(struct atsc_rrt_section_part3); +	if (len < (pos + part3->descriptors_length)) +		return NULL; + +	if (verify_descriptors(buf + pos, part3->descriptors_length)) +		return NULL; + +	pos += part3->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_rrt_section *) psip; +} diff --git a/lib/libucsi/atsc/rrt_section.h b/lib/libucsi/atsc/rrt_section.h new file mode 100644 index 0000000..fba4596 --- /dev/null +++ b/lib/libucsi/atsc/rrt_section.h @@ -0,0 +1,379 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_RRT_SECTION_H +#define _UCSI_ATSC_RRT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_rrt_section structure. + */ +struct atsc_rrt_section { +	struct atsc_section_psip head; + +	uint8_t rating_region_name_length; +	/* struct atsc_text rating_region_name_text */ +	/* struct atsc_rrt_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_rrt_section_part2 { +	uint8_t dimensions_defined; +	/* struct atsc_rrt_dimension dimensions[] */ +	/* struct atsc_rrt_section_part3 part3 */ +} __ucsi_packed; + +struct atsc_rrt_dimension { +	uint8_t dimension_name_length; +	/* struct atsc_text dimension_name_text */ +	/* struct atsc_rrt_dimension_part2 part2 */ +} __ucsi_packed; + +struct atsc_rrt_dimension_part2 { +  EBIT3(uint8_t reserved			: 3; , +	uint8_t graduated_scale			: 1; , +	uint8_t values_defined			: 4; ); +	/* struct atsc_rrt_dimension_value values[] */ +} __ucsi_packed; + +struct atsc_rrt_dimension_value { +	uint8_t abbrev_rating_value_length; +	/* struct atsc_text abbrev_rating_value_text */ +	/* struct atsc_rrt_dimension_value_part2 */ +} __ucsi_packed; + +struct atsc_rrt_dimension_value_part2 { +	uint8_t rating_value_length; +	/* struct atsc_text rating_value_text */ +} __ucsi_packed; + +struct atsc_rrt_section_part3 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + + +static inline struct atsc_rrt_dimension * +		atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2); +static inline struct atsc_rrt_dimension * +		atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2, +		struct atsc_rrt_dimension *pos, +		int idx); +static inline struct atsc_rrt_dimension_value * +		atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2); +static inline struct atsc_rrt_dimension_value * +		atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2, +		struct atsc_rrt_dimension_value *pos, +		int idx); + +/** + * Process a atsc_rrt_section. + * + * @param section Pointer to anj atsc_section_psip structure. + * @return atsc_rrt_section pointer, or NULL on error. + */ +struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the rating_region field of an RRT. + * + * @param rrt RRT pointer. + * @return The transport_stream_id. + */ +static inline uint8_t atsc_rrt_section_rating_region(struct atsc_rrt_section *rrt) +{ +	return rrt->head.ext_head.table_id_ext & 0xff; +} + +/** + * Accessor for the rating_region_name_text field of an RRT. + * + * @param rrt RRT pointer. + * @return struct atsc_text pointer, or NULL. + */ +static inline struct atsc_text *atsc_rrt_section_rating_region_name_text(struct atsc_rrt_section *rrt) +{ +	if (rrt->rating_region_name_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) rrt) + sizeof(struct atsc_rrt_section)); +} + +/** + * Accessor for the part2 field of an RRT. + * + * @param rrt RRT pointer. + * @return struct atsc_rrt_section_part2 pointer. + */ +static inline struct atsc_rrt_section_part2 *atsc_rrt_section_part2(struct atsc_rrt_section *rrt) +{ +	return (struct atsc_rrt_section_part2 *) +		(((uint8_t*) rrt) + sizeof(struct atsc_rrt_section) + +			rrt->rating_region_name_length); +} + +/** + * Iterator for the dimensions field in an atsc_rrt_section_part2. + * + * @param rrt atsc_rrt_section pointer. + * @param pos Variable containing a pointer to the current atsc_rrt_dimension. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_rrt_section_dimensions_for_each(rrt, pos, idx) \ +	for ((pos) = atsc_rrt_section_dimensions_first(rrt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_rrt_section_dimensions_next(rrt, pos, ++idx)) + +/** + * Accessor for the dimension_name_text field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text *atsc_rrt_dimension_name_text(struct atsc_rrt_dimension *dimension) +{ +	if (dimension->dimension_name_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) dimension) + sizeof(struct atsc_rrt_dimension)); +} + +/** + * Accessor for the part2 field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_rrt_dimension_part2 pointer. + */ +static inline struct atsc_rrt_dimension_part2 *atsc_rrt_dimension_part2(struct atsc_rrt_dimension *dimension) +{ +	return (struct atsc_rrt_dimension_part2 *) +			(((uint8_t*) dimension) + +			sizeof(struct atsc_rrt_dimension) + +			dimension->dimension_name_length); +} + +/** + * Iterator for the values field in a atsc_rrt_dimension_part2 structure. + * + * @param part2 atsc_rrt_dimension_part2 pointer. + * @param pos Variable containing a pointer to the current value. + * @param idx Integer used to count which value we are in + */ +#define atsc_rrt_dimension_part2_values_for_each(part2, pos, idx) \ +	for ((pos) = atsc_rrt_dimension_part2_values_first(part2), idx=0; \ +	     (pos); \ +	     (pos) = atsc_rrt_dimension_part2_values_next(part2, pos, ++idx)) + +/** + * Accessor for the dimension_name_text field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_text pointer. + */ +static inline struct atsc_text * +	atsc_rrt_dimension_value_abbrev_rating_value_text(struct atsc_rrt_dimension_value *value) +{ +	if (value->abbrev_rating_value_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) value) + sizeof(struct atsc_rrt_dimension_value)); +} + +/** + * Accessor for the part2 field of an atsc_rrt_dimension_value. + * + * @param value atsc_rrt_dimension_value pointer. + * @return struct atsc_rrt_dimension_value_part2 pointer. + */ +static inline struct atsc_rrt_dimension_value_part2 *atsc_rrt_dimension_value_part2(struct atsc_rrt_dimension_value *value) +{ +	return (struct atsc_rrt_dimension_value_part2 *) +		(((uint8_t*) value) + +		sizeof(struct atsc_rrt_dimension_value) + +		value->abbrev_rating_value_length); +} + +/** + * Accessor for the rating_value_text field of an atsc_rrt_dimension_value_part2. + * + * @param part2 atsc_rrt_dimension_value_part2 pointer. + * @return struct atsc_text pointer. + */ +static inline struct atsc_text *atsc_rrt_dimension_value_part2_rating_value_text(struct atsc_rrt_dimension_value_part2 *part2) +{ +	if (part2->rating_value_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) part2) + sizeof(struct atsc_rrt_dimension_value_part2)); +} + +/** + * Accessor for the third part of an atsc_rrt_section. + * + * @param part2 atsc_rrt_section_part2 pointer. + * @return atsc_rrt_section_part3 pointer. + */ +static inline struct atsc_rrt_section_part3 * +	atsc_rrt_section_part3(struct atsc_rrt_section_part2 *part2) +{ +	int pos = sizeof(struct atsc_rrt_section_part2); + +	struct atsc_rrt_dimension *cur_dimension; +	int idx; +	atsc_rrt_section_dimensions_for_each(part2, cur_dimension, idx) { +		pos += sizeof(struct atsc_rrt_dimension); +		pos += cur_dimension->dimension_name_length; +		pos += sizeof(struct atsc_rrt_dimension_part2); + +		// now we need to iterate over the values. yuck +		struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(cur_dimension); +		struct atsc_rrt_dimension_value *cur_value; +		int vidx; +		atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) { +			pos += sizeof(struct atsc_rrt_dimension_value); +			pos += cur_value->abbrev_rating_value_length; + +			struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value); +			pos += sizeof(struct atsc_rrt_dimension_value_part2); +			pos += vpart2->rating_value_length; +		} +	} + +	return (struct atsc_rrt_section_part3 *) (((uint8_t*) part2) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_rrt_section structure. + * + * @param part3 atsc_rrt_section_part3 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_rrt_section_part3_descriptors_for_each(part3, pos) \ +	for ((pos) = atsc_rrt_section_part3_descriptors_first(part3); \ +	     (pos); \ +	     (pos) = atsc_rrt_section_part3_descriptors_next(part3, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_rrt_dimension * +	atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_rrt_section_part2); + +	if (part2->dimensions_defined == 0) +		return NULL; + +	return (struct atsc_rrt_dimension*) (((uint8_t *) part2) + pos); +} + +static inline struct atsc_rrt_dimension * +	atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2, +					 struct atsc_rrt_dimension *pos, +					 int idx) +{ +	if (idx >= part2->dimensions_defined) +		return NULL; + +	struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(pos); +	int len = sizeof(struct atsc_rrt_dimension_part2); + +	// now we need to iterate over the values. yuck +	struct atsc_rrt_dimension_value *cur_value; +	int vidx; +	atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) { +		len += sizeof(struct atsc_rrt_dimension_value); +		len += cur_value->abbrev_rating_value_length; + +		struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value); +		len += sizeof(struct atsc_rrt_dimension_value_part2); +		len += vpart2->rating_value_length; +	} + +	return (struct atsc_rrt_dimension *) (((uint8_t*) dpart2) + len); +} + +static inline struct atsc_rrt_dimension_value * +	atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_rrt_dimension_part2); + +	if (part2->values_defined == 0) +		return NULL; + +	return (struct atsc_rrt_dimension_value*) (((uint8_t *) part2) + pos); +} + +static inline struct atsc_rrt_dimension_value * +	atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2, +					     struct atsc_rrt_dimension_value *pos, +					     int idx) +{ +	if (idx >= part2->values_defined) +		return NULL; + +	struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(pos); +	int len = sizeof(struct atsc_rrt_dimension_value_part2); +	len += vpart2->rating_value_length; + +	return (struct atsc_rrt_dimension_value *) (((uint8_t*) vpart2) + len); +} + +static inline struct descriptor * +	atsc_rrt_section_part3_descriptors_first(struct atsc_rrt_section_part3 *part3) +{ +	size_t pos = sizeof(struct atsc_rrt_section_part3); + +	if (part3->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part3) + pos); +} + +static inline struct descriptor * +	atsc_rrt_section_part3_descriptors_next(struct atsc_rrt_section_part3 *part3, +						struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part3 + sizeof(struct atsc_rrt_section_part3), +				part3->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/section.h b/lib/libucsi/atsc/section.h new file mode 100644 index 0000000..23d59ea --- /dev/null +++ b/lib/libucsi/atsc/section.h @@ -0,0 +1,84 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/section.h> +#include <libucsi/atsc/mgt_section.h> +#include <libucsi/atsc/tvct_section.h> +#include <libucsi/atsc/cvct_section.h> +#include <libucsi/atsc/rrt_section.h> +#include <libucsi/atsc/eit_section.h> +#include <libucsi/atsc/ett_section.h> +#include <libucsi/atsc/stt_section.h> +#include <libucsi/atsc/dcct_section.h> +#include <libucsi/atsc/dccsct_section.h> + +#ifndef _UCSI_ATSC_SECTION_H +#define _UCSI_ATSC_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ATSC_BASE_PID 0x1ffb + +/** + * Enumeration of ATSC section tags. + */ +enum atsc_section_tag { +	stag_atsc_master_guide					= 0xc7, +	stag_atsc_terrestrial_virtual_channel			= 0xc8, +	stag_atsc_cable_virtual_channel				= 0xc9, +	stag_atsc_rating_region					= 0xca, +	stag_atsc_event_information				= 0xcb, +	stag_atsc_extended_text					= 0xcc, +	stag_atsc_system_time					= 0xcd, +}; + +/** + * ATSC specific PSIP section structure. + */ +struct atsc_section_psip { +	struct section_ext		ext_head; +	uint8_t				protocol_version; +} __ucsi_packed; + +/** + * Decode a PSIP section structure. + * + * @param section_ext Pointer to the processed section_ext structure. + * @return Pointer to the parsed section_psip structure, or NULL if invalid. + */ +static inline struct atsc_section_psip *atsc_section_psip_decode(struct section_ext *section_ext) +{ +	size_t len = section_ext_length(section_ext); +	if (len < sizeof(struct atsc_section_psip)) { +		return NULL; +	} + +	return (struct atsc_section_psip *) section_ext; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/service_location_descriptor.h b/lib/libucsi/atsc/service_location_descriptor.h new file mode 100644 index 0000000..aad5b4a --- /dev/null +++ b/lib/libucsi/atsc/service_location_descriptor.h @@ -0,0 +1,141 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR +#define _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_stream_types { +	ATSC_STREAM_TYPE_VIDEO			= 0x02, +	ATSC_STREAM_TYPE_AUDIO 			= 0x81, +}; + +/** + * atsc_service_location_descriptor structure. + */ +struct atsc_service_location_descriptor { +	struct descriptor d; + +  EBIT2(uint16_t reserved		: 3; , +	uint16_t PCR_PID		:13; ); +	uint8_t number_elements; +	/* struct atsc_service_location_element elements[] */ +} __ucsi_packed; + +/** + * An entry in the elements field of an atsc_service_location_descriptor. + */ +struct atsc_caption_service_location_element { +	uint8_t stream_type; +  EBIT2(uint16_t reserved 		: 3; , +	uint16_t elementary_PID		:13; ); +	iso639lang_t language_code; +} __ucsi_packed; + +/** + * Process an atsc_service_location_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_service_location_descriptor pointer, or NULL on error. + */ +static inline struct atsc_service_location_descriptor* +	atsc_service_location_descriptor_codec(struct descriptor* d) +{ +	struct atsc_service_location_descriptor *ret = +		(struct atsc_service_location_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 3) +		return NULL; +	bswap16(buf + pos); +	pos+=3; + +	for(idx = 0; idx < ret->number_elements; idx++) { +		if (d->len < (pos + sizeof(struct atsc_caption_service_entry))) +			return NULL; + +		bswap16(buf+pos+1); + +		pos += sizeof(struct atsc_caption_service_entry); +	} + +	return (struct atsc_service_location_descriptor*) d; +} + +/** + * Iterator for elements field of a atsc_service_location_descriptor. + * + * @param d atsc_service_location_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_service_location_element. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_service_location_descriptor_elements_for_each(d, pos, idx) \ +	for ((pos) = atsc_service_location_descriptor_elements_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_service_location_descriptor_elements_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_caption_service_location_element* +	atsc_service_location_descriptor_elements_first(struct atsc_service_location_descriptor *d) +{ +	if (d->number_elements == 0) +		return NULL; + +	return (struct atsc_caption_service_location_element *) +		((uint8_t*) d + sizeof(struct atsc_service_location_descriptor)); +} + +static inline struct atsc_caption_service_location_element* + 	atsc_service_location_descriptor_elements_next(struct atsc_service_location_descriptor *d, +						       struct atsc_caption_service_location_element *pos, + 						       int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_caption_service_location_element); + +	if (idx >= d->number_elements) +		return NULL; +	return (struct atsc_caption_service_location_element *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/stt_section.c b/lib/libucsi/atsc/stt_section.c new file mode 100644 index 0000000..23ddd76 --- /dev/null +++ b/lib/libucsi/atsc/stt_section.c @@ -0,0 +1,42 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/stt_section.h> + +struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t *buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); + +	if (len < sizeof(struct atsc_stt_section)) +		return NULL; + +	bswap32(buf + pos); +	pos += 5; +	bswap16(buf + pos); +	pos += 2; + +	if (verify_descriptors(buf + pos, len - sizeof(struct atsc_stt_section))) +		return NULL; + +	return (struct atsc_stt_section *) psip; +} diff --git a/lib/libucsi/atsc/stt_section.h b/lib/libucsi/atsc/stt_section.h new file mode 100644 index 0000000..79db5a1 --- /dev/null +++ b/lib/libucsi/atsc/stt_section.h @@ -0,0 +1,105 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_STT_SECTION_H +#define _UCSI_ATSC_STT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_stt_section structure. + */ +struct atsc_stt_section { +	struct atsc_section_psip head; + +	atsctime_t system_time; +	uint8_t gps_utc_offset; +  EBIT4(uint16_t DS_status			: 1; , +	uint16_t reserved			: 2; , +	uint16_t DS_day_of_month		: 5; , +	uint16_t DS_hour			: 8; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a atsc_stt_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_stt_section pointer, or NULL on error. + */ +struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *section); + +/** + * Iterator for the services field in a atsc_stt_section. + * + * @param stt atsc_stt_section pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_stt_section_descriptors_for_each(stt, pos) \ +	for ((pos) = atsc_stt_section_descriptors_first(stt); \ +	     (pos); \ +	     (pos) = atsc_stt_section_descriptors_next(stt, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	atsc_stt_section_descriptors_first(struct atsc_stt_section *stt) +{ +	size_t pos = sizeof(struct atsc_stt_section); + +	if (pos >= section_ext_length(&stt->head.ext_head)) +		return NULL; + +	return (struct descriptor*) ((uint8_t *) stt + pos); +} + +static inline struct descriptor * +	atsc_stt_section_descriptors_next(struct atsc_stt_section *stt, +				          struct descriptor *pos) +{ +	int len = section_ext_length(&stt->head.ext_head); +	len -= sizeof(struct atsc_stt_section); + +	return next_descriptor((uint8_t*) stt + sizeof(struct atsc_stt_section), +				len, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/stuffing_descriptor.h b/lib/libucsi/atsc/stuffing_descriptor.h new file mode 100644 index 0000000..777c282 --- /dev/null +++ b/lib/libucsi/atsc/stuffing_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_atsc@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 _UCSI_ATSC_STUFFING_DESCRIPTOR +#define _UCSI_ATSC_STUFFING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * atsc_stuffing_descriptor. + */ +struct atsc_stuffing_descriptor { +	struct descriptor d; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process a atsc_stuffing_descriptor. + * + * @param d Generic descriptor structure. + * @return atsc_stuffing_descriptor pointer, or NULL on error. + */ +static inline struct atsc_stuffing_descriptor* +	atsc_stuffing_descriptor_codec(struct descriptor* d) +{ +	return (struct atsc_stuffing_descriptor*) d; +} + +/** + * Retrieve a pointer to the data field of a atsc_stuffing_descriptor. + * + * @param d atsc_stuffing_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	atsc_stuffing_descriptor_data(struct atsc_stuffing_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct atsc_stuffing_descriptor); +} + +/** + * Calculate length of the data field of a atsc_stuffing_descriptor. + * + * @param d atsc_stuffing_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_stuffing_descriptor_data_length(struct atsc_stuffing_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/time_shifted_service_descriptor.h b/lib/libucsi/atsc/time_shifted_service_descriptor.h new file mode 100644 index 0000000..599e66d --- /dev/null +++ b/lib/libucsi/atsc/time_shifted_service_descriptor.h @@ -0,0 +1,136 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR +#define _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_time_shifted_service_descriptor structure. + */ +struct atsc_time_shifted_service_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t number_of_services	: 5; ); +	/* struct atsc_time_shifted_service services[] */ +} __ucsi_packed; + +/** + * An entry in the services field of an atsc_time_shifted_service_descriptor. + */ +struct atsc_time_shifted_service { +  EBIT2(uint16_t reserved 		: 6; , +	uint16_t time_shift		:10; ); +  EBIT3(uint32_t reserved2 		: 4; , +	uint32_t major_channel_number	:10; , +	uint32_t minor_channel_number	:10; ); +} __ucsi_packed; + +/** + * Process an atsc_time_shifted_service_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_time_shifted_service_descriptor pointer, or NULL on error. + */ +static inline struct atsc_time_shifted_service_descriptor* +	atsc_time_shifted_service_descriptor_codec(struct descriptor* d) +{ +	struct atsc_time_shifted_service_descriptor *ret = +		(struct atsc_time_shifted_service_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->number_of_services; idx++) { +		if (d->len < (pos + sizeof(struct atsc_time_shifted_service))) +			return NULL; + +		bswap16(buf+pos); +		bswap24(buf+pos+2); + +		pos += sizeof(struct atsc_time_shifted_service); +	} + +	return (struct atsc_time_shifted_service_descriptor*) d; +} + +/** + * Iterator for services field of a atsc_time_shifted_service_descriptor. + * + * @param d atsc_time_shifted_service_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_service_location_element. + * @param idx Integer used to count which service we are in. + */ +#define atsc_time_shifted_service_descriptor_services_for_each(d, pos, idx) \ +	for ((pos) = atsc_time_shifted_service_descriptor_services_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_time_shifted_service_descriptor_services_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_time_shifted_service* +	atsc_time_shifted_service_descriptor_services_first(struct atsc_time_shifted_service_descriptor *d) +{ +	if (d->number_of_services == 0) +		return NULL; + +	return (struct atsc_time_shifted_service *) +		((uint8_t*) d + sizeof(struct atsc_time_shifted_service_descriptor)); +} + +static inline struct atsc_time_shifted_service* + 	atsc_time_shifted_service_descriptor_services_next(struct atsc_time_shifted_service_descriptor *d, +							   struct atsc_time_shifted_service *pos, +							   int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_time_shifted_service); + +	if (idx >= d->number_of_services) +		return NULL; +	return (struct atsc_time_shifted_service *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/tvct_section.c b/lib/libucsi/atsc/tvct_section.c new file mode 100644 index 0000000..d187414 --- /dev/null +++ b/lib/libucsi/atsc/tvct_section.c @@ -0,0 +1,81 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/atsc/tvct_section.h> + +struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; +	struct atsc_tvct_section *tvct = (struct atsc_tvct_section *) psip; + +	if (len < sizeof(struct atsc_tvct_section)) +		return NULL; + +	pos++; + +	for(idx =0; idx < tvct->num_channels_in_section; idx++) { + +		if ((pos + sizeof(struct atsc_tvct_channel)) > len) +			return NULL; +		struct atsc_tvct_channel *channel = (struct atsc_tvct_channel *) (buf+pos); + +		pos += 7*2; + +		bswap32(buf+pos); +		bswap32(buf+pos+4); +		bswap16(buf+pos+8); +		bswap16(buf+pos+10); +		bswap16(buf+pos+12); +		bswap16(buf+pos+14); +		bswap16(buf+pos+16); +		pos+=18; + +		if ((pos + channel->descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, channel->descriptors_length)) +			return NULL; + +		pos += channel->descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_tvct_section_part2)) > len) +		return NULL; +	struct atsc_tvct_section_part2 *part2 = (struct atsc_tvct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); +	pos+=2; + +	if ((pos + part2->descriptors_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; + +	if (pos != len) +		return NULL; + +	return (struct atsc_tvct_section *) psip; +} diff --git a/lib/libucsi/atsc/tvct_section.h b/lib/libucsi/atsc/tvct_section.h new file mode 100644 index 0000000..77bc5f4 --- /dev/null +++ b/lib/libucsi/atsc/tvct_section.h @@ -0,0 +1,227 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_ATSC_TVCT_SECTION_H +#define _UCSI_ATSC_TVCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +/** + * atsc_tvct_section structure. + */ +struct atsc_tvct_section { +	struct atsc_section_psip head; + +	uint8_t num_channels_in_section; +	/* struct atsc_tvct_channel channels[] */ + 	/* struct atsc_tvct_channel_part2 part2 */ +} __ucsi_packed; + +struct atsc_tvct_channel { +	uint16_t short_name[7]; // UTF-16 network ordered +  EBIT4(uint32_t reserved			: 4; , +	uint32_t major_channel_number		:10; , +  	uint32_t minor_channel_number		:10; , +	uint32_t modulation_mode		: 8; ); +	uint32_t carrier_frequency; +	uint16_t channel_TSID; +	uint16_t program_number; +  EBIT7(uint16_t ETM_location			: 2; , +	uint16_t access_controlled		: 1; , +	uint16_t hidden				: 1; , +	uint16_t reserved1			: 2; , +	uint16_t hide_guide			: 1; , +	uint16_t reserved2			: 3; , +	uint16_t service_type			: 6; ); +	uint16_t source_id; +  EBIT2(uint16_t reserved3			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_tvct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_tvct_channel *atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct); +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct, struct atsc_tvct_channel *pos, int idx); + +/** + * Process a atsc_tvct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_tvct_section pointer, or NULL on error. + */ +struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the transport_stream_id field of a TVCT. + * + * @param tvct TVCT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t atsc_tvct_section_transport_stream_id(struct atsc_tvct_section *tvct) +{ +	return tvct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the channels field in an atsc_tvct_section. + * + * @param mgt atsc_tvct_section pointer. + * @param pos Variable containing a pointer to the current atsc_tvct_channel. + * @param idx Integer used to count which channel we in. + */ +#define atsc_tvct_section_channels_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_tvct_section_channels_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_tvct_section_channels_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_tvct_channel structure. + * + * @param channel atsc_tvct_channel pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_tvct_channel_descriptors_for_each(channel, pos) \ +	for ((pos) = atsc_tvct_channel_descriptors_first(channel); \ +	     (pos); \ +	     (pos) = atsc_tvct_channel_descriptors_next(channel, pos)) + +/** + * Accessor for the second part of an atsc_tvct_section. + * + * @param mgt atsc_tvct_section pointer. + * @return atsc_tvct_section_part2 pointer. + */ +static inline struct atsc_tvct_section_part2 * +	atsc_tvct_section_part2(struct atsc_tvct_section *mgt) +{ +	int pos = sizeof(struct atsc_tvct_section); + +	struct atsc_tvct_channel *cur_channel; +	int idx; +	atsc_tvct_section_channels_for_each(mgt, cur_channel, idx) { +		pos += sizeof(struct atsc_tvct_channel); +		pos += cur_channel->descriptors_length; +	} + +	return (struct atsc_tvct_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_tvct_section structure. + * + * @param part2 atsc_tvct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_tvct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_tvct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_tvct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct) +{ +	size_t pos = sizeof(struct atsc_tvct_section); + +	if (tvct->num_channels_in_section == 0) +		return NULL; + +	return (struct atsc_tvct_channel*) (((uint8_t *) tvct) + pos); +} + +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct, +				     struct atsc_tvct_channel *pos, +				     int idx) +{ +	if (idx >= tvct->num_channels_in_section) +		return NULL; + +	return (struct atsc_tvct_channel *) +		(((uint8_t*) pos) + sizeof(struct atsc_tvct_channel) + pos->descriptors_length); +} + +static inline struct descriptor * +	atsc_tvct_channel_descriptors_first(struct atsc_tvct_channel *channel) +{ +	size_t pos = sizeof(struct atsc_tvct_channel); + +	if (channel->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) channel) + pos); +} + +static inline struct descriptor * +	atsc_tvct_channel_descriptors_next(struct atsc_tvct_channel *channel, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) channel + sizeof(struct atsc_tvct_channel), +				channel->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_tvct_section_part2_descriptors_first(struct atsc_tvct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_tvct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_tvct_section_part2_descriptors_next(struct atsc_tvct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_tvct_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/types.c b/lib/libucsi/atsc/types.c new file mode 100644 index 0000000..8f4b7ea --- /dev/null +++ b/lib/libucsi/atsc/types.c @@ -0,0 +1,71 @@ +/* + * section and descriptor parser + * + * 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 <string.h> +#include "libucsi/atsc/types.h" + +/* GPS epoch == unix time_t at 06/Jan/1980 */ +#define GPS_EPOCH 315964800 + + +int atsc_text_validate(uint8_t *buf, int len) +{ +	int i; +	int j; +	int number_strings; +	int number_segments; +	int number_bytes; +	int pos = 0; + +	if (len == 0) +		return 0; +	number_strings = buf[pos]; +	pos++; + +	for(i=0; i< number_strings; i++) { +		if (len < (pos+4)) +			return -1; +		number_segments = buf[pos+3]; +		pos+=4; + +		for(j=0; j < number_segments; j++) { +			if (len < (pos+3)) +				return -1; +			number_bytes = buf[pos+2]; +			pos+=3; + +			if (len < (pos + number_bytes)) +				return -1; +			pos += number_bytes; +		} +	} + +	return 0; +} + +time_t atsctime_to_unixtime(atsctime_t atsc) +{ +	return atsc + GPS_EPOCH; +} + +atsctime_t unixtime_to_atsctime(time_t t) +{ +	return t - GPS_EPOCH; +} diff --git a/lib/libucsi/atsc/types.h b/lib/libucsi/atsc/types.h new file mode 100644 index 0000000..4d4b802 --- /dev/null +++ b/lib/libucsi/atsc/types.h @@ -0,0 +1,227 @@ +	/* + * section and descriptor parser + * + * 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 _UCSI_ATSC_TYPES_H +#define _UCSI_ATSC_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <time.h> +#include <libucsi/types.h> + +enum atsc_vct_modulation { +	ATSC_VCT_MODULATION_ANALOG 	= 0x01, +	ATSC_VCT_MODULATION_SCTE_MODE1 	= 0x02, +	ATSC_VCT_MODULATION_SCTE_MODE2 	= 0x03, +	ATSC_VCT_MODULATION_8VSB 	= 0x04, +	ATSC_VCT_MODULATION_16VSB 	= 0x05, +}; + +enum atsc_vct_service_type { +	ATSC_VCT_SERVICE_TYPE_ANALOG 	= 0x01, +	ATSC_VCT_SERVICE_TYPE_TV 	= 0x02, +	ATSC_VCT_SERVICE_TYPE_AUDIO 	= 0x03, +	ATSC_VCT_SERVICE_TYPE_DATA 	= 0x04, +}; + +enum atsc_etm_location { +	ATSC_VCT_ETM_NONE	 		= 0x00, +	ATSC_VCT_ETM_IN_THIS_PTC 		= 0x01, +	ATSC_VCT_ETM_IN_CHANNEL_TSID 		= 0x02, +}; + +enum atsc_text_compress_type { +	ATSC_TEXT_COMPRESS_NONE			= 0x00, +	ATSC_TEXT_COMPRESS_PROGRAM_TITLE	= 0x01, +	ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION	= 0x02, +}; + +enum atsc_text_segment_mode { +	ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MIN	= 0x00, +	ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX	= 0x33, +	ATSC_TEXT_SEGMENT_MODE_SCSU			= 0x3e, +	ATSC_TEXT_SEGMENT_MODE_UTF16			= 0x3f, +	ATSC_TEXT_SEGMENT_MODE_TAIWAN_BITMAP		= 0x40, +	ATSC_TEXT_SEGMENT_MODE_TAIWAN_CODEWORD_BITMAP	= 0x41, +}; + +typedef uint32_t atsctime_t; + +struct atsc_text { +	uint8_t number_strings; +	/* struct atsc_text_string strings[] */ +}; + +struct atsc_text_string { +	iso639lang_t language_code; +	uint8_t number_segments; +	/* struct atsc_text_string_segment segments[] */ +}; + +struct atsc_text_string_segment { +	uint8_t compression_type; +	uint8_t mode; +	uint8_t number_bytes; +	/* uint8_t bytes[] */ +}; + +/** + * Iterator for strings field of an atsc_text structure. + * + * @param txt atsc_text pointer. + * @param pos Variable holding a pointer to the current atsc_text_string. + * @param idx Iterator variable. + */ +#define atsc_text_strings_for_each(txt, pos, idx) \ +	for ((pos) = atsc_text_strings_first(txt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_text_strings_next(txt, pos, ++idx)) + +/** + * Iterator for segments field of an atsc_text_string structure. + * + * @param str atsc_text_string pointer. + * @param pos Variable holding a pointer to the current atsc_text_string_segment. + * @param idx Iterator variable. + */ +#define atsc_text_string_segments_for_each(str, pos, idx) \ +	for ((pos) = atsc_text_string_segments_first(str), idx=0; \ +	     (pos); \ +	     (pos) = atsc_text_string_segments_next(str, pos, ++idx)) + +/** + * Accessor for the bytes field of an atsc_text_string_segment. + * + * @param seg atsc_text_string_segment pointer. + * @return Pointer to the bytes. + */ +static inline uint8_t* +	atsc_text_string_segment_bytes(struct atsc_text_string_segment *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_text_string_segment); +} + +/** + * Validate a buffer containing an atsc_text structure. + * + * @param buf Start of the atsc_text structure. + * @param len Length in bytes of the buffer. + * @return 0 if valid, nonzero if not. + */ +extern int atsc_text_validate(uint8_t *buf, int len); + +/** + * Decodes an atsc_text_segment with mode < 0x3e. Decompression of the ATSC text encoding IS + * supported. The output text will be in the UTF-8 encoding. + * + * @param segment Pointer to the segment to decode. + * @param destbuf Pointer to the malloc()ed buffer to append text to (pass NULL if none). + * @param destbufsize Size of destbuf in bytes. + * @param destbufpos Position within destbuf. This will be updated to point after the end of the + * string on exit. + * @return New value of destbufpos, or < 0 on error. + */ +extern int atsc_text_segment_decode(struct atsc_text_string_segment *segment, +				    uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos); + +/** + * Convert from ATSC time to unix time_t. + * + * @param atsc ATSC time. + * @return The time value. + */ +extern time_t atsctime_to_unixtime(atsctime_t atsc); + +/** + * Convert from unix time_t to atsc time. + * + * @param t unix time_t. + * @return The atsc time value. + */ +extern atsctime_t unixtime_to_atsctime(time_t t); + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_text_string* +	atsc_text_strings_first(struct atsc_text *txt) +{ +	if (txt->number_strings == 0) +		return NULL; + +	return (struct atsc_text_string *) +		((uint8_t*) txt + sizeof(struct atsc_text)); +} + +static inline struct atsc_text_string* +	atsc_text_strings_next(struct atsc_text *txt, struct atsc_text_string *pos, int idx) +{ +	int i; +	uint8_t *buf; + +	if (idx >= txt->number_strings) +		return NULL; + +	buf = ((uint8_t*) pos) + sizeof(struct atsc_text_string); +	for(i=0; i < pos->number_segments; i++) { +		struct atsc_text_string_segment *seg = +			(struct atsc_text_string_segment *) buf; + +		buf += sizeof(struct atsc_text_string_segment); +		buf += seg->number_bytes; +	} + +	return (struct atsc_text_string *) buf; +} + +static inline struct atsc_text_string_segment* +	atsc_text_string_segments_first(struct atsc_text_string *str) +{ +	if (str->number_segments == 0) +		return NULL; + +	return (struct atsc_text_string_segment *) +		((uint8_t*) str + sizeof(struct atsc_text_string)); +} + +static inline struct atsc_text_string_segment* +	atsc_text_string_segments_next(struct atsc_text_string *str, +				       struct atsc_text_string_segment *pos, int idx) +{ +	if (idx >= str->number_segments) +		return NULL; + +	return (struct atsc_text_string_segment *) +		(((uint8_t*) pos) + sizeof(struct atsc_text_string_segment) + pos->number_bytes); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/crc32.c b/lib/libucsi/crc32.c new file mode 100644 index 0000000..dc1de5c --- /dev/null +++ b/lib/libucsi/crc32.c @@ -0,0 +1,89 @@ +/** + * crc32 calculation routines. + * + * Copyright (c) 2005 by 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 <stdint.h> + +uint32_t crc32tbl[] = +{ +	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, +	0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, +	0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, +	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, +	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, +	0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, +	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, +	0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, +	0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, +	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, +	0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, +	0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, +	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, +	0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, +	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, +	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, +	0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, +	0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, +	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, +	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, +	0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, +	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, +	0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, +	0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, +	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, +	0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, +	0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, +	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, +	0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, +	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, +	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, +	0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, +	0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, +	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, +	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, +	0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, +	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, +	0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, +	0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, +	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, +	0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, +	0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, +	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, +	0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, +	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, +	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, +	0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, +	0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, +	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, +	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, +	0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, +	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, +	0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, +	0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, +	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, +	0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, +	0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, +	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, +	0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, +	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, +	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, +	0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, +	0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, +	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; diff --git a/lib/libucsi/crc32.h b/lib/libucsi/crc32.h new file mode 100644 index 0000000..7d781ce --- /dev/null +++ b/lib/libucsi/crc32.h @@ -0,0 +1,58 @@ +/** + * crc32 calculation routines. + * + * Copyright (c) 2005 by 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 _UCSI_CRC32_H +#define _UCSI_CRC32_H 1 + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define CRC32_INIT (~0) + +extern uint32_t crc32tbl[]; + +/** + * Calculate a CRC32 over a piece of data. + * + * @param crc Current CRC value (use CRC32_INIT for first call). + * @param buf Buffer to calculate over. + * @param len Number of bytes. + * @return Calculated CRC. + */ +static inline uint32_t crc32(uint32_t crc, uint8_t* buf, size_t len) +{ +	size_t i; + +	for (i=0; i< len; i++) { +		crc = (crc << 8) ^ crc32tbl[((crc >> 24) ^ buf[i]) & 0xff]; +	} + +	return crc; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/descriptor.h b/lib/libucsi/descriptor.h new file mode 100644 index 0000000..606e45d --- /dev/null +++ b/lib/libucsi/descriptor.h @@ -0,0 +1,129 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_DESCRIPTOR_H +#define _UCSI_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/endianops.h> +#include <stdint.h> +#include <stdlib.h> + +/** + * Generic descriptor header. + */ +struct descriptor { +	uint8_t tag; +	uint8_t len; +} __ucsi_packed; + +/** + * Retreive pointer to the next descriptor structure. + * + * @param buf The buffer of descriptors. + * @param len Size of the buffer. + * @param pos Current descriptor. + * @return Pointer to next descriptor, or NULL if there are none. + */ +static inline struct descriptor * +	next_descriptor(uint8_t * buf, size_t len, struct descriptor * pos) +{ +	uint8_t* next; + +	if (pos == NULL) +		return NULL; + +	next = (uint8_t*) pos + 2 + pos->len; +	if (next >= buf + len) +		return NULL; + +	return (struct descriptor *) next; +} + + +/** + * The unknown descriptor. + */ +struct unknown_descriptor { +	struct descriptor d; + +	/* uint8_t data [] */ +} __ucsi_packed; + +/** + * Retrieve pointer to the unknown descriptor's data field. + * + * @param d The descriptor. + * @return Pointer to the data field. + */ +static inline uint8_t * +	unknown_descriptor_data(struct unknown_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct unknown_descriptor); +} + +/** + * Retrieve size of unknown descriptor's data field. + * + * @param d The descriptor. + * @return Size of data field in bytes. + */ +static inline int +	unknown_descriptor_data_size(struct unknown_descriptor *d) +{ +	return d->d.len; +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline int verify_descriptors(uint8_t * buf, size_t len) +{ +	size_t pos = 0; + +	while (pos < len) { +		if ((pos + 2) > len) +			return -1; + +		pos += 2 + buf[pos+1]; +	} + +	if (pos != len) +		return -1; + +	return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/Makefile b/lib/libucsi/dvb/Makefile new file mode 100644 index 0000000..78876dc --- /dev/null +++ b/lib/libucsi/dvb/Makefile @@ -0,0 +1,121 @@ +# Makefile for linuxtv.org dvb-apps/lib/libucsi/dvb + +.PHONY: sub-error-dvb + +sub-error-dvb: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += dvb/bat_section.o           \ +           dvb/dit_section.o           \ +           dvb/eit_section.o           \ +           dvb/int_section.o           \ +           dvb/nit_section.o           \ +           dvb/rst_section.o           \ +           dvb/sdt_section.o           \ +           dvb/sit_section.o           \ +           dvb/st_section.o            \ +           dvb/tdt_section.o           \ +           dvb/tot_section.o           \ +           dvb/tva_container_section.o \ +           dvb/types.o + +sub-install += dvb + +else + +includes = ac3_descriptor.h                                    \ +           adaptation_field_data_descriptor.h                  \ +           ait_application_descriptor.h                        \ +           ait_application_icons_descriptor.h                  \ +           ait_application_name_descriptor.h                   \ +           ait_external_application_authorisation_descriptor.h \ +           ancillary_data_descriptor.h                         \ +           announcement_support_descriptor.h                   \ +           application_signalling_descriptor.h                 \ +           bat_section.h                                       \ +           bouquet_name_descriptor.h                           \ +           ca_identifier_descriptor.h                          \ +           cable_delivery_descriptor.h                         \ +           cell_frequency_link_descriptor.h                    \ +           cell_list_descriptor.h                              \ +           component_descriptor.h                              \ +           content_descriptor.h                                \ +           content_identifier_descriptor.h                     \ +           country_availability_descriptor.h                   \ +           data_broadcast_descriptor.h                         \ +           data_broadcast_id_descriptor.h                      \ +           default_authority_descriptor.h                      \ +           descriptor.h                                        \ +           dit_section.h                                       \ +           dsng_descriptor.h                                   \ +           eit_section.h                                       \ +           extended_event_descriptor.h                         \ +           frequency_list_descriptor.h                         \ +           int_section.h                                       \ +           ip_mac_platform_name_descriptor.h                   \ +           ip_mac_platform_provider_name_descriptor.h          \ +           ip_mac_stream_location_descriptor.h                 \ +           linkage_descriptor.h                                \ +           local_time_offset_descriptor.h                      \ +           mhp_data_broadcast_id_descriptor.h                  \ +           mosaic_descriptor.h                                 \ +           multilingual_bouquet_name_descriptor.h              \ +           multilingual_component_descriptor.h                 \ +           multilingual_network_name_descriptor.h              \ +           multilingual_service_name_descriptor.h              \ +           network_name_descriptor.h                           \ +           nit_section.h                                       \ +           nvod_reference_descriptor.h                         \ +           parental_rating_descriptor.h                        \ +           partial_transport_stream_descriptor.h               \ +           pdc_descriptor.h                                    \ +           private_data_specifier_descriptor.h                 \ +           related_content_descriptor.h                        \ +           rnt_rar_over_dvb_stream_descriptor.h                \ +           rnt_rar_over_ip_descriptor.h                        \ +           rnt_rnt_scan_descriptor.h                           \ +           rst_section.h                                       \ +           s2_satellite_delivery_descriptor.h                  \ +           satellite_delivery_descriptor.h                     \ +           scrambling_descriptor.h                             \ +           sdt_section.h                                       \ +           section.h                                           \ +           service_availability_descriptor.h                   \ +           service_descriptor.h                                \ +           service_identifier_descriptor.h                     \ +           service_list_descriptor.h                           \ +           service_move_descriptor.h                           \ +           short_event_descriptor.h                            \ +           short_smoothing_buffer_descriptor.h                 \ +           sit_section.h                                       \ +           st_section.h                                        \ +           stream_identifier_descriptor.h                      \ +           stuffing_descriptor.h                               \ +           subtitling_descriptor.h                             \ +           target_ip_address_descriptor.h                      \ +           target_ipv6_address_descriptor.h                    \ +           target_ip_slash_descriptor.h                        \ +           target_ip_source_slash_descriptor.h                 \ +           target_ipv6_slash_descriptor.h                      \ +           target_ipv6_source_slash_descriptor.h               \ +           tdt_section.h                                       \ +           telephone_descriptor.h                              \ +           teletext_descriptor.h                               \ +           terrestrial_delivery_descriptor.h                   \ +           time_shifted_event_descriptor.h                     \ +           time_shifted_service_descriptor.h                   \ +           tot_section.h                                       \ +           transport_stream_descriptor.h                       \ +           tva_container_section.h                             \ +           tva_id_descriptor.h                                 \ +           types.h                                             \ +           vbi_data_descriptor.h                               \ +           vbi_teletext_descriptor.h + +include ../../../Make.rules + +lib_name = libucsi/dvb + +endif diff --git a/lib/libucsi/dvb/ac3_descriptor.h b/lib/libucsi/dvb/ac3_descriptor.h new file mode 100644 index 0000000..0a2a5cd --- /dev/null +++ b/lib/libucsi/dvb/ac3_descriptor.h @@ -0,0 +1,88 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_AC3_DESCRIPTOR +#define _UCSI_DVB_AC3_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_ac3_descriptor structure. + */ +struct dvb_ac3_descriptor { +	struct descriptor d; + +  EBIT5(uint8_t ac3_type_flag		: 1; , +	uint8_t bsid_flag		: 1; , +	uint8_t mainid_flag		: 1; , +	uint8_t asvc_flag		: 1; , +	uint8_t reserved		: 4; ); +	/* uint8_t additional_info[] */ +} __ucsi_packed; + +/** + * Process a dvb_ac3_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_ac3_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ac3_descriptor* +	dvb_ac3_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_ac3_descriptor) - 2)) +		return NULL; + +	return (struct dvb_ac3_descriptor*) d; +} + +/** + * Retrieve pointer to additional_info field of a dvb_ac3_descriptor. + * + * @param d dvb_ac3_descriptor pointer. + * @return Pointer to additional_info field. + */ +static inline uint8_t *dvb_ac3_descriptor_additional_info(struct dvb_ac3_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_ac3_descriptor); +} + +/** + * Determine length of additional_info field of a dvb_ac3_descriptor. + * + * @param d dvb_ac3_descriptor pointer. + * @return Length of field in bytes. + */ +static inline int dvb_ac3_descriptor_additional_info_length(struct dvb_ac3_descriptor *d) +{ +	return d->d.len - 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/adaptation_field_data_descriptor.h b/lib/libucsi/dvb/adaptation_field_data_descriptor.h new file mode 100644 index 0000000..b207054 --- /dev/null +++ b/lib/libucsi/dvb/adaptation_field_data_descriptor.h @@ -0,0 +1,62 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_ADAPTATION_FIELD_DATA_DESCRIPTOR +#define _UCSI_DVB_ADAPTATION_FIELD_DATA_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_adaptation_field_data_descriptor structure. + */ +struct dvb_adaptation_field_data_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved			: 7; , +	uint8_t announcement_switching_data	: 1; ); +} __ucsi_packed; + +/** + * Process a dvb_adaptation_field_data_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to dvb_adaptation_field_data_descriptor, or NULL on error. + */ +static inline struct dvb_adaptation_field_data_descriptor* +	dvb_adaptation_field_data_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_adaptation_field_data_descriptor) - 2)) +		return NULL; + +	return (struct dvb_adaptation_field_data_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ait_application_descriptor.h b/lib/libucsi/dvb/ait_application_descriptor.h new file mode 100644 index 0000000..95fb7e3 --- /dev/null +++ b/lib/libucsi/dvb/ait_application_descriptor.h @@ -0,0 +1,204 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_AIT_APPLICATION_DESCRIPTOR +#define _UCSI_DVB_AIT_APPLICATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for the visibility field. + */ +enum { +	AVB_AIT_APPLICATION_VISIBILITY_HIDDEN		= 0x00, +	AVB_AIT_APPLICATION_VISIBILITY_APPSONLY		= 0x01, +	AVB_AIT_APPLICATION_VISIBILITY_VISIBLE		= 0x03, +}; + +/** + * dvb_ait_application_descriptor structure. + */ +struct dvb_ait_application_descriptor { +	struct descriptor d; + +	uint8_t application_profiles_length; +	/* struct dvb_ait_application_profile profiles [] */ +	/* struct dvb_ait_application_descriptor_part2 part2 */ +} __ucsi_packed; + +/** + * An entry in the profiles field of a dvb_ait_application_descriptor. + */ +struct dvb_ait_application_profile { +	uint16_t application_profile; +	uint8_t version_major; +	uint8_t version_minor; +	uint8_t version_micro; +} __ucsi_packed; + +/** + * Second part of a dvb_ait_application_descriptor structure. + */ +struct dvb_ait_application_descriptor_part2 { +  EBIT3(uint8_t service_bound_flag		: 1; , +	uint8_t visibility			: 2; , +	uint8_t reserved			: 5; ); +	uint8_t application_priority; +	/* uint8_t transport_protocol_label[] */ +} __ucsi_packed; + +/** + * Process a dvb_ait_application_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ait_application_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ait_application_descriptor* +	dvb_ait_application_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t pos2 = 0; +	uint32_t len = d->len + 2; +	uint8_t* buf = (uint8_t*) d; +	struct dvb_ait_application_descriptor *ret = +		(struct dvb_ait_application_descriptor*) d; + +	if (len < sizeof(struct dvb_ait_application_descriptor)) +		return NULL; + +	if (len < (sizeof(struct dvb_ait_application_descriptor) + ret->application_profiles_length)) +		return NULL; + +	if (ret->application_profiles_length % sizeof(struct dvb_ait_application_profile)) +		return NULL; + +	pos += sizeof(struct dvb_ait_application_descriptor); +	pos2 = 0; +	while(pos2 < ret->application_profiles_length) { +		bswap16(buf + pos + pos2); +		pos2 += sizeof(struct dvb_ait_application_descriptor); +	} +	pos += pos2; + +	if (len < (pos + sizeof(struct dvb_ait_application_descriptor_part2))) +		return NULL; + +	return ret; +} + +/** + * Iterator for the profiles field of a dvb_ait_application_descriptor. + * + * @param d dvb_ait_application_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ait_application_profile. + */ +#define dvb_ait_application_descriptor_profiles_for_each(d, pos) \ +	for ((pos) = dvb_ait_application_descriptor_profiles_first(d); \ +	     (pos); \ +	     (pos) = dvb_ait_application_descriptor_profiles_next(d, pos)) + +/** + * Accessor for the part2 field of a dvb_ait_application_descriptor. + * + * @param d dvb_ait_application_descriptor pointer. + * @return dvb_ait_application_descriptor_part2 pointer. + */ +static inline struct dvb_ait_application_descriptor_part2* +	dvb_ait_application_descriptor_part2(struct dvb_ait_application_descriptor* d) +{ +	return (struct dvb_ait_application_descriptor_part2*) +		((uint8_t*) d + +		 sizeof(struct dvb_ait_application_descriptor) + +		 d->application_profiles_length); +} + +/** + * Accessor for the transport_protocol_label field of a dvb_ait_application_descriptor_part2. + * + * @param d dvb_ait_application_descriptor_part2 pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_ait_application_descriptor_part2_transport_protocol_label(struct dvb_ait_application_descriptor_part2* d) +{ +	return (uint8_t*) d + +			sizeof(struct dvb_ait_application_descriptor_part2); +} + +/** + * Calculate the number of bytes in the transport_protocol_label field of a dvb_ait_application_descriptor_part2. + * + * @param d dvb_ait_application_descriptor pointer. + * @param part2 dvb_ait_application_descriptor_part2 pointer. + * @return Number of bytes. + */ +static inline int +	dvb_ait_application_descriptor_part2_transport_protocol_label_length(struct dvb_ait_application_descriptor *d, +									     struct dvb_ait_application_descriptor_part2* part2) +{ +	uint8_t *ptr = (uint8_t*) part2 + sizeof(struct dvb_ait_application_descriptor_part2); +	uint8_t *end = (uint8_t*) d + d->d.len + 2; + +	return (int) (end - ptr); +} + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ait_application_profile* +	dvb_ait_application_descriptor_profiles_first(struct dvb_ait_application_descriptor *d) +{ +	if (d->application_profiles_length == 0) +		return NULL; + +	return (struct dvb_ait_application_profile *) +		((uint8_t*) d + sizeof(struct dvb_ait_application_descriptor)); +} + +static inline struct dvb_ait_application_profile* +	dvb_ait_application_descriptor_profiles_next(struct dvb_ait_application_descriptor *d, +						     struct dvb_ait_application_profile *pos) +{ +	uint8_t *end = (uint8_t*) d + +			sizeof(struct dvb_ait_application_descriptor) + +			d->application_profiles_length; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ait_application_profile); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ait_application_profile *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ait_application_icons_descriptor.h b/lib/libucsi/dvb/ait_application_icons_descriptor.h new file mode 100644 index 0000000..431cd6c --- /dev/null +++ b/lib/libucsi/dvb/ait_application_icons_descriptor.h @@ -0,0 +1,157 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_AIT_APPLICATION_ICONS_DESCRIPTOR +#define _UCSI_DVB_AIT_APPLICATION_ICONS_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Possible values for the icon_flags field. + */ +enum { +	AIT_APPLICATION_ICON_FLAG_32_32		= 0x001, +	AIT_APPLICATION_ICON_FLAG_32_32_43	= 0x002, +	AIT_APPLICATION_ICON_FLAG_24_32_169	= 0x004, + +	AIT_APPLICATION_ICON_FLAG_64_64		= 0x008, +	AIT_APPLICATION_ICON_FLAG_64_64_43	= 0x010, +	AIT_APPLICATION_ICON_FLAG_48_64_169	= 0x020, + +	AIT_APPLICATION_ICON_FLAG_128_128	= 0x040, +	AIT_APPLICATION_ICON_FLAG_128_128_43	= 0x080, +	AIT_APPLICATION_ICON_FLAG_96_128_169	= 0x100, +}; + +/** + * dvb_ait_application_icons_descriptor structure. + */ +struct dvb_ait_application_icons_descriptor { +	struct descriptor d; + +	uint8_t icon_locator_length; +	/* uint8_t icon_locator[] */ +	/* struct dvb_ait_application_icons_descriptor_part2 */ +} __ucsi_packed; + +/** + * Second part of a dvb_ait_application_icons_descriptor. + */ +struct dvb_ait_application_icons_descriptor_part2 { +	uint16_t icon_flags; +	/* uint8_t reserved[] */ +} __ucsi_packed; + +/** + * Process a dvb_ait_application_icons_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ait_application_icons_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ait_application_icons_descriptor* +	dvb_ait_application_icons_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d; +	uint32_t pos = 0; +	uint32_t len = d->len + 2; +	struct dvb_ait_application_icons_descriptor *ret = +		(struct dvb_ait_application_icons_descriptor *) d; + +	if (len < sizeof(struct dvb_ait_application_icons_descriptor)) +		return NULL; +	if (len < (sizeof(struct dvb_ait_application_icons_descriptor) + ret->icon_locator_length)) +		return NULL; + +	pos += sizeof(struct dvb_ait_application_icons_descriptor) + ret->icon_locator_length; + +	if ((len - pos) < sizeof(struct dvb_ait_application_icons_descriptor_part2)) +		return NULL; +	bswap16(buf + pos); + +	return ret; +} +/** + * Accessor for the icon_locator field of a dvb_ait_application_icons_descriptor. + * + * @param e dvb_ait_application_icons_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_ait_application_icons_descriptor_icon_locator(struct dvb_ait_application_icons_descriptor *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor); +} + +/** + * Accessor for the part2 field of a dvb_ait_application_icons_descriptor. + * + * @param e dvb_ait_application_icons_descriptor Pointer. + * @return dvb_ait_application_icons_descriptor_part2 pointer. + */ +static inline struct dvb_ait_application_icons_descriptor_part2 * +	dvb_ait_application_icons_descriptor_part2(struct dvb_ait_application_icons_descriptor *e) +{ +	return (struct dvb_ait_application_icons_descriptor_part2 *) +		((uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor) + +		e->icon_locator_length); +} + +/** + * Accessor for the reserved field of a dvb_ait_application_icons_descriptor_part2. + * + * @param e dvb_ait_application_icons_part2 pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_ait_application_icons_descriptor_part2_reserved(struct dvb_ait_application_icons_descriptor_part2 *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor_part2); +} + +/** + * Calculate the number of bytes in the reserved field of a dvb_ait_application_icons_descriptor_part2. + * + * @param d dvb_ait_application_icons_descriptorpointer. + * @param part2 dvb_ait_application_icons_descriptor_part2 pointer. + * @return Number of bytes. + */ +static inline int +	dvb_ait_application_icons_descriptor_part2_reserved_length(struct dvb_ait_application_icons_descriptor *d, +		struct dvb_ait_application_icons_descriptor_part2* part2) +{ +	uint8_t *ptr = (uint8_t*) part2 + sizeof(struct dvb_ait_application_icons_descriptor_part2); +	uint8_t *end = (uint8_t*) d + d->d.len + 2; + +	return (int) (end - ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ait_application_name_descriptor.h b/lib/libucsi/dvb/ait_application_name_descriptor.h new file mode 100644 index 0000000..a4b719e --- /dev/null +++ b/lib/libucsi/dvb/ait_application_name_descriptor.h @@ -0,0 +1,145 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_AIT_APPLICATION_NAME_DESCRIPTOR +#define _UCSI_DVB_AIT_APPLICATION_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_ait_application_name_descriptor structure. + */ +struct dvb_ait_application_name_descriptor { +	struct descriptor d; + +	/* struct dvb_ait_application_name names[] */ +} __ucsi_packed; + +/** + * An entry in the names field of a dvb_ait_application_name_descriptor. + */ +struct dvb_ait_application_name { +	iso639lang_t language_code; +	uint8_t application_name_length; +	/* uint8_t name[] */ +} __ucsi_packed; + +/** + * Process a dvb_ait_application_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ait_application_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ait_application_name_descriptor* +	dvb_ait_application_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_ait_application_name *e = +			(struct dvb_ait_application_name*) (buf + pos); + +		pos += sizeof(struct dvb_ait_application_name); + +		if (pos > len) +			return NULL; + +		pos += e->application_name_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_ait_application_name_descriptor*) d; +} + +/** + * Iterator for entries in the names field of a dvb_ait_application_name_descriptor. + * + * @param d dvb_ait_application_name_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ait_application_name. + */ +#define dvb_ait_application_name_descriptor_names_for_each(d, pos) \ +	for ((pos) = dvb_ait_application_name_descriptor_names_first(d); \ +	     (pos); \ +	     (pos) = dvb_ait_application_name_descriptor_names_next(d, pos)) + +/** + * Accessor for the name field of a dvb_ait_application_name. + * + * @param e dvb_ait_application_name pointer. + * @return Pointer to the name field. + */ +static inline uint8_t * +	dvb_ait_application_name_name(struct dvb_ait_application_name *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_ait_application_name); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ait_application_name* +	dvb_ait_application_name_descriptor_names_first(struct dvb_ait_application_name_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ait_application_name *) +		((uint8_t*) d + sizeof(struct dvb_ait_application_name_descriptor)); +} + +static inline struct dvb_ait_application_name* +	dvb_ait_application_name_descriptor_names_next(struct dvb_ait_application_name_descriptor *d, +							    struct dvb_ait_application_name *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_ait_application_name) + +			pos->application_name_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_ait_application_name *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h b/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h new file mode 100644 index 0000000..34f584a --- /dev/null +++ b/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h @@ -0,0 +1,125 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_AIT_EXTERNAL_APPLICATION_AUTHORISATION_DESCRIPTOR +#define _UCSI_DVB_AIT_EXTERNAL_APPLICATION_AUTHORISATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_ait_external_application_authorisation_descriptor structure. + */ +struct dvb_ait_external_application_authorisation_descriptor { +	struct descriptor d; + +	/* struct dvb_ait_external_application_authorisation auths[] */ +} __ucsi_packed; + +/** + * An entry in the auths field of a dvb_ait_external_application_authorisation_descriptor. + */ +struct dvb_ait_external_application_authorisation { +	uint32_t organization_id; +	uint16_t application_id; +	uint8_t application_priority; +} __ucsi_packed; + +/** + * Process a dvb_ait_external_application_authorisation_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ait_external_application_authorisation_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ait_external_application_authorisation_descriptor* +	dvb_ait_external_application_authorisation_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_ait_external_application_authorisation)) +		return NULL; + +	while(pos < len) { +		bswap32(buf + pos); +		bswap32(buf + pos + 4); +		pos += sizeof(struct dvb_ait_external_application_authorisation); +	} + +	return (struct dvb_ait_external_application_authorisation_descriptor*) d; +} + +/** + * Iterator for entries in the auths field of a dvb_ait_external_application_authorisation_descriptor. + * + * @param d dvb_ait_external_application_authorisation_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ait_external_application_authorisation. + */ +#define dvb_ait_external_application_authorisation_descriptor_auths_for_each(d, pos) \ +	for ((pos) = dvb_ait_external_application_authorisation_descriptor_auths_first(d); \ +	     (pos); \ +	     (pos) = dvb_ait_external_application_authorisation_descriptor_auths_next(d, pos)) + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ait_external_application_authorisation* +	dvb_ait_external_application_authorisation_descriptor_auths_first(struct dvb_ait_external_application_authorisation_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ait_external_application_authorisation *) +		((uint8_t*) d + sizeof(struct dvb_ait_external_application_authorisation_descriptor)); +} + +static inline struct dvb_ait_external_application_authorisation* +	dvb_ait_external_application_authorisation_descriptor_auths_next(struct dvb_ait_external_application_authorisation_descriptor *d, +							    struct dvb_ait_external_application_authorisation *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_ait_external_application_authorisation); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ait_external_application_authorisation *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ancillary_data_descriptor.h b/lib/libucsi/dvb/ancillary_data_descriptor.h new file mode 100644 index 0000000..04b2f59 --- /dev/null +++ b/lib/libucsi/dvb/ancillary_data_descriptor.h @@ -0,0 +1,67 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_ANCILLARY_DATA_DESCRIPTOR +#define _UCSI_DVB_ANCILLARY_DATA_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_ancillary_data_descriptor structure. + */ +struct dvb_ancillary_data_descriptor { +	struct descriptor d; +  EBIT8(uint8_t reserved			: 1; , +	uint8_t rds_via_udcp			: 1; , +	uint8_t mpeg4_ancillary_data		: 1; , +	uint8_t scale_factor_error_check	: 1; , +	uint8_t dab_ancillary_data		: 1; , +	uint8_t announcement_switching_data	: 1; , +	uint8_t extended_ancillary_data		: 1; , +	uint8_t dvd_video_ancillary_data	: 1; ); +} __ucsi_packed; + +/** + * Process a dvb_ancillary_data_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ancillary_data_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ancillary_data_descriptor* +	dvb_ancillary_data_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_ancillary_data_descriptor) - 2)) +		return NULL; + +	return (struct dvb_ancillary_data_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/announcement_support_descriptor.h b/lib/libucsi/dvb/announcement_support_descriptor.h new file mode 100644 index 0000000..9eb20c4 --- /dev/null +++ b/lib/libucsi/dvb/announcement_support_descriptor.h @@ -0,0 +1,219 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_ANNOUNCEMENT_SUPPORT_DESCRIPTOR +#define _UCSI_DVB_ANNOUNCEMENT_SUPPORT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for announcement_support_indicator. + */ +enum { +	DVB_ANNOUNCEMENT_SUPPORT_EMERGENCY		= 0x01, +	DVB_ANNOUNCEMENT_SUPPORT_ROAD_TRAFFIC_FLASH	= 0x02, +	DVB_ANNOUNCEMENT_SUPPORT_PUBLIC_TRANSPORT_FLASH	= 0x04, +	DVB_ANNOUNCEMENT_SUPPORT_WARNING_MESSAGE	= 0x08, +	DVB_ANNOUNCEMENT_SUPPORT_NEWS_FLASH		= 0x10, +	DVB_ANNOUNCEMENT_SUPPORT_WEATHER_FLASH		= 0x20, +	DVB_ANNOUNCEMENT_SUPPORT_EVENT_ANNOUNCEMENT	= 0x40, +	DVB_ANNOUNCEMENT_SUPPORT_PERSONAL_CALL		= 0x80, +}; + +/** + * Possible values for announcement_type. + */ +enum { +	DVB_ANNOUNCEMENT_TYPE_EMERGENCY			= 0x00, +	DVB_ANNOUNCEMENT_TYPE_ROAD_TRAFFIC_FLASH	= 0x01, +	DVB_ANNOUNCEMENT_TYPE_PUBLIC_TRANSPORT_FLASH	= 0x02, +	DVB_ANNOUNCEMENT_TYPE_WARNING_MESSAGE		= 0x03, +	DVB_ANNOUNCEMENT_TYPE_NEWS_FLASH		= 0x04, +	DVB_ANNOUNCEMENT_TYPE_WEATHER_FLASH		= 0x05, +	DVB_ANNOUNCEMENT_TYPE_EVENT_ANNOUNCEMENT	= 0x06, +	DVB_ANNOUNCEMENT_TYPE_PERSONAL_CALL		= 0x07, +}; + +/** + * Possible values for reference_type. + */ +enum { +	DVB_REFERENCE_TYPE_AUDIO			= 0x00, +	DVB_REFERENCE_TYPE_OTHER_AUDIO			= 0x01, +	DVB_REFERENCE_TYPE_OTHER_SERVICE		= 0x02, +	DVB_REFERENCE_TYPE_OTHER_TS			= 0x03, +}; + +/** + * dvb_announcement_support_descriptor structure. + */ +struct dvb_announcement_support_descriptor { +	struct descriptor d; +	uint16_t announcement_support_indicator; +	/* struct dvb_announcement_support_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_announcement_support_descriptor. + */ +struct dvb_announcement_support_entry { +  EBIT3(uint8_t announcement_type		: 4; , +	uint8_t reserved			: 1; , +	uint8_t reference_type			: 3; ); +	/* Only if reference_type == 1, 2 or 3: +	 * struct dvb_announcement_support_reference reference */ +} __ucsi_packed; + +/** + * The optional reference field only present in a dvb_announcement_support_descriptor if + * its reference_type field is 1,2 or 3. + */ +struct dvb_announcement_support_reference { +	uint16_t original_network_id; +	uint16_t transport_stream_id; +	uint16_t service_id; +	uint8_t component_tag; +} __ucsi_packed; + +/** + * Process a dvb_announcement_support_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_announcement_support_descriptor pointer, or NULL on error. + */ +static inline struct dvb_announcement_support_descriptor* +	dvb_announcement_support_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	if (len < (sizeof(struct dvb_announcement_support_descriptor) - 2)) +		return NULL; + +	bswap16(buf+pos); + +	pos += 2; + +	while(pos < len) { +		struct dvb_announcement_support_entry *e = +			(struct dvb_announcement_support_entry*) (buf+pos); + +		pos += sizeof(struct dvb_announcement_support_entry); + +		if (pos > len) +			return NULL; + +		if ((e->reference_type == 1) || +		    (e->reference_type == 2) || +		    (e->reference_type == 3)) { +			if ((pos + sizeof(struct dvb_announcement_support_reference)) > len) +				return NULL; + +			bswap16(buf+pos); +			bswap16(buf+pos+2); +			bswap16(buf+pos+4); + +			pos += sizeof(struct dvb_announcement_support_reference); +		} +	} + +	return (struct dvb_announcement_support_descriptor*) d; +} + +/** + * Iterator for the entries field of a dvb_announcement_support_descriptor. + * + * @param d dvb_announcement_support_descriptor pointer. + * @param pod Variable holding a pointer to the current dvb_announcement_support_entry. + */ +#define dvb_announcement_support_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_announcement_support_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_announcement_support_descriptor_entries_next(d, pos)) + +/** + * Accessor for the reference field of a dvb_announcement_support_entry if present. + * + * @param entry dvb_announcement_support_entry pointer. + * @return dvb_announcement_support_reference pointer, or NULL on error. + */ +static inline struct dvb_announcement_support_reference* +	dvb_announcement_support_entry_reference(struct dvb_announcement_support_entry* entry) +{ +	if ((entry->reference_type != 0x01) && +	    (entry->reference_type != 0x02) && +	    (entry->reference_type != 0x03)) +		return NULL; + +	return (struct dvb_announcement_support_reference*) +		((uint8_t*) entry + sizeof(struct dvb_announcement_support_entry)); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_announcement_support_entry* +	dvb_announcement_support_descriptor_entries_first(struct dvb_announcement_support_descriptor *d) +{ +	if (d->d.len == 2) +		return NULL; + +	return (struct dvb_announcement_support_entry *) +		((uint8_t*) d + sizeof(struct dvb_announcement_support_descriptor)); +} + +static inline struct dvb_announcement_support_entry* +	dvb_announcement_support_descriptor_entries_next(struct dvb_announcement_support_descriptor *d, +							 struct dvb_announcement_support_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t* next = (uint8_t*) pos + sizeof(struct dvb_announcement_support_entry); +	struct dvb_announcement_support_reference* reference = +		dvb_announcement_support_entry_reference(pos); + +	if (reference) +		next += sizeof(struct dvb_announcement_support_reference); + +	if (next >= end) +		return NULL; + +	return (struct dvb_announcement_support_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/application_signalling_descriptor.h b/lib/libucsi/dvb/application_signalling_descriptor.h new file mode 100644 index 0000000..78211cf --- /dev/null +++ b/lib/libucsi/dvb/application_signalling_descriptor.h @@ -0,0 +1,124 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_APPLICATION_SIGNALLING_DESCRIPTOR +#define _UCSI_DVB_APPLICATION_SIGNALLING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_application_signalling_descriptor structure. + */ +struct dvb_application_signalling_descriptor { +	struct descriptor d; + +	/* struct dvb_application_signalling_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_application_signalling_descriptor. + */ +struct dvb_application_signalling_entry { +	uint16_t application_type; +  EBIT2(uint8_t reserved		: 3; , +	uint8_t AIT_version_number	: 5; ); +} __ucsi_packed; + +/** + * Process a dvb_application_signalling_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_application_signalling_descriptor pointer, or NULL on error. + */ +static inline struct dvb_application_signalling_descriptor* +	dvb_application_signalling_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t len = d->len; +	uint8_t* buf = (uint8_t*) d + 2; + +	pos += sizeof(struct dvb_application_signalling_descriptor) - 2; +	if (len % sizeof(struct dvb_application_signalling_entry)) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos+=3; +	} + +	return (struct dvb_application_signalling_descriptor*) d; +} + +/** + * Iterator for the entries field of a dvb_application_signalling_descriptor. + * + * @param d dvb_application_signalling_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_application_signalling_entry. + */ +#define dvb_application_signalling_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_application_signalling_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_application_signalling_descriptor_entries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_application_signalling_entry* +	dvb_application_signalling_descriptor_entries_first(struct dvb_application_signalling_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_application_signalling_entry *) +		((uint8_t*) d + sizeof(struct dvb_application_signalling_descriptor)); +} + +static inline struct dvb_application_signalling_entry* +	dvb_application_signalling_descriptor_entries_next(struct dvb_application_signalling_descriptor *d, +							   struct dvb_application_signalling_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_application_signalling_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_application_signalling_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/bat_section.c b/lib/libucsi/dvb/bat_section.c new file mode 100644 index 0000000..99e5cf6 --- /dev/null +++ b/lib/libucsi/dvb/bat_section.c @@ -0,0 +1,77 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/bat_section.h> + +struct dvb_bat_section * dvb_bat_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); +	struct dvb_bat_section * ret = (struct dvb_bat_section *) ext; + +	if (len < sizeof(struct dvb_bat_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	if ((pos + ret->bouquet_descriptors_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, ret->bouquet_descriptors_length)) +		return NULL; +	pos += ret->bouquet_descriptors_length; + +	if ((pos + sizeof(struct dvb_bat_section_part2)) > len) +		return NULL; + +	bswap16(buf + pos); +	pos += sizeof(struct dvb_bat_section_part2); + +	while (pos < len) { +		struct dvb_bat_transport * transport = +			(struct dvb_bat_transport *) (buf + pos); + +		if ((pos + sizeof(struct dvb_bat_transport))  > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 2); +		bswap16(buf + pos + 4); + +		pos += sizeof(struct dvb_bat_transport); + +		if ((pos + transport->transport_descriptors_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, +					transport->transport_descriptors_length)) +			return NULL; + +		pos += transport->transport_descriptors_length; +	} + +	if (pos != len) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/bat_section.h b/lib/libucsi/dvb/bat_section.h new file mode 100644 index 0000000..94ed8a4 --- /dev/null +++ b/lib/libucsi/dvb/bat_section.h @@ -0,0 +1,211 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_BAT_SECTION_H +#define _UCSI_DVB_BAT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_bat_section structure. + */ +struct dvb_bat_section { +	struct section_ext head; + +  EBIT2(uint16_t reserved_1			: 4; , +	uint16_t bouquet_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +	/* struct dvb_bat_section_part2 part2 */ +}; + +/** + * Second part of a dvb_bat_section, following the variable length descriptors field. + */ +struct dvb_bat_section_part2 { +  EBIT2(uint16_t reserved_2			: 4; , +	uint16_t transport_stream_loop_length	:12; ); +	/* struct dvb_bat_transport transports[] */ +} __ucsi_packed; + +/** + * An entry in the transports field of a dvb_bat_section_part2. + */ +struct dvb_bat_transport { +	uint16_t transport_stream_id; +	uint16_t original_network_id; +  EBIT2(uint16_t reserved			: 4; , +	uint16_t transport_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +}; + +/** + * Process a dvb_bat_section. + * + * @param section Generic section  pointer. + * @return dvb_bat_section pointer, or NULL on error. + */ +struct dvb_bat_section *dvb_bat_section_codec(struct section_ext *section); + +/** + * Accessor for the bouquet_id field of a BAT. + * + * @param bat BAT pointer. + * @return The bouquet_id. + */ +static inline uint16_t dvb_bat_section_bouquet_id(struct dvb_bat_section *bat) +{ +	return bat->head.table_id_ext; +} + +/** + * Iterator for the descriptors field in a dvb_bat_section. + * + * @param bat dvb_bat_section pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define dvb_bat_section_descriptors_for_each(bat, pos) \ +	for ((pos) = dvb_bat_section_descriptors_first(bat); \ +	     (pos); \ +	     (pos) = dvb_bat_section_descriptors_next(bat, pos)) + +/** + * Accessor for the second part of a dvb_bat_section. + * + * @param bat dvb_bat_section pointer. + * @return dvb_bat_section_part2 pointer. + */ +static inline struct dvb_bat_section_part2 * +	dvb_bat_section_part2(struct dvb_bat_section *bat) +{ +	return (struct dvb_bat_section_part2 *) +		((uint8_t*) bat + +		 sizeof(struct dvb_bat_section) + +		 bat->bouquet_descriptors_length); + +} + +/** + * Iterator for the transports field of a dvb_bat_section_part2. + * + * @param part2 dvb_bat_section_part2 pointer. + * @param pos Variable containing a pointer to the current dvb_bat_transport. + */ +#define dvb_bat_section_transports_for_each(part2, pos) \ +	for ((pos) = dvb_bat_section_transports_first(part2); \ +	     (pos); \ +	     (pos) = dvb_bat_section_transports_next(part2, pos)) + +/** + * Iterator for the descriptors field of a dvb_bat_transport. + * + * @param transport dvb_bat_transport pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define dvb_bat_transport_descriptors_for_each(transport, pos) \ +	for ((pos) = dvb_bat_transport_descriptors_first(transport); \ +	     (pos); \ +	     (pos) = dvb_bat_transport_descriptors_next(transport, pos)) + + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	dvb_bat_section_descriptors_first(struct dvb_bat_section *bat) +{ +	if (bat->bouquet_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) bat + sizeof(struct dvb_bat_section)); +} + +static inline struct descriptor * +	dvb_bat_section_descriptors_next(struct dvb_bat_section *bat, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) bat + sizeof(struct dvb_bat_section), +			       bat->bouquet_descriptors_length, +			       pos); +} + +static inline struct dvb_bat_transport * +	dvb_bat_section_transports_first(struct dvb_bat_section_part2 *part2) +{ +	if (part2->transport_stream_loop_length == 0) +		return NULL; + +	return (struct dvb_bat_transport *) +		((uint8_t *) part2 + sizeof(struct dvb_bat_section_part2)); +} + +static inline struct dvb_bat_transport * +	dvb_bat_section_transports_next(struct dvb_bat_section_part2 *part2, +					struct dvb_bat_transport *pos) +{ +	uint8_t *end = (uint8_t*) part2 + sizeof(struct dvb_bat_section_part2) + +			part2->transport_stream_loop_length; +	uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_bat_transport) + +			pos->transport_descriptors_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_bat_transport *) next; +} + +static inline struct descriptor * +	dvb_bat_transport_descriptors_first(struct dvb_bat_transport *t) +{ +	if (t->transport_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t*)t + sizeof(struct dvb_bat_transport)); +} + +static inline struct descriptor * +	dvb_bat_transport_descriptors_next(struct dvb_bat_transport *t, +					   struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) t + sizeof(struct dvb_bat_transport), +			       t->transport_descriptors_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/bouquet_name_descriptor.h b/lib/libucsi/dvb/bouquet_name_descriptor.h new file mode 100644 index 0000000..a298849 --- /dev/null +++ b/lib/libucsi/dvb/bouquet_name_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_BOUQUET_NAME_DESCRIPTOR +#define _UCSI_DVB_BOUQUET_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_bouquet_name_descriptor  structure. + */ +struct dvb_bouquet_name_descriptor { +	struct descriptor d; + +	/* uint8_t name[] */ +} __ucsi_packed; + +/** + * Process a dvb_bouquet_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_bouquet_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_bouquet_name_descriptor* +	dvb_bouquet_name_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_bouquet_name_descriptor*) d; +} + +/** + * Accessor for the name field of a dvb_bouquet_name_descriptor. + * + * @param d dvb_bouquet_name_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_bouquet_name_descriptor_name(struct dvb_bouquet_name_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_bouquet_name_descriptor); +} + +/** + * Determine the length of the name field of a dvb_bouquet_name_descriptor in bytes. + * + * @param d dvb_bouquet_name_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_bouquet_name_descriptor_name_length(struct dvb_bouquet_name_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ca_identifier_descriptor.h b/lib/libucsi/dvb/ca_identifier_descriptor.h new file mode 100644 index 0000000..ac670a9 --- /dev/null +++ b/lib/libucsi/dvb/ca_identifier_descriptor.h @@ -0,0 +1,94 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CA_IDENTIFIER_DESCRIPTOR +#define _UCSI_DVB_CA_IDENTIFIER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_ca_identifier_descriptor structure. + */ +struct dvb_ca_identifier_descriptor { +	struct descriptor d; + +	/* uint16_t ca_system_ids[] */ +} __ucsi_packed; + +/** + * Process a dvb_ca_identifier_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ca_identifier_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ca_identifier_descriptor* +	dvb_ca_identifier_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; +	uint8_t *buf = (uint8_t*) d + 2; +	uint32_t pos = 0; + +	if (len % 2) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos+=2; +	} + +	return (struct dvb_ca_identifier_descriptor*) d; +} + +/** + * Accessor for the ca_system_ids field of a dvb_ca_identifier_descriptor. + * + * @param d Generic descriptor pointer. + * @return Pointer to the field. + */ +static inline uint16_t * +	dvb_ca_identifier_descriptor_ca_system_ids(struct dvb_ca_identifier_descriptor *d) +{ +	return (uint16_t *) ((uint8_t *) d + sizeof(struct dvb_ca_identifier_descriptor)); +} + +/** + * Calculate the number of entries in the ca_system_ids field of a dvb_ca_identifier_descriptor. + * + * @param d dvb_ca_identifier_descriptor pointer. + * @return Number of entries. + */ +static inline int +	dvb_ca_identifier_descriptor_ca_system_ids_count(struct dvb_ca_identifier_descriptor *d) +{ +	return d->d.len >> 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/cable_delivery_descriptor.h b/lib/libucsi/dvb/cable_delivery_descriptor.h new file mode 100644 index 0000000..f0f92f3 --- /dev/null +++ b/lib/libucsi/dvb/cable_delivery_descriptor.h @@ -0,0 +1,70 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CABLE_DELIVERY_DESCRIPTOR +#define _UCSI_DVB_CABLE_DELIVERY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_cable_delivery_descriptor structure. + */ +struct dvb_cable_delivery_descriptor { +	struct descriptor d; + +	uint32_t frequency;			// BCD, units 100Hz +  EBIT2(uint16_t reserved	: 12; , +	uint16_t fec_outer	: 4;  ); +	uint8_t modulation; +  EBIT2(uint32_t symbol_rate	: 28; ,		// BCD, units 100Hz +	uint32_t fec_inner	: 4;  ); +} __ucsi_packed; + +/** + * Process a dvb_cable_delivery_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_cable_delivery_descriptor pointer, or NULL on error. + */ +static inline struct dvb_cable_delivery_descriptor* +	dvb_cable_delivery_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_cable_delivery_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 6); +	bswap32((uint8_t*) d + 9); + +	return (struct dvb_cable_delivery_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/cell_frequency_link_descriptor.h b/lib/libucsi/dvb/cell_frequency_link_descriptor.h new file mode 100644 index 0000000..63f7fd2 --- /dev/null +++ b/lib/libucsi/dvb/cell_frequency_link_descriptor.h @@ -0,0 +1,190 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CELL_FREQUENCY_LINK_DESCRIPTOR +#define _UCSI_DVB_CELL_FREQUENCY_LINK_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_cell_frequency_link_descriptor structure. + */ +struct dvb_cell_frequency_link_descriptor { +	struct descriptor d; + +	/* struct dvb_cell_frequency_link_cell cells[] */ +} __ucsi_packed; + +/** + * An entry in the cells field of a dvb_cell_frequency_link_descriptor. + */ +struct dvb_cell_frequency_link_cell { +	uint16_t cell_id; +	uint32_t frequency; +	uint8_t subcell_loop_info_length; +	/* struct dvb_cell_frequency_link_subcell subcells[] */ +} __ucsi_packed; + +/** + * An entry in the subcells field of a dvb_cell_frequency_link_cell. + */ +struct dvb_cell_frequency_link_cell_subcell { +	uint8_t cell_id_extension; +	uint32_t transposer_frequency; +} __ucsi_packed; + +/** + * Process a dvb_cell_frequency_link_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_cell_frequency_link_descriptor pointer, or NULL on error. + */ +static inline struct dvb_cell_frequency_link_descriptor* +	dvb_cell_frequency_link_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t pos2 = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_cell_frequency_link_cell *e = +			(struct dvb_cell_frequency_link_cell*) (buf+pos); + +		if ((pos + sizeof(struct dvb_cell_frequency_link_cell)) > len) +			return NULL; + +		bswap16(buf+pos); +		bswap32(buf+pos+2); + +		pos += sizeof(struct dvb_cell_frequency_link_cell); + +		if ((pos + e->subcell_loop_info_length) > len) +			return NULL; + +		if (e->subcell_loop_info_length % sizeof(struct dvb_cell_frequency_link_cell_subcell)) +			return NULL; + +		pos2 = 0; +		while(pos2 < e->subcell_loop_info_length) { +			bswap32(buf+pos+pos2+1); + +			pos2 += sizeof(struct dvb_cell_frequency_link_cell_subcell); +		} + +		pos += e->subcell_loop_info_length; +	} + +	return (struct dvb_cell_frequency_link_descriptor*) d; +} + +/** + * Iterator for the cells field of a dvb_cell_frequency_link_descriptor. + * + * @param d dvb_cell_frequency_link_descriptor pointer. + * @param pos Variable holding a pointer to the current dvb_cell_frequency_link_cell. + */ +#define dvb_cell_frequency_link_descriptor_cells_for_each(d, pos) \ +	for ((pos) = dvb_cell_frequency_link_descriptor_cells_first(d); \ +	     (pos); \ +	     (pos) = dvb_cell_frequency_link_descriptor_cells_next(d, pos)) + +/** + * Iterator for the subcells field of a dvb_cell_frequency_link_cell. + * + * @param cell dvb_cell_frequency_link_cell pointer. + * @param pos Variable holding a pointer to the current dvb_cell_frequency_link_cell_subcell. + */ +#define dvb_cell_frequency_link_cell_subcells_for_each(cell, pos) \ +	for ((pos) = dvb_cell_frequency_link_cell_subcells_first(cell); \ +	     (pos); \ +	     (pos) = dvb_cell_frequency_link_cell_subcells_next(cell, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_cell_frequency_link_cell* +	dvb_cell_frequency_link_descriptor_cells_first(struct dvb_cell_frequency_link_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_cell_frequency_link_cell *) +		((uint8_t*) d + sizeof(struct dvb_cell_frequency_link_descriptor)); +} + +static inline struct dvb_cell_frequency_link_cell* +	dvb_cell_frequency_link_descriptor_cells_next(struct dvb_cell_frequency_link_descriptor *d, +						      struct dvb_cell_frequency_link_cell *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_cell_frequency_link_cell) + +			pos->subcell_loop_info_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_cell_frequency_link_cell *) next; +} + +static inline struct dvb_cell_frequency_link_cell_subcell* +	dvb_cell_frequency_link_cell_subcells_first(struct dvb_cell_frequency_link_cell *d) +{ +	if (d->subcell_loop_info_length == 0) +		return NULL; + +	return (struct dvb_cell_frequency_link_cell_subcell*) +		((uint8_t*) d + sizeof(struct dvb_cell_frequency_link_cell)); +} + +static inline struct dvb_cell_frequency_link_cell_subcell* +	dvb_cell_frequency_link_cell_subcells_next(struct dvb_cell_frequency_link_cell *cell, +					      struct dvb_cell_frequency_link_cell_subcell *pos) +{ +	uint8_t *end = (uint8_t*) cell + cell->subcell_loop_info_length; +	uint8_t *next = (uint8_t*) pos + +			sizeof(struct dvb_cell_frequency_link_cell_subcell); + +	if (next >= end) +		return NULL; + +	return (struct dvb_cell_frequency_link_cell_subcell *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/cell_list_descriptor.h b/lib/libucsi/dvb/cell_list_descriptor.h new file mode 100644 index 0000000..ddbaf2c --- /dev/null +++ b/lib/libucsi/dvb/cell_list_descriptor.h @@ -0,0 +1,201 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CELL_LIST_DESCRIPTOR +#define _UCSI_DVB_CELL_LIST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_cell_list_descriptor structure. + */ +struct dvb_cell_list_descriptor { +	struct descriptor d; + +	/* struct dvb_cell_list_entry cells[] */ +} __ucsi_packed; + +/** + * An entry in the cells field of a dvb_cell_list_descriptor. + */ +struct dvb_cell_list_entry { +	uint16_t cell_id; +	uint16_t cell_latitude; +	uint16_t cell_longitude; +  EBIT3(uint32_t cell_extend_of_latitude	:12; , +	uint32_t cell_extend_of_longitude	:12; , +	uint32_t subcell_info_loop_length	: 8; ); +	/* struct dvb_subcell_list_entry subcells[] */ +} __ucsi_packed; + +/** + * An entry in the subcells field of a dvb_cell_list_entry. + */ +struct dvb_subcell_list_entry { +	uint8_t cell_id_extension; +	uint16_t subcell_latitude; +	uint16_t subcell_longitude; +  EBIT2(uint32_t subcell_extend_of_latitude	:12; , +	uint32_t subcell_extend_of_longitude	:12; ); +} __ucsi_packed; + +/** + * Process a dvb_cell_list_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_cell_list_descriptor pointer, or NULL on error. + */ +static inline struct dvb_cell_list_descriptor* +	dvb_cell_list_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t pos2 = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_cell_list_entry *e = +			(struct dvb_cell_list_entry*) (buf+pos); + +		if ((pos + sizeof(struct dvb_cell_list_entry)) > len) +			return NULL; + +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		bswap16(buf+pos+4); +		bswap32(buf+pos+6); + +		pos += sizeof(struct dvb_cell_list_entry); + +		if ((pos + e->subcell_info_loop_length) > len) +			return NULL; + +		if (e->subcell_info_loop_length % sizeof(struct dvb_subcell_list_entry)) +			return NULL; + +		pos2 = 0; +		while(pos2 < e->subcell_info_loop_length) { +			bswap16(buf+pos+pos2+1); +			bswap16(buf+pos+pos2+3); +			bswap24(buf+pos+pos2+5); + +			pos2 += sizeof(struct dvb_subcell_list_entry); +		} + +		pos += e->subcell_info_loop_length; +	} + +	return (struct dvb_cell_list_descriptor*) d; +} + +/** + * Iterator for the cells field of a dvb_cell_list_descriptor. + * + * @param d dvb_cell_list_descriptor pointer. + * @param pos Variable holding a pointer to the current dvb_cell_list_entry. + */ +#define dvb_cell_list_descriptor_cells_for_each(d, pos) \ +	for ((pos) = dvb_cell_list_descriptor_cells_first(d); \ +	     (pos); \ +	     (pos) = dvb_cell_list_descriptor_cells_next(d, pos)) + +/** + * Iterator for the subcells field of a dvb_cell_list_entry. + * + * @param cell dvb_cell_list_entry pointer. + * @param pos Variable holding a pointer to the current dvb_subcell_list_entry. + */ +#define dvb_cell_list_entry_subcells_for_each(cell, pos) \ +	for ((pos) = dvb_cell_list_entry_subcells_first(cell); \ +	     (pos); \ +	     (pos) = dvb_cell_list_entry_subcells_next(cell, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_cell_list_entry* +	dvb_cell_list_descriptor_cells_first(struct dvb_cell_list_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_cell_list_entry *) +		((uint8_t*) d + sizeof(struct dvb_cell_list_descriptor)); +} + +static inline struct dvb_cell_list_entry* +	dvb_cell_list_descriptor_cells_next(struct dvb_cell_list_descriptor *d, +					    struct dvb_cell_list_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_cell_list_entry) + +			pos->subcell_info_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_cell_list_entry *) next; +} + +static inline struct dvb_subcell_list_entry* +	dvb_cell_list_entry_subcells_first(struct dvb_cell_list_entry *d) +{ +	if (d->subcell_info_loop_length == 0) +		return NULL; + +	return (struct dvb_subcell_list_entry*) +		((uint8_t*) d + sizeof(struct dvb_cell_list_entry)); +} + +static inline struct dvb_subcell_list_entry* +	dvb_cell_list_entry_subcells_next(struct dvb_cell_list_entry *d, +					  struct dvb_subcell_list_entry *pos) +{ +	uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_subcell_list_entry); +	uint8_t *end = (uint8_t*) d + +			sizeof(struct dvb_cell_list_entry) + +			d->subcell_info_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_subcell_list_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/component_descriptor.h b/lib/libucsi/dvb/component_descriptor.h new file mode 100644 index 0000000..31d38e1 --- /dev/null +++ b/lib/libucsi/dvb/component_descriptor.h @@ -0,0 +1,147 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_COMPONENT_DESCRIPTOR +#define _UCSI_DVB_COMPONENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Possible values for stream_content. + */ +enum { +	DVB_STREAM_CONTENT_VIDEO 		= 0x01, +	DVB_STREAM_CONTENT_AUDIO 		= 0x02, +	DVB_STREAM_CONTENT_SUBTITLE 		= 0x03, +	DVB_STREAM_CONTENT_AC3	 		= 0x04, +}; + +/** + * Possible values for component_type. + */ +enum { +	DVB_COMPONENT_TYPE_VIDEO_43_25Hz		= 0x01, +	DVB_COMPONENT_TYPE_VIDEO_169_PAN_25Hz		= 0x02, +	DVB_COMPONENT_TYPE_VIDEO_169_NOPAN_25Hz		= 0x03, +	DVB_COMPONENT_TYPE_VIDEO_GT169_25Hz		= 0x04, + +	DVB_COMPONENT_TYPE_VIDEO_43_30Hz		= 0x05, +	DVB_COMPONENT_TYPE_VIDEO_169_PAN_30Hz		= 0x06, +	DVB_COMPONENT_TYPE_VIDEO_169_NOPAN_30Hz		= 0x07, +	DVB_COMPONENT_TYPE_VIDEO_GT169_30Hz		= 0x08, + +	DVB_COMPONENT_TYPE_HDVIDEO_43_25Hz		= 0x09, +	DVB_COMPONENT_TYPE_HDVIDEO_169_PAN_25Hz		= 0x0a, +	DVB_COMPONENT_TYPE_HDVIDEO_169_NOPAN_25Hz	= 0x0b, +	DVB_COMPONENT_TYPE_HDVIDEO_GT169_25Hz		= 0x0c, + +	DVB_COMPONENT_TYPE_HDVIDEO_43_30Hz		= 0x0d, +	DVB_COMPONENT_TYPE_HDVIDEO_169_PAN_30Hz		= 0x0e, +	DVB_COMPONENT_TYPE_HDVIDEO_169_NOPAN_30Hz	= 0x0f, +	DVB_COMPONENT_TYPE_HDVIDEO_GT169_30Hz		= 0x10, + +	DVB_COMPONENT_TYPE_AUDIO_SINGLE_MONO		= 0x01, +	DVB_COMPONENT_TYPE_AUDIO_DUAL_MONO		= 0x02, +	DVB_COMPONENT_TYPE_AUDIO_STEREO			= 0x03, +	DVB_COMPONENT_TYPE_AUDIO_MULTI_LINGUAL_MULTI_CHAN= 0x04, +	DVB_COMPONENT_TYPE_AUDIO_SURROUND		= 0x05, +	DVB_COMPONENT_TYPE_AUDIO_VISUAL_IMPAIRED	= 0x40, +	DVB_COMPONENT_TYPE_AUDIO_HARDHEAR		= 0x41, +	DVB_COMPONENT_TYPE_AUDIO_SUPPLEMENTARY		= 0x42, + +	DVB_COMPONENT_TYPE_SUBTITLE_TELETEXT		= 0x01, +	DVB_COMPONENT_TYPE_SUBTITLE_ASSOC_TELETEXT	= 0x02, +	DVB_COMPONENT_TYPE_SUBTITLE_VBI			= 0x03, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB			= 0x10, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_43		= 0x11, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_169		= 0x12, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_2211		= 0x13, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR	= 0x20, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_43	= 0x21, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_169	= 0x22, +	DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_2211	= 0x23, +}; + +/** + * dvb_component_descriptor structure. + */ +struct dvb_component_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved	: 4; , +	uint8_t stream_content	: 4; ); +	uint8_t component_type; +	uint8_t component_tag; +	iso639lang_t language_code; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_component_descriptor. + * + * @param d Pointer to a generic descriptor. + * @return dvb_component_descriptor pointer, or NULL on error. + */ +static inline struct dvb_component_descriptor* +	dvb_component_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_component_descriptor) - 2)) +		return NULL; + +	return (struct dvb_component_descriptor*) d; +} + +/** + * Accessor for the text field of a dvb_component_descriptor. + * + * @param d dvb_component_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_component_descriptor_text(struct dvb_component_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_component_descriptor); +} + +/** + * Determine the length of the text field of a dvb_component_descriptor. + * + * @param d dvb_component_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_component_descriptor_text_length(struct dvb_component_descriptor *d) +{ +	return d->d.len - 6; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/content_descriptor.h b/lib/libucsi/dvb/content_descriptor.h new file mode 100644 index 0000000..d2a63a0 --- /dev/null +++ b/lib/libucsi/dvb/content_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CONTENT_DESCRIPTOR +#define _UCSI_DVB_CONTENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +// FIXME: the nibbles + +/** + * dvb_content_descriptor structure. + */ +struct dvb_content_descriptor { +	struct descriptor d; + +	/* struct dvb_content_nibble nibbles[] */ +} __ucsi_packed; + +/** + * An entry in the nibbles field of a dvb_content_descriptor. + */ +struct dvb_content_nibble { +  EBIT2(uint8_t content_nibble_level_1	: 4; , +	uint8_t content_nibble_level_2	: 4; ); +  EBIT2(uint8_t user_nibble_1		: 4; , +	uint8_t user_nibble_2		: 4; ); +} __ucsi_packed; + +/** + * Process a dvb_content_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_content_descriptor pointer, or NULL on error. + */ +static inline struct dvb_content_descriptor* +	dvb_content_descriptor_codec(struct descriptor* d) +{ +	if (d->len % sizeof(struct dvb_content_nibble)) +		return NULL; + +	return (struct dvb_content_descriptor*) d; +} + +/** + * Iterator for the nibbles field of a dvb_content_descriptor. + * + * @param d dvb_content_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_content_nibble. + */ +#define dvb_content_descriptor_nibbles_for_each(d, pos) \ +	for ((pos) = dvb_content_descriptor_nibbles_first(d); \ +	     (pos); \ +	     (pos) = dvb_content_descriptor_nibbles_next(d, pos)) + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_content_nibble* +	dvb_content_descriptor_nibbles_first(struct dvb_content_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_content_nibble *) +		((uint8_t*) d + sizeof(struct dvb_content_descriptor)); +} + +static inline struct dvb_content_nibble* +	dvb_content_descriptor_nibbles_next(struct dvb_content_descriptor *d, +					    struct dvb_content_nibble *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_content_nibble); + +	if (next >= end) +		return NULL; + +	return (struct dvb_content_nibble *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/content_identifier_descriptor.h b/lib/libucsi/dvb/content_identifier_descriptor.h new file mode 100644 index 0000000..c2cf9ea --- /dev/null +++ b/lib/libucsi/dvb/content_identifier_descriptor.h @@ -0,0 +1,233 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_CONTENT_IDENTIFIER_DESCRIPTOR +#define _UCSI_DVB_CONTENT_IDENTIFIER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + + +/** + * Possible values for the crid_type. + */ +enum { +	DVB_CRID_TYPE_NONE		= 0x00, +	DVB_CRID_TYPE_ITEM		= 0x01, +	DVB_CRID_TYPE_SERIES		= 0x02, +	DVB_CRID_TYPE_RECOMMENDATION	= 0x03, +}; + +/** + * Possible values for the crid_location. + */ +enum { +	DVB_CRID_LOCATION_THIS_DESCRIPTOR	= 0x00, +	DVB_CRID_LOCATION_CIT			= 0x01, +}; + +/** + * dvb_content_identifier_descriptor structure. + */ +struct dvb_content_identifier_descriptor { +	struct descriptor d; + +	/* struct dvb_content_identifier_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_content_identifier_descriptor. + */ +struct dvb_content_identifier_entry { +  EBIT2(uint8_t crid_type		: 6; , +	uint8_t crid_location		: 2; ); +	/* struct dvb_content_identifier_data_00 data0 */ +	/* struct dvb_content_identifier_data_01 data1 */ +} __ucsi_packed; + +/** + * The data if crid_location == 0 + */ +struct dvb_content_identifier_entry_data_0 { +	uint8_t crid_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * The data if crid_location == 1 + */ +struct dvb_content_identifier_entry_data_1 { +	uint16_t crid_ref; +} __ucsi_packed; + + +/** + * Process a dvb_content_identifier_descriptor. + * + * @param d Generic descriptor. + * @return dvb_content_identifier_descriptor pointer, or NULL on error. + */ +static inline struct dvb_content_identifier_descriptor* +	dvb_content_identifier_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len + 2; +	uint32_t pos = 2; +	uint8_t *buf = (uint8_t*) d; + +	while(pos < len) { +		struct dvb_content_identifier_entry *e = +			(struct dvb_content_identifier_entry*) (buf + pos); + +		if (len < (pos+1)) +			return NULL; +		pos++; + +		switch(e->crid_location) { +		case 0: +			if (len < (pos + 1)) +				return NULL; +			if (len < (pos + 1 + buf[pos])) +				return NULL; +			pos += 1 + buf[pos]; +			break; + +		case 1: +			if (len < (pos+2)) +				return NULL; +			bswap16(buf+pos); +			break; +		} +	} + +	if (pos != len) +		return NULL; + +	return (struct dvb_content_identifier_descriptor*) d; +} + +/** + * Iterator for entries field of a dvb_content_identifier_descriptor. + * + * @param d dvb_content_identifier_descriptor pointer. + * @param pos Variable holding a pointer to the current dvb_content_identifier_entry. + */ +#define dvb_content_identifier_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_content_identifier_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_content_identifier_descriptor_entries_next(d, pos)) + +/** + * Accessor for the data0 field of a dvb_content_identifier_entry. + * + * @param d dvb_content_identifier_entry pointer. + * @return Pointer, or NULL on error. + */ +static inline struct dvb_content_identifier_entry_data_0* +	dvb_content_identifier_entry_data_0(struct dvb_content_identifier_entry *d) +{ +	if (d->crid_location != 0) +		return NULL; +	return (struct dvb_content_identifier_entry_data_0*) +		((uint8_t*) d + sizeof(struct dvb_content_identifier_entry)); +} +/** + * Accessor for the data field of a dvb_content_identifier_entry_data_0. + * + * @param d dvb_content_identifier_entry_data_0 pointer. + * @return Pointer, or NULL on error. + */ +static inline uint8_t* +	dvb_content_identifier_entry_data_0_data(struct dvb_content_identifier_entry_data_0 *d) +{ +	return ((uint8_t*) d + sizeof(struct dvb_content_identifier_entry_data_0)); +} + +/** + * Accessor for the data1 field of a dvb_content_identifier_entry. + * + * @param d dvb_content_identifier_entry pointer. + * @return Pointer, or NULL on error. + */ +static inline struct dvb_content_identifier_entry_data_1* +	dvb_content_identifier_entry_data_1(struct dvb_content_identifier_entry *d) +{ +	if (d->crid_location != 1) +		return NULL; +	return (struct dvb_content_identifier_entry_data_1*) +		((uint8_t*) d + sizeof(struct dvb_content_identifier_entry)); +} + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_content_identifier_entry* +	dvb_content_identifier_descriptor_entries_first(struct dvb_content_identifier_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_content_identifier_entry *) +		((uint8_t*) d + sizeof(struct dvb_content_identifier_descriptor)); +} + +static inline struct dvb_content_identifier_entry* +	dvb_content_identifier_descriptor_entries_next(struct dvb_content_identifier_descriptor *d, +					     struct dvb_content_identifier_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_content_identifier_entry); + +	if (next >= end) +		return NULL; + +	switch(pos->crid_location) { +	case 0: +		if ((next+2) >= end) +			return NULL; +		if ((next+2+next[1]) >= end) +			return NULL; +		break; + +	case 1: +		if ((next+3) >= end) +			return NULL; +		break; +	} + +	return (struct dvb_content_identifier_entry*) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/country_availability_descriptor.h b/lib/libucsi/dvb/country_availability_descriptor.h new file mode 100644 index 0000000..65b1661 --- /dev/null +++ b/lib/libucsi/dvb/country_availability_descriptor.h @@ -0,0 +1,120 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR +#define _UCSI_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_country_availability_descriptor structure. + */ +struct dvb_country_availability_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t country_availability_flag	: 1; , +	uint8_t reserved			: 7; ); +	/* struct dvb_country_availability_entry countries[] */ +} __ucsi_packed; + +/** + * An entry in the countries field of a dvb_country_availability_descriptor. + */ +struct dvb_country_availability_entry { +	iso639country_t country_code; +} __ucsi_packed; + +/** + * Process a dvb_country_availability_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_country_availability_descriptor pointer, or NULL on error. + */ +static inline struct dvb_country_availability_descriptor* +	dvb_country_availability_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; + +	if (len < (sizeof(struct dvb_country_availability_descriptor) - 2)) +		return NULL; + +	if ((len - 1) % sizeof(struct dvb_country_availability_entry)) +		return NULL; + +	return (struct dvb_country_availability_descriptor*) d; +} + +/** + * Iterator for the countries field of a dvb_country_availability_descriptor. + * + * @param d dvb_country_availability_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_country_availability_entry. + */ +#define dvb_country_availability_descriptor_countries_for_each(d, pos) \ +	for ((pos) = dvb_country_availability_descriptor_countries_first(d); \ +	     (pos); \ +	     (pos) = dvb_country_availability_descriptor_countries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_country_availability_entry* +	dvb_country_availability_descriptor_countries_first(struct dvb_country_availability_descriptor *d) +{ +	if (d->d.len == 1) +		return NULL; + +	return (struct dvb_country_availability_entry *) +		((uint8_t*) d + sizeof(struct dvb_country_availability_descriptor)); +} + +static inline struct dvb_country_availability_entry* +	dvb_country_availability_descriptor_countries_next(struct dvb_country_availability_descriptor *d, +							   struct dvb_country_availability_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_country_availability_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_country_availability_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/data_broadcast_descriptor.h b/lib/libucsi/dvb/data_broadcast_descriptor.h new file mode 100644 index 0000000..069e1db --- /dev/null +++ b/lib/libucsi/dvb/data_broadcast_descriptor.h @@ -0,0 +1,139 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DATA_BROADCAST_DESCRIPTOR +#define _UCSI_DVB_DATA_BROADCAST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_data_broadcast_descriptor structure. + */ +struct dvb_data_broadcast_descriptor { +	struct descriptor d; + +	uint16_t data_broadcast_id; +	uint8_t component_tag; +	uint8_t selector_length; +	/* uint8_t selector[] */ +	/* struct dvb_data_broadcast_descriptor_part2 part2 */ +} __ucsi_packed; + +/** + * Second part of a dvb_data_broadcast_descriptor following the variable length selector field. + */ +struct dvb_data_broadcast_descriptor_part2 { +	iso639lang_t language_code; +	uint8_t text_length; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_data_broadcast_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_data_broadcast_descriptor pointer, or NULL on error. + */ +static inline struct dvb_data_broadcast_descriptor* +	dvb_data_broadcast_descriptor_codec(struct descriptor* d) +{ +	struct dvb_data_broadcast_descriptor *p = +		(struct dvb_data_broadcast_descriptor *) d; +	struct dvb_data_broadcast_descriptor_part2 *p2; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = sizeof(struct dvb_data_broadcast_descriptor) - 2; +	uint32_t len = d->len; + +	if (pos > len) +		return NULL; + +	bswap16(buf + 2); + +	pos += p->selector_length; + +	if (pos > len) +		return NULL; + +	p2 = (struct dvb_data_broadcast_descriptor_part2*) (buf + 2 + pos); + +	pos += sizeof(struct dvb_data_broadcast_descriptor_part2); + +	if (pos > len) +		return NULL; + +	pos += p2->text_length; + +	if (pos != len) +		return NULL; + +	return p; +} + +/** + * Accessor for the selector field of a dvb_data_broadcast_descriptor. + * + * @param d dvb_data_broadcast_descriptor pointer. + * @return pointer to the field. + */ +static inline uint8_t * +	dvb_data_broadcast_descriptor_selector(struct dvb_data_broadcast_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_data_broadcast_descriptor); +} + +/** + * Accessor for the second part of a dvb_data_broadcast_descriptor. + * + * @param d dvb_data_broadcast_descriptor pointer. + * @return dvb_data_broadcast_descriptor_part2 pointer. + */ +static inline struct dvb_data_broadcast_descriptor_part2 * +	dvb_data_broadcast_descriptor_part2(struct dvb_data_broadcast_descriptor *d) +{ +	return (struct dvb_data_broadcast_descriptor_part2*) +		((uint8_t*) d + sizeof(struct dvb_data_broadcast_descriptor) + +		 d->selector_length); +} + +/** + * Accessor for the text field in a dvb_data_broadcast_descriptor_part2. + * + * @param d dvb_data_broadcast_descriptor_part2 pointer. + * @return pointer to the field. + */ +static inline uint8_t * +	dvb_data_broadcast_descriptor_part2_text(struct dvb_data_broadcast_descriptor_part2 *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_data_broadcast_descriptor_part2); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/data_broadcast_id_descriptor.h b/lib/libucsi/dvb/data_broadcast_id_descriptor.h new file mode 100644 index 0000000..446927c --- /dev/null +++ b/lib/libucsi/dvb/data_broadcast_id_descriptor.h @@ -0,0 +1,221 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR +#define _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for data_broadcast_id. + */ +enum { +	DVB_BROADCAST_ID_DATA_PIPE			= 0X0001, +	DVB_BROADCAST_ID_ASYNCHRONOUS_DATA_STREAM	= 0X0002, +	DVB_BROADCAST_ID_SYNCHRONOUS_DATA_STREAM	= 0X0003, +	DVB_BROADCAST_ID_SYNCHRONISED_DATA_STREAM	= 0X0004, +	DVB_BROADCAST_ID_MULTI_PROTOCOL_ENCAPSULATION	= 0X0005, +	DVB_BROADCAST_ID_DATA_CAROUSEL			= 0X0006, +	DVB_BROADCAST_ID_OBJECT_CAROUSEL		= 0X0007, +	DVB_BROADCAST_ID_DVB_ATM_STREAMS		= 0X0008, +	DVB_BROADCAST_ID_HIGHER_PROTOCOLS		= 0X0009, +	DVB_BROADCAST_ID_SOFTWARE_UPDATE		= 0x000A, +	DVB_BROADCAST_ID_IP_MAC_NOTIFICATION_TABLE	= 0x000B, +}; + +/** + * dvb_data_broadcast_id_descriptor structure. + */ +struct dvb_data_broadcast_id_descriptor { +	struct descriptor d; + +	uint16_t data_broadcast_id; +	/* uint8_t id_selector_byte[] */ +} __ucsi_packed; + +/** + * id_selector_byte for 0x000b data_broadcast_id (IP/MAC Notification Table). + */ +struct dvb_id_selector_byte_000b { +	uint8_t platform_id_data_length; +	/* struct dvb_ip_mac_notification_info infos[] */ +	/* uint8_t private_data[] */ +} __ucsi_packed; + +/** + * Entries in the infos field of a dvb_id_selector_byte_0b. + */ +struct dvb_ip_mac_notification_info { +  EBIT2(uint32_t platform_id		: 24; , +	uint8_t action_type		: 8;  ); +  EBIT3(uint8_t reserved		: 2;  , +	uint8_t INT_versioning_flag	: 1;  , +	uint8_t INT_version		: 5;  ); +} __ucsi_packed; + +/** + * Process a dvb_data_broadcast_id_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_data_broadcast_id_descriptor pointer, or NULL on error. + */ +static inline struct dvb_data_broadcast_id_descriptor* +	dvb_data_broadcast_id_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_data_broadcast_id_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); + +	return (struct dvb_data_broadcast_id_descriptor*) d; +} + +/** + * Accessor for the selector_byte field of a dvb_data_broadcast_id_descriptor. + * + * @param d dvb_data_broadcast_id_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_data_broadcast_id_descriptor_id_selector_byte(struct dvb_data_broadcast_id_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_data_broadcast_id_descriptor); +} + +/** + * Determine the length of the selector_byte field of a dvb_data_broadcast_id_descriptor. + * + * @param d dvb_data_broadcast_id_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_data_broadcast_id_descriptor_id_selector_byte_length(struct dvb_data_broadcast_id_descriptor *d) +{ +	return d->d.len - 2; +} + +/** + * Accessor for a dvb_id_selector_byte_000b pointer. + * + * @param d dvb_data_broadcast_id_descriptor pointer. + * @return Pointer to the data field. + */ +static inline struct dvb_id_selector_byte_000b * +	dvb_id_selector_byte_000b(struct dvb_data_broadcast_id_descriptor *d) +{ +	if (d->data_broadcast_id != DVB_BROADCAST_ID_IP_MAC_NOTIFICATION_TABLE) +		return NULL; +	return (struct dvb_id_selector_byte_000b *) dvb_data_broadcast_id_descriptor_id_selector_byte(d); +} + +/** + * Iterator for the dvb_ip_mac_notification_info field of a dvb_id_selector_byte_000b. + * + * @param id_selector_byte dvb_id_selector_byte_000b pointer. + * @param pos Variable containing a pointer to the current dvb_ip_mac_notification_info. + */ +#define dvb_id_selector_byte_000b_ip_mac_notification_info_for_each(id_selector_byte, pos) \ +	for ((pos) = dvb_ip_mac_notification_info_first(id_selector_byte); \ +	     (pos); \ +	     (pos) = dvb_ip_mac_notification_info_next(id_selector_byte, pos)) + +/** + * Length of the private_data field of a dvb_id_selector_byte_000b. + * + * @param d descriptor pointer. + * @param i dvb_id_selector_byte_000b pointer. + * @return Length of the field. + */ +static inline uint8_t +	dvb_id_selector_byte_000b_private_data_length(struct descriptor *d, +			    struct dvb_id_selector_byte_000b *i) +{ +	return (uint8_t) (d->len - +	     sizeof(struct descriptor) - +	     i->platform_id_data_length - +	     sizeof(struct dvb_id_selector_byte_000b)); +} + +/** + * Accessor for the private_data field of a dvb_id_selector_byte_000b. + * + * @param d descriptor pointer. + * @param i dvb_id_selector_byte_000b pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_id_selector_byte_000b_private_data(struct descriptor *d, +			    struct dvb_id_selector_byte_000b *i) +{ +	if (dvb_id_selector_byte_000b_private_data_length(d, i) <= 0) +		return NULL; + +	return (uint8_t *) i + i->platform_id_data_length + sizeof(struct dvb_id_selector_byte_000b); +} + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ip_mac_notification_info * +	dvb_ip_mac_notification_info_first(struct dvb_id_selector_byte_000b *d) +{ +	if (d->platform_id_data_length == 0) +		return NULL; + +	bswap32((uint8_t *) d + sizeof(struct dvb_id_selector_byte_000b)); + +	return (struct dvb_ip_mac_notification_info *) ((uint8_t *) d + sizeof(struct dvb_id_selector_byte_000b)); +} + +static inline struct dvb_ip_mac_notification_info * +	dvb_ip_mac_notification_info_next(struct dvb_id_selector_byte_000b *d, +				    struct dvb_ip_mac_notification_info *pos) +{ +	uint8_t *end = (uint8_t *) d + d->platform_id_data_length; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_id_selector_byte_000b) + +			sizeof(struct dvb_ip_mac_notification_info); + +	if (next >= end) +		return NULL; + +	bswap32(next); + +	return (struct dvb_ip_mac_notification_info *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif + +#include <libucsi/dvb/mhp_data_broadcast_id_descriptor.h> diff --git a/lib/libucsi/dvb/default_authority_descriptor.h b/lib/libucsi/dvb/default_authority_descriptor.h new file mode 100644 index 0000000..0b0ba73 --- /dev/null +++ b/lib/libucsi/dvb/default_authority_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DEFAULT_AUTHORITY_DESCRIPTOR +#define _UCSI_DVB_DEFAULT_AUTHORITY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_default_authority_descriptor structure. + */ +struct dvb_default_authority_descriptor { +	struct descriptor d; + +	/* char name[] */ +} __ucsi_packed; + +/** + * Process a dvb_default_authority_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_default_authority_descriptor pointer, or NULL on error. + */ +static inline struct dvb_default_authority_descriptor* +	dvb_default_authority_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_default_authority_descriptor*) d; +} + +/** + * Accessor for the name field in a dvb_default_authority_descriptor. + * + * @param d dvb_default_authority_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_default_authority_descriptor_name(struct dvb_default_authority_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_default_authority_descriptor); +} + +/** + * Calculate the length of the name field in a dvb_default_authority_descriptor. + * + * @param d dvb_default_authority_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_default_authority_descriptor_name_length(struct dvb_default_authority_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/descriptor.h b/lib/libucsi/dvb/descriptor.h new file mode 100644 index 0000000..303e17a --- /dev/null +++ b/lib/libucsi/dvb/descriptor.h @@ -0,0 +1,229 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DESCRIPTOR_H +#define _UCSI_DVB_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/dvb/ac3_descriptor.h> +#include <libucsi/dvb/adaptation_field_data_descriptor.h> +#include <libucsi/dvb/ancillary_data_descriptor.h> +#include <libucsi/dvb/announcement_support_descriptor.h> +#include <libucsi/dvb/application_signalling_descriptor.h> +#include <libucsi/dvb/bouquet_name_descriptor.h> +#include <libucsi/dvb/ca_identifier_descriptor.h> +#include <libucsi/dvb/cable_delivery_descriptor.h> +#include <libucsi/dvb/cell_frequency_link_descriptor.h> +#include <libucsi/dvb/cell_list_descriptor.h> +#include <libucsi/dvb/component_descriptor.h> +#include <libucsi/dvb/content_descriptor.h> +#include <libucsi/dvb/content_identifier_descriptor.h> +#include <libucsi/dvb/country_availability_descriptor.h> +#include <libucsi/dvb/data_broadcast_descriptor.h> +#include <libucsi/dvb/data_broadcast_id_descriptor.h> +#include <libucsi/dvb/default_authority_descriptor.h> +#include <libucsi/dvb/dsng_descriptor.h> +#include <libucsi/dvb/extended_event_descriptor.h> +#include <libucsi/dvb/frequency_list_descriptor.h> +#include <libucsi/dvb/ip_mac_platform_name_descriptor.h> +#include <libucsi/dvb/ip_mac_platform_provider_name_descriptor.h> +#include <libucsi/dvb/ip_mac_stream_location_descriptor.h> +#include <libucsi/dvb/linkage_descriptor.h> +#include <libucsi/dvb/local_time_offset_descriptor.h> +#include <libucsi/dvb/mosaic_descriptor.h> +#include <libucsi/dvb/multilingual_bouquet_name_descriptor.h> +#include <libucsi/dvb/multilingual_component_descriptor.h> +#include <libucsi/dvb/multilingual_network_name_descriptor.h> +#include <libucsi/dvb/multilingual_service_name_descriptor.h> +#include <libucsi/dvb/network_name_descriptor.h> +#include <libucsi/dvb/nvod_reference_descriptor.h> +#include <libucsi/dvb/parental_rating_descriptor.h> +#include <libucsi/dvb/partial_transport_stream_descriptor.h> +#include <libucsi/dvb/pdc_descriptor.h> +#include <libucsi/dvb/private_data_specifier_descriptor.h> +#include <libucsi/dvb/related_content_descriptor.h> +#include <libucsi/dvb/satellite_delivery_descriptor.h> +#include <libucsi/dvb/s2_satellite_delivery_descriptor.h> +#include <libucsi/dvb/scrambling_descriptor.h> +#include <libucsi/dvb/service_availability_descriptor.h> +#include <libucsi/dvb/service_descriptor.h> +#include <libucsi/dvb/service_identifier_descriptor.h> +#include <libucsi/dvb/service_list_descriptor.h> +#include <libucsi/dvb/service_move_descriptor.h> +#include <libucsi/dvb/short_event_descriptor.h> +#include <libucsi/dvb/short_smoothing_buffer_descriptor.h> +#include <libucsi/dvb/stream_identifier_descriptor.h> +#include <libucsi/dvb/stuffing_descriptor.h> +#include <libucsi/dvb/subtitling_descriptor.h> +#include <libucsi/dvb/target_ip_address_descriptor.h> +#include <libucsi/dvb/target_ipv6_address_descriptor.h> +#include <libucsi/dvb/target_ip_slash_descriptor.h> +#include <libucsi/dvb/target_ip_source_slash_descriptor.h> +#include <libucsi/dvb/target_ipv6_slash_descriptor.h> +#include <libucsi/dvb/target_ipv6_source_slash_descriptor.h> +#include <libucsi/dvb/telephone_descriptor.h> +#include <libucsi/dvb/teletext_descriptor.h> +#include <libucsi/dvb/terrestrial_delivery_descriptor.h> +#include <libucsi/dvb/time_shifted_event_descriptor.h> +#include <libucsi/dvb/time_shifted_service_descriptor.h> +#include <libucsi/dvb/transport_stream_descriptor.h> +#include <libucsi/dvb/tva_id_descriptor.h> +#include <libucsi/dvb/vbi_data_descriptor.h> +#include <libucsi/dvb/vbi_teletext_descriptor.h> +#include <libucsi/endianops.h> + +/** + * The following are disabled because support is incomplete just now. + */ +/* +#include <libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h> +#include <libucsi/dvb/rnt_rar_over_ip_descriptor.h> +#include <libucsi/dvb/rnt_rnt_scan_descriptor.h> +#include <libucsi/dvb/ait_application_descriptor.h> +#include <libucsi/dvb/ait_application_name_descriptor.h> +#include <libucsi/dvb/ait_external_application_authorisation_descriptor.h> +#include <libucsi/dvb/ait_application_icons_descriptor.h> +*/ + +/** + * The following are not implemented just now + */ +/* +#include <libucsi/dvb/ait_transport_protocol_descriptor.h> +#include <libucsi/dvb/ait_dvb_j_application_descriptor.h> +#include <libucsi/dvb/ait_dvb_j_application_location_descriptor.h> +#include <libucsi/dvb/ait_dvb_html_application_descriptor.h> +#include <libucsi/dvb/ait_dvb_html_application_location_descriptor.h> +#include <libucsi/dvb/ait_dvb_html_application_boundary_descriptor.h> +#include <libucsi/dvb/ait_prefetch_descriptor.h> +#include <libucsi/dvb/ait_dii_location_descriptor.h> +#include <libucsi/dvb/ait_ip_signalling_descriptor.h> +*/ + +/** + * Enumeration of DVB descriptor tags. + */ +enum dvb_descriptor_tag { +	dtag_dvb_network_name			= 0x40, +	dtag_dvb_service_list			= 0x41, +	dtag_dvb_stuffing			= 0x42, +	dtag_dvb_satellite_delivery_system	= 0x43, +	dtag_dvb_cable_delivery_system		= 0x44, +	dtag_dvb_vbi_data			= 0x45, +	dtag_dvb_vbi_teletext			= 0x46, +	dtag_dvb_bouquet_name			= 0x47, +	dtag_dvb_service			= 0x48, +	dtag_dvb_country_availability		= 0x49, +	dtag_dvb_linkage			= 0x4a, +	dtag_dvb_nvod_reference			= 0x4b, +	dtag_dvb_time_shifted_service		= 0x4c, +	dtag_dvb_short_event			= 0x4d, +	dtag_dvb_extended_event			= 0x4e, +	dtag_dvb_time_shifted_event		= 0x4f, +	dtag_dvb_component			= 0x50, +	dtag_dvb_mosaic				= 0x51, +	dtag_dvb_stream_identifier		= 0x52, +	dtag_dvb_ca_identifier			= 0x53, +	dtag_dvb_content			= 0x54, +	dtag_dvb_parental_rating		= 0x55, +	dtag_dvb_teletext			= 0x56, +	dtag_dvb_telephone			= 0x57, +	dtag_dvb_local_time_offset		= 0x58, +	dtag_dvb_subtitling			= 0x59, +	dtag_dvb_terrestial_delivery_system	= 0x5a, +	dtag_dvb_multilingual_network_name	= 0x5b, +	dtag_dvb_multilingual_bouquet_name	= 0x5c, +	dtag_dvb_multilingual_service_name	= 0x5d, +	dtag_dvb_multilingual_component		= 0x5e, +	dtag_dvb_private_data_specifier		= 0x5f, +	dtag_dvb_service_move			= 0x60, +	dtag_dvb_short_smoothing_buffer		= 0x61, +	dtag_dvb_frequency_list			= 0x62, +	dtag_dvb_partial_transport_stream	= 0x63, +	dtag_dvb_data_broadcast			= 0x64, +	dtag_dvb_scrambling			= 0x65, +	dtag_dvb_data_broadcast_id		= 0x66, +	dtag_dvb_transport_stream		= 0x67, +	dtag_dvb_dsng				= 0x68, +	dtag_dvb_pdc				= 0x69, +	dtag_dvb_ac3				= 0x6a, +	dtag_dvb_ancillary_data			= 0x6b, +	dtag_dvb_cell_list			= 0x6c, +	dtag_dvb_cell_frequency_link		= 0x6d, +	dtag_dvb_announcement_support		= 0x6e, +	dtag_dvb_application_signalling		= 0x6f, +	dtag_dvb_adaptation_field_data		= 0x70, +	dtag_dvb_service_identifier		= 0x71, +	dtag_dvb_service_availability		= 0x72, +	dtag_dvb_default_authority		= 0x73, +	dtag_dvb_related_content		= 0x74, +	dtag_dvb_tva_id				= 0x75, +	dtag_dvb_content_identifier		= 0x76, +	dtag_dvb_time_slice_fec_identifier	= 0x77, +	dtag_dvb_ecm_repetition_rate		= 0x78, +	dtag_dvb_s2_satellite_delivery_descriptor= 0x79, +	dtag_dvb_enhanced_ac3_descriptor	= 0x7a, +	dtag_dvb_dts_descriptor			= 0x7b, +	dtag_dvb_aac_descriptor			= 0x7c, +	dtag_dvb_extension_descriptor		= 0x7f, + +	/* descriptors which may only appear in an RNT */ +	dtag_dvb_rnt_rar_over_dvb_stream	= 0x40, +	dtag_dvb_rnt_rar_over_ip		= 0x41, +	dtag_dvb_rnt_rnt_scan			= 0x42, + +	/* descriptors which may only appear in an AIT */ +	dtag_dvb_ait_application		= 0x00, +	dtag_dvb_ait_application_name		= 0x01, +	dtag_dvb_ait_transport_protocol		= 0x02, +	dtag_dvb_ait_dvb_j_application		= 0x03, +	dtag_dvb_ait_dvb_j_application_location	= 0x04, +	dtag_dvb_ait_external_application_authorisation	= 0x05, +	dtag_dvb_ait_dvb_html_application	= 0x08, +	dtag_dvb_ait_dvb_html_application_location = 0x09, +	dtab_dvb_ait_dvb_html_application_boundary = 0x0a, +	dtag_dvb_ait_application_icons		= 0x0b, +	dtag_dvb_ait_prefetch			= 0x0c, +	dtag_dvb_ait_dii_location		= 0x0d, +	dtag_dvb_ait_ip_signalling		= 0x11, + +	/* descriptors which may only appear in INT */ +	dtag_dvb_target_ip_address		= 0x09, +	dtag_dvb_target_ipv6_address		= 0x0a, +	dtag_dvb_ip_mac_platform_name		= 0x0c, +	dtag_dvb_ip_mac_platform_provider_name	= 0x0d, +	dtag_dvb_target_ip_slash		= 0x0f, +	dtag_dvb_target_ip_source_slash		= 0x10, +	dtag_dvb_target_ipv6_slash		= 0x11, +	dtag_dvb_target_ipv6_source_slash	= 0x12, +	dtag_dvb_ip_mac_stream_location		= 0x13, + +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/dit_section.c b/lib/libucsi/dvb/dit_section.c new file mode 100644 index 0000000..4f69d4e --- /dev/null +++ b/lib/libucsi/dvb/dit_section.c @@ -0,0 +1,32 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/dit_section.h> + +struct dvb_dit_section * dvb_dit_section_codec(struct section * section) +{ +	struct dvb_dit_section * ret = (struct dvb_dit_section *)section; + +	if (section->length < 1) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/dit_section.h b/lib/libucsi/dvb/dit_section.h new file mode 100644 index 0000000..69fce4f --- /dev/null +++ b/lib/libucsi/dvb/dit_section.h @@ -0,0 +1,54 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DIT_SECTION_H +#define _UCSI_DVB_DIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_dit_section structure. + */ +struct dvb_dit_section { +	struct section head; + +  EBIT2(uint8_t transition_flag : 1; , +	uint8_t reserved 	: 7; ); +}; + +/** + * Process a dvb_dit_section. + * + * @param section Pointer to a generic section header. + * @return Pointer to a dvb_dit_section, or NULL on error. + */ +struct dvb_dit_section * dvb_dit_section_codec(struct section *section); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/dsng_descriptor.h b/lib/libucsi/dvb/dsng_descriptor.h new file mode 100644 index 0000000..6fd369b --- /dev/null +++ b/lib/libucsi/dvb/dsng_descriptor.h @@ -0,0 +1,80 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_DSNG_DESCRIPTOR +#define _UCSI_DVB_DSNG_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_dsng_descriptor structure. + */ +struct dvb_dsng_descriptor { +	struct descriptor d; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process a dvb_dsng_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to a dvb_dsng_descriptor, or NULL on error. + */ +static inline struct dvb_dsng_descriptor* +	dvb_dsng_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_dsng_descriptor*) d; +} + +/** + * Accessor for the data field in a dvb_dsng_descriptor. + * + * @param d dvb_dsng_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t *dvb_dsng_descriptor_data(struct dvb_dsng_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_dsng_descriptor); +} + +/** + * Determine the length of the data field in a dvb_dsng_descriptor. + * + * @param d dvb_dsng_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int dvb_dsng_descriptor_data_length(struct dvb_dsng_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/eit_section.c b/lib/libucsi/dvb/eit_section.c new file mode 100644 index 0000000..97b0261 --- /dev/null +++ b/lib/libucsi/dvb/eit_section.c @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/eit_section.h> + +struct dvb_eit_section *dvb_eit_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct dvb_eit_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; +	bswap16(buf + pos); +	pos += 4; + +	while (pos < len) { +		struct dvb_eit_event * event = +			(struct dvb_eit_event *) (buf + pos); + +		if ((pos + sizeof(struct dvb_eit_event)) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 10); + +		pos += sizeof(struct dvb_eit_event); + +		if ((pos + event->descriptors_loop_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, event->descriptors_loop_length)) +			return NULL; + +		pos += event->descriptors_loop_length; +	} + +	if (pos != len) +		return NULL; + +	return (struct dvb_eit_section *) ext; +} diff --git a/lib/libucsi/dvb/eit_section.h b/lib/libucsi/dvb/eit_section.h new file mode 100644 index 0000000..a2f3e4f --- /dev/null +++ b/lib/libucsi/dvb/eit_section.h @@ -0,0 +1,160 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_EIT_SECTION_H +#define _UCSI_DVB_EIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> +#include <libucsi/dvb/types.h> + + +/** + * dvb_eit_section structure. + */ +struct dvb_eit_section { +	struct section_ext head; + +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint8_t segment_last_section_number; +	uint8_t last_table_id; +	/* struct eit_event events[] */ +} __ucsi_packed; + +/** + * An entry in the events field of a dvb_eit_section. + */ +struct dvb_eit_event { +	uint16_t event_id; +	dvbdate_t start_time; +	dvbduration_t duration; +  EBIT3(uint16_t running_status		: 3;  , +	uint16_t free_ca_mode		: 1;  , +	uint16_t descriptors_loop_length:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a dvb_eit_section. + * + * @param section Pointer to a generic section_ext structure. + * @return Pointer to a dvb_eit_section, or NULL on error. + */ +struct dvb_eit_section *dvb_eit_section_codec(struct section_ext *section); + +/** + * Accessor for the service_id field of an EIT. + * + * @param eit EIT pointer. + * @return The service_id. + */ +static inline uint16_t dvb_eit_section_service_id(struct dvb_eit_section *eit) +{ +	return eit->head.table_id_ext; +} + +/** + * Iterator for the events field of a dvb_eit_section. + * + * @param eit dvb_eit_section pointer. + * @param pos Variable containing a pointer to the current dvb_eit_event. + */ +#define dvb_eit_section_events_for_each(eit, pos) \ +	for ((pos) = dvb_eit_section_events_first(eit); \ +	     (pos); \ +	     (pos) = dvb_eit_section_events_next(eit, pos)) + +/** + * Iterator for the descriptors field of a dvb_eit_event. + * + * @param eit dvb_eit_event pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define dvb_eit_event_descriptors_for_each(event, pos) \ +	for ((pos) = dvb_eit_event_descriptors_first(event); \ +	     (pos); \ +	     (pos) = dvb_eit_event_descriptors_next(event, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_eit_event * +	dvb_eit_section_events_first(struct dvb_eit_section *eit) +{ +	size_t pos = sizeof(struct dvb_eit_section); + +	if (pos >= section_ext_length(&eit->head)) +		return NULL; + +        return (struct dvb_eit_event*) ((uint8_t *) eit + pos); +} + +static inline struct dvb_eit_event * +	dvb_eit_section_events_next(struct dvb_eit_section *eit, +				    struct dvb_eit_event *pos) +{ +	uint8_t *end = (uint8_t*) eit + section_ext_length(&eit->head); +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_eit_event) + +			pos->descriptors_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_eit_event *) next; +} + +static inline struct descriptor * +	dvb_eit_event_descriptors_first(struct dvb_eit_event * t) +{ +	if (t->descriptors_loop_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) t + sizeof(struct dvb_eit_event)); +} + +static inline struct descriptor * +	dvb_eit_event_descriptors_next(struct dvb_eit_event * t, +				       struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) t + sizeof(struct dvb_eit_event), +			       t->descriptors_loop_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/extended_event_descriptor.h b/lib/libucsi/dvb/extended_event_descriptor.h new file mode 100644 index 0000000..bba04b0 --- /dev/null +++ b/lib/libucsi/dvb/extended_event_descriptor.h @@ -0,0 +1,232 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_EXTENDED_EVENT_DESCRIPTOR +#define _UCSI_DVB_EXTENDED_EVENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_extended_event_descriptor structure. + */ +struct dvb_extended_event_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t descriptor_number	: 4; , +	uint8_t last_descriptor_number	: 4; ); +	iso639lang_t language_code; +	uint8_t length_of_items; +	/* struct dvb_extended_event_item items[] */ +	/* struct dvb_extended_event_descriptor_part2 part2 */ +} __ucsi_packed; + +/** + * An entry in the items field of a dvb_extended_event_descriptor. + */ +struct dvb_extended_event_item { +	uint8_t item_description_length; +	/* uint8_t item_description[] */ +	/* struct dvb_extended_event_item_part2 part2 */ +} __ucsi_packed; + +/** + * The second part of a dvb_extended_event_item, following the variable length + * description field. + */ +struct dvb_extended_event_item_part2 { +	uint8_t item_length; +	/* uint8_t item[] */ +} __ucsi_packed; + +/** + * The second part of a dvb_extended_event_descriptor, following the variable + * length items field. + */ +struct dvb_extended_event_descriptor_part2 { +	uint8_t text_length; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_extended_event_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_extended_event_descriptor pointer, or NULL on error. + */ +static inline struct dvb_extended_event_descriptor* +	dvb_extended_event_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; +	struct dvb_extended_event_descriptor * p = +		(struct dvb_extended_event_descriptor *) d; +	struct dvb_extended_event_descriptor_part2 *p2; + +	pos += sizeof(struct dvb_extended_event_descriptor) - 2; + +	if (pos > len) +		return NULL; + +	pos += p->length_of_items; + +	if (pos > len) +		return NULL; + +	p2 = (struct dvb_extended_event_descriptor_part2*) (buf+pos); + +	pos += sizeof(struct dvb_extended_event_descriptor_part2); + +	if (pos > len) +		return NULL; + +	pos += p2->text_length; + +	if (pos != len) +		return NULL; + +	return p; +} + +/** + * Iterator for the items field of a dvb_extended_event_descriptor. + * + * @param d dvb_extended_event_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_extended_event_item. + */ +#define dvb_extended_event_descriptor_items_for_each(d, pos) \ +	for ((pos) = dvb_extended_event_descriptor_items_first(d); \ +	     (pos); \ +	     (pos) = dvb_extended_event_descriptor_items_next(d, pos)) + +/** + * Accessor for the description field of a dvb_extended_event_item. + * + * @param d dvb_extended_event_item pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_extended_event_item_description(struct dvb_extended_event_item *d) +{ +	return (uint8_t*) d + sizeof(struct dvb_extended_event_item); +} + +/** + * Accessor for the second part of a dvb_extended_event_item. + * + * @param dvb_extended_event_item pointer. + * @return dvb_extended_event_item_part2 pointer. + */ +static inline struct dvb_extended_event_item_part2* +	dvb_extended_event_item_part2(struct dvb_extended_event_item *d) +{ +	return (struct dvb_extended_event_item_part2*) +		((uint8_t*) d + sizeof(struct dvb_extended_event_item) + +		 d->item_description_length); +} + +/** + * Accessor for the item field of a dvb_extended_event_item_part2. + * + * @param d dvb_extended_event_item_part2 pointer. + * @return Pointer to the item field. + */ +static inline uint8_t* +	dvb_extended_event_item_part2_item(struct dvb_extended_event_item_part2 *d) +{ +	return (uint8_t*) d + sizeof(struct dvb_extended_event_item_part2); +} + +/** + * Accessor for the second part of a dvb_extended_event_descriptor. + * + * @param d dvb_extended_event_descriptor pointer. + * @return dvb_extended_event_descriptor_part2 pointer. + */ +static inline struct dvb_extended_event_descriptor_part2* +	dvb_extended_event_descriptor_part2(struct dvb_extended_event_descriptor *d) +{ +	return (struct dvb_extended_event_descriptor_part2*) +		((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor) + +		 d->length_of_items); +} + +/** + * Accessor for the text field of an dvb_extended_event_descriptor_part2. + * + * @param d dvb_extended_event_descriptor_part2 pointer. + * @return Pointer to the text field. + */ +static inline uint8_t* +	dvb_extended_event_descriptor_part2_text(struct dvb_extended_event_descriptor_part2 *d) +{ +	return (uint8_t*) +		((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor_part2)); +} + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_extended_event_item* +	dvb_extended_event_descriptor_items_first(struct dvb_extended_event_descriptor *d) +{ +	if (d->length_of_items == 0) +		return NULL; + +	return (struct dvb_extended_event_item *) +		((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor)); +} + +static inline struct dvb_extended_event_item* +	dvb_extended_event_descriptor_items_next(struct dvb_extended_event_descriptor *d, +						 struct dvb_extended_event_item *pos) +{ +	struct dvb_extended_event_item_part2* part2 = +		dvb_extended_event_item_part2(pos); +	uint8_t *end = (uint8_t*) d + sizeof(struct dvb_extended_event_descriptor) + d->length_of_items; +	uint8_t *next =	(uint8_t *) part2 + +			sizeof(struct dvb_extended_event_item_part2) + +			part2->item_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_extended_event_item *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/frequency_list_descriptor.h b/lib/libucsi/dvb/frequency_list_descriptor.h new file mode 100644 index 0000000..4c18cec --- /dev/null +++ b/lib/libucsi/dvb/frequency_list_descriptor.h @@ -0,0 +1,107 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_FREQUENCY_LIST_DESCRIPTOR +#define _UCSI_DVB_FREQUENCY_LIST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for coding_type. + */ +enum { +	DVB_CODING_TYPE_SATELLITE		= 0x01, +	DVB_CODING_TYPE_CABLE			= 0x02, +	DVB_CODING_TYPE_TERRESTRIAL		= 0x03, +}; + +/** + * dvb_frequency_list_descriptor structure. + */ +struct dvb_frequency_list_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved	: 6; , +	uint8_t coding_type	: 2; ); +	/* uint32_t centre_frequencies [] */ +} __ucsi_packed; + +/** + * Process a dvb_frequency_list_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return dvb_frequency_list_descriptor pointer, or NULL on error. + */ +static inline struct dvb_frequency_list_descriptor* +	dvb_frequency_list_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	pos += sizeof(struct dvb_frequency_list_descriptor) - 2; + +	if ((len - pos) % 4) +		return NULL; + +	while(pos < len) { +		bswap32(buf+pos); +		pos += 4; +	} + +	return (struct dvb_frequency_list_descriptor*) d; +} + +/** + * Accessor for the centre_frequencies field of a dvb_frequency_list_descriptor. + * + * @param d dvb_frequency_list_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint32_t * +	dvb_frequency_list_descriptor_centre_frequencies(struct dvb_frequency_list_descriptor *d) +{ +	return (uint32_t *) ((uint8_t *) d + sizeof(struct dvb_frequency_list_descriptor)); +} + +/** + * Determine the number of entries in the centre_frequencies field of a dvb_frequency_list_descriptor. + * + * @param d dvb_frequency_list_descriptor pointer. + * @return The number of entries. + */ +static inline int +	dvb_frequency_list_descriptor_centre_frequencies_count(struct dvb_frequency_list_descriptor *d) +{ +	return (d->d.len - 1) >> 2; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/int_section.c b/lib/libucsi/dvb/int_section.c new file mode 100644 index 0000000..c2bb15f --- /dev/null +++ b/lib/libucsi/dvb/int_section.c @@ -0,0 +1,79 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2005 Patrick Boettcher (pb@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 + */ + +#include <libucsi/dvb/int_section.h> + +struct dvb_int_section * dvb_int_section_codec(struct section_ext *ext) +{ +	uint8_t *buf = (uint8_t *) ext; +	struct dvb_int_section *in = (struct dvb_int_section *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct dvb_int_section)) +		return NULL; + +	bswap32(buf+8); +	bswap16(buf+12); +	pos += 6; + +	if (len - pos < in->platform_descriptors_length) +		return NULL; + +	if (verify_descriptors(buf + pos, in->platform_descriptors_length)) +		return NULL; + +	pos += in->platform_descriptors_length; + +	while (pos < len) { +		struct dvb_int_target *s2 = (struct dvb_int_target *) (buf + pos); +		struct dvb_int_operational_loop *s3; + +		bswap16(buf + pos); /* target_descriptor_loop_length swap */ + +		if (len - pos < s2->target_descriptors_length) +			return NULL; + +		pos += sizeof(struct dvb_int_target); + +		if (verify_descriptors(buf + pos, s2->target_descriptors_length)) +			return NULL; + +		pos += s2->target_descriptors_length; + +		s3 = (struct dvb_int_operational_loop *) (buf + pos); + +		bswap16(buf + pos); /* operational_descriptor_loop_length swap */ + +		if (len - pos < s3->operational_descriptors_length) +			return NULL; + +		pos += sizeof(struct dvb_int_operational_loop); + +		if (verify_descriptors(buf + pos, s3->operational_descriptors_length)) +			return NULL; + +		pos += s3->operational_descriptors_length; +	} + +	return (struct dvb_int_section *) ext; +} diff --git a/lib/libucsi/dvb/int_section.h b/lib/libucsi/dvb/int_section.h new file mode 100644 index 0000000..932c0e8 --- /dev/null +++ b/lib/libucsi/dvb/int_section.h @@ -0,0 +1,245 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2005 Patrick Boettcher (pb@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 _UCSI_DVB_INT_SECTION_H +#define _UCSI_DVB_INT_SECTION_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_int_section structure - IP/MAC notification section. + */ +struct dvb_int_section { +	struct section_ext head; + +  EBIT2(uint32_t platform_id				:24;  , +	uint32_t processing_order			: 8;  ); +  EBIT2(uint16_t reserved2				: 4;  , +	uint16_t platform_descriptors_length		:12;  ); +	/* struct descriptor platform_descriptors[] */ +	/* struct dvb_int_target target_loop[] */ +} __ucsi_packed; + +/** + * An entry in the target_loop field of a dvb_int_section. + */ +struct dvb_int_target { +  EBIT2(uint16_t reserved3			: 4;  , +	uint16_t target_descriptors_length	:12;  ); +	/* struct descriptor target_descriptors[] */ +	/* struct dvb_int_operational_loop operational_loop */ +} __ucsi_packed; + +/** + * The operational_loop field in a dvb_int_target. + */ +struct dvb_int_operational_loop { +  EBIT2(uint16_t reserved4				: 4;  , +	uint16_t operational_descriptors_length		:12;  ); +	/* struct descriptor operational_descriptors[] */ +} __ucsi_packed; + +/** + * Process a dvb_int_section. + * + * @param section Generic section_ext pointer. + * @return dvb_int_section pointer, or NULL on error. + */ +extern struct dvb_int_section * dvb_int_section_codec(struct section_ext *section); + +/** + * Accessor for the action_type field of an INT. + * + * @param intp INT pointer. + * @return The action_type. + */ +static inline uint8_t dvb_int_section_action_type(struct dvb_int_section *intp) +{ +	return intp->head.table_id_ext >> 8; +} + +/** + * Accessor for the platform_id_hash field of an INT. + * + * @param intp INT pointer. + * @return The platform_id_hash. + */ +static inline uint8_t dvb_int_section_platform_id_hash(struct dvb_int_section *intp) +{ +	return intp->head.table_id_ext & 0xff; +} + +/** + * Iterator for platform_descriptors field in a dvb_int_section. + * + * @param intp dvb_int_section pointer. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define dvb_int_section_platform_descriptors_for_each(intp, pos) \ +	for ((pos) = dvb_int_section_platform_descriptors_first(intp); \ +	     (pos); \ +	     (pos) = dvb_int_section_platform_descriptors_next(intp, pos)) + +/** + * Iterator for the target_loop field in a dvb_int_section. + * + * @param intp dvb_int_section pointer. + * @param pos Variable holding a pointer to the current dvb_int_target. + */ +#define dvb_int_section_target_loop_for_each(intp,pos) \ +	for ((pos) = dvb_int_section_target_loop_first(intp); \ +	     (pos); \ +	     (pos) = dvb_int_section_target_loop_next(intp, pos)) + +/** + * Iterator for the target_descriptors field in a dvb_int_target. + * + * @param target dvb_int_target pointer. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define dvb_int_target_target_descriptors_for_each(target, pos) \ +	for ((pos) = dvb_int_target_target_descriptors_first(target); \ +	     (pos); \ +	     (pos) = dvb_int_target_target_descriptors_next(target, pos)) + +/** + * Accessor for the operational_loop field of a dvb_int_target. + * + * @param target dvb_int_target pointer. + * @return Pointer to a dvb_int_operational_loop. + */ +static inline struct dvb_int_operational_loop * +	dvb_int_target_operational_loop(struct dvb_int_target *target) +{ +	return (struct dvb_int_operational_loop *) +		((uint8_t *) target + sizeof(struct dvb_int_target) + target->target_descriptors_length); +} + +/** + * Iterator for the operational_descriptors field in a dvb_int_operational_loop. + * + * @param oploop dvb_int_operational_loop pointer. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define dvb_int_operational_loop_operational_descriptors_for_each(oploop, pos) \ +	for ((pos) = dvb_int_operational_loop_operational_descriptors_first(oploop); \ +	     (pos); \ +	     (pos) = dvb_int_operational_loop_operational_descriptors_next(oploop, pos)) + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	dvb_int_section_platform_descriptors_first(struct dvb_int_section *in) +{ +	if (in->platform_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) in + sizeof(struct dvb_int_section)); +} + +static inline struct descriptor * +	dvb_int_section_platform_descriptors_next(struct dvb_int_section *in, +		struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) in + sizeof(struct dvb_int_section), +		in->platform_descriptors_length, +		pos); +} + +static inline struct dvb_int_target * +	dvb_int_section_target_loop_first(struct dvb_int_section *in) +{ +	if (sizeof(struct dvb_int_section) + in->platform_descriptors_length >= (uint32_t) section_ext_length((struct section_ext *) in)) +		return NULL; + +	return (struct dvb_int_target *) +		((uint8_t *) in + sizeof(struct dvb_int_section) + in->platform_descriptors_length); +} + +static inline struct dvb_int_target * +	dvb_int_section_target_loop_next(struct dvb_int_section *in, +			struct dvb_int_target *pos) +{ +	struct dvb_int_operational_loop *ol = dvb_int_target_operational_loop(pos); +	struct dvb_int_target *next = +		(struct dvb_int_target *) ( (uint8_t *) pos + +			sizeof(struct dvb_int_target) + pos->target_descriptors_length + +			sizeof(struct dvb_int_operational_loop) + ol->operational_descriptors_length); +	struct dvb_int_target *end = +		(struct dvb_int_target *) ((uint8_t *) in + section_ext_length((struct section_ext *) in) ); + +	if (next >= end) +		return 0; +	return next; +} + +static inline struct descriptor * +	dvb_int_target_target_descriptors_first(struct dvb_int_target *tl) +{ +	if (tl->target_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) tl + sizeof(struct dvb_int_target)); +} + +static inline struct descriptor * +	dvb_int_target_target_descriptors_next(struct dvb_int_target *tl, +		struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) tl + sizeof(struct dvb_int_target), +		tl->target_descriptors_length, +		pos); +} + +static inline struct descriptor * +	dvb_int_operational_loop_operational_descriptors_first(struct dvb_int_operational_loop *ol) +{ +	if (ol->operational_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) ol + sizeof(struct dvb_int_operational_loop)); +} + +static inline struct descriptor * +	dvb_int_operational_loop_operational_descriptors_next(struct dvb_int_operational_loop *ol, +		struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) ol + sizeof(struct dvb_int_operational_loop), +		ol->operational_descriptors_length, +		pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h b/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h new file mode 100644 index 0000000..c470e89 --- /dev/null +++ b/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h @@ -0,0 +1,87 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR +#define _UCSI_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_ip_platform_name_descriptor structure. + */ +struct dvb_ip_platform_name_descriptor { +	struct descriptor d; + +	iso639lang_t language_code; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_ip_platform_name_descriptor. + * + * @param d Pointer to a generic descriptor. + * @return dvb_ip_platform_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ip_platform_name_descriptor* +	dvb_ip_platform_name_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_ip_platform_name_descriptor) - 2)) +		return NULL; + +	return (struct dvb_ip_platform_name_descriptor*) d; +} + +/** + * Accessor for the text field of a dvb_ip_platform_name_descriptor. + * + * @param d dvb_ip_platform_name_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_ip_platform_name_descriptor_text(struct dvb_ip_platform_name_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_ip_platform_name_descriptor); +} + +/** + * Determine the length of the text field of a dvb_ip_platform_name_descriptor. + * + * @param d dvb_ip_platform_name_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_ip_platform_name_descriptor_text_length(struct dvb_ip_platform_name_descriptor *d) +{ +	return d->d.len - 3; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h b/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h new file mode 100644 index 0000000..ba95b8f --- /dev/null +++ b/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h @@ -0,0 +1,87 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR +#define _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_ip_platform_provider_name_descriptor structure. + */ +struct dvb_ip_platform_provider_name_descriptor { +	struct descriptor d; + +	iso639lang_t language_code; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_ip_platform_provider_name_descriptor. + * + * @param d Pointer to a generic descriptor. + * @return dvb_ip_platform_provider_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ip_platform_provider_name_descriptor* +	dvb_ip_platform_provider_name_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_ip_platform_provider_name_descriptor) - 2)) +		return NULL; + +	return (struct dvb_ip_platform_provider_name_descriptor*) d; +} + +/** + * Accessor for the text field of a dvb_ip_platform_provider_name_descriptor. + * + * @param d dvb_ip_platform_provider_name_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_ip_platform_provider_name_descriptor_text(struct dvb_ip_platform_provider_name_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_ip_platform_provider_name_descriptor); +} + +/** + * Determine the length of the text field of a dvb_ip_platform_provider_name_descriptor. + * + * @param d dvb_ip_platform_provider_name_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_ip_platform_provider_name_descriptor_text_length(struct dvb_ip_platform_provider_name_descriptor *d) +{ +	return d->d.len - 3; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h b/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h new file mode 100644 index 0000000..36216d6 --- /dev/null +++ b/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h @@ -0,0 +1,73 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_IP_MAC_STREAM_LOCATION_DESCRIPTOR +#define _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_ip_mac_stream_location_descriptor structure. + */ +struct dvb_ip_mac_stream_location_descriptor { +	struct descriptor d; + +	uint16_t network_id; +	uint16_t original_network_id; +	uint16_t transport_stream_id; +	uint16_t service_id; +	uint8_t component_tag; +} __ucsi_packed; + +/** + * Process a dvb_ip_mac_stream_location_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_ip_mac_stream_location_descriptor pointer, or NULL on error. + */ +static inline struct dvb_ip_mac_stream_location_descriptor* +	dvb_ip_mac_stream_location_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; + +	if (d->len != (sizeof(struct dvb_ip_mac_stream_location_descriptor) - 2)) +		return NULL; + +	bswap16(buf); +	bswap16(buf+2); +	bswap16(buf+4); +	bswap16(buf+6); + +	return (struct dvb_ip_mac_stream_location_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/linkage_descriptor.h b/lib/libucsi/dvb/linkage_descriptor.h new file mode 100644 index 0000000..d2be789 --- /dev/null +++ b/lib/libucsi/dvb/linkage_descriptor.h @@ -0,0 +1,480 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_LINKAGE_DESCRIPTOR +#define _UCSI_DVB_LINKAGE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Possible values for linkage_type. + */ +enum { +	DVB_LINKAGE_TYPE_INFORMATION			= 0x01, +	DVB_LINKAGE_TYPE_EPG				= 0x02, +	DVB_LINKAGE_TYPE_CA_REPLACEMENT			= 0x03, +	DVB_LINKAGE_TYPE_TS_WITH_BAT_NIT		= 0x04, +	DVB_LINKAGE_TYPE_SERVICE_REPLACMENT		= 0x05, +	DVB_LINKAGE_TYPE_DATA_BCAST			= 0x06, +	DVB_LINKAGE_TYPE_RCS_MAP			= 0x07, +	DVB_LINKAGE_TYPE_MOBILE_HANDOVER		= 0x08, +	DVB_LINKAGE_TYPE_SOFTWARE_UPDATE		= 0x09, +	DVB_LINKAGE_TYPE_TS_WITH_SSU_BAT_NIT		= 0x0a, +	DVB_LINKAGE_TYPE_IP_MAC_NOTIFICATION		= 0x0b, +	DVB_LINKAGE_TYPE_TS_WITH_INT_BAT_NIT		= 0x0c, +}; + +/** + * Possible values for hand_over_type. + */ +enum { +	DVB_HAND_OVER_TYPE_IDENTICAL_NEIGHBOURING_COUNTRY	= 0x01, +	DVB_HAND_OVER_TYPE_LOCAL_VARIATION			= 0x02, +	DVB_HAND_OVER_TYPE_ASSOCIATED_SERVICE			= 0x03, +}; + +/** + * Possible values for origin_type. + */ +enum { +	DVB_ORIGIN_TYPE_NIT				= 0x00, +	DVB_ORIGIN_TYPE_SDT				= 0x01, +}; + +/** + * dvb_linkage_descriptor structure. + */ +struct dvb_linkage_descriptor { +	struct descriptor d; + +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint16_t service_id; +	uint8_t linkage_type; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Data for a linkage_type of 0x08. + */ +struct dvb_linkage_data_08 { +  EBIT3(uint8_t hand_over_type		: 4;  , +	uint8_t reserved		: 3;  , +	uint8_t origin_type		: 1;  ); +	/* uint16_t network_id if hand_over_type == 1,2,3 */ +	/* uint16_t initial_service_id if origin_type = 0 */ +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Data for an linkage_type of 0x0b (IP/MAC Notification Table). + */ +struct dvb_linkage_data_0b { +	uint8_t platform_id_data_length; +	/* struct platform_id ids[] */ +} __ucsi_packed; + +/** + * Entries in the ids field of a dvb_linkage_data_0b. + */ +struct dvb_platform_id { +  EBIT2(uint32_t platform_id			: 24; , +	uint8_t platform_name_loop_length	: 8;  ); +	/* struct platform_name names[] */ +} __ucsi_packed; + +/** + * Entries in the names field of a dvb_platform_id. + */ +struct dvb_platform_name { +	iso639lang_t language_code; +	uint8_t platform_name_length; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Data for a linkage_type of 0x0c (IP/MAC Notification Table). + */ +struct dvb_linkage_data_0c { +	uint8_t table_type; +	/* uint16_t bouquet_id if table_type == 0x02 */ +} __ucsi_packed; + + +/** + * Process a dvb_linkage_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_linkage_descriptor pointer, or NULL on error. + */ +static inline struct dvb_linkage_descriptor* +	dvb_linkage_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; +	struct dvb_linkage_descriptor *p = +		(struct dvb_linkage_descriptor*) d; + +	if (len < (sizeof(struct dvb_linkage_descriptor) - 2)) +		return NULL; + +	bswap16(buf); +	bswap16(buf+2); +	bswap16(buf+4); + +	pos += sizeof(struct dvb_linkage_descriptor) - 2; + +	if (p->linkage_type == 0x08) { +		struct dvb_linkage_data_08 *d08; + +		if ((len - pos) < sizeof(struct dvb_linkage_data_08)) +			return NULL; +		d08 = (struct dvb_linkage_data_08 *) (buf+pos); +		pos += sizeof(struct dvb_linkage_data_08); + +		switch(d08->hand_over_type) { +		case 1: +		case 2: +		case 3: +			if ((len - pos) < 2) +				return NULL; +			bswap16(buf+pos); +			pos += 2; +			break; +		} +		if (d08->origin_type == 0) { +			if ((len - pos) < 2) +				return NULL; +			bswap16(buf+pos); +			pos+=2; +		} + +	} else if (p->linkage_type == 0x0b) { +		uint32_t pos2=0; +		struct dvb_linkage_data_0b *l_0b = (struct dvb_linkage_data_0b *) (buf + pos); + +		if ((len - pos) < sizeof(struct dvb_linkage_data_0b)) +			return NULL; + +		pos += sizeof(struct dvb_linkage_data_0b); +		if ((len - pos) < l_0b->platform_id_data_length) +			return NULL; + +		while (pos2 < l_0b->platform_id_data_length) { +			bswap32(buf + pos + pos2); + +			struct dvb_platform_id *p_id = (struct dvb_platform_id *) (buf + pos + pos2); +			if ((len - pos - pos2) < p_id->platform_name_loop_length) +				return NULL; + +			pos2 += sizeof(struct dvb_platform_id) + p_id->platform_name_loop_length; +		} + +		pos += pos2; +	} else if (p->linkage_type == 0x0c) { +		struct dvb_linkage_data_0c *l_0c = (struct dvb_linkage_data_0c *) (buf + pos); + +		if ((len - pos) < sizeof(struct dvb_linkage_data_0c)) +			return NULL; +		pos += sizeof(struct dvb_linkage_data_0c); + +		if (l_0c->table_type == 0x02) { +			if ((len - pos) < 2) +				return NULL; +			bswap16(buf+pos); +		} +	} + +	return (struct dvb_linkage_descriptor*) d; +} + +/** + * Accessor for the data field of a dvb_linkage_descriptor. + * + * @param d dvb_linkage_descriptor pointer. + * @return Pointer to the data field. + */ +static inline uint8_t * +	dvb_linkage_descriptor_data(struct dvb_linkage_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_linkage_descriptor); +} + +/** + * Determine the length of the data field of a dvb_linkage_descriptor. + * + * @param d dvb_linkage_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_linkage_descriptor_data_length(struct dvb_linkage_descriptor *d) +{ +	return d->d.len - 7; +} + +/** + * Accessor for a dvb_linkage_data_08 pointer. + * + * @param d dvb_linkage_descriptor pointer. + * @return Pointer to the data field. + */ +static inline struct dvb_linkage_data_08 * +	dvb_linkage_data_08(struct dvb_linkage_descriptor *d) +{ +	if (d->linkage_type != 0x08) +		return NULL; +	return (struct dvb_linkage_data_08 *) dvb_linkage_descriptor_data(d); +} + +/** + * Accessor for the network_id field of a dvb_linkage_data_08. + * + * @param d dvb_linkage_descriptor pointer + * @param d08 dvb_linkage_data_08 pointer. + * @return network_id, or -1 if not present + */ +static inline int +	dvb_linkage_data_08_network_id(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08) +{ +	if (d->linkage_type != 0x08) +		return -1; + +	switch(d08->hand_over_type) { +	case 1: +	case 2: +	case 3: +		return *((uint16_t*) ((uint8_t*) d08 + sizeof(struct dvb_linkage_data_08))); +	} + +	return -1; +} + +/** + * Accessor for the initial_service_id field of a dvb_linkage_data_08. + * + * @param d dvb_linkage_descriptor pointer + * @param d08 dvb_linkage_data_08 pointer. + * @return initial_service_id, or -1 if not present + */ +static inline int +	dvb_linkage_data_08_initial_service_id(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08) +{ +	uint8_t *pos; + +	if (d->linkage_type != 0x08) +		return -1; +	if (d08->origin_type != 0) +		return -1; + +	pos = ((uint8_t*) d08) + sizeof(struct dvb_linkage_data_08); +	switch(d08->hand_over_type) { +	case 1: +	case 2: +	case 3: +		pos +=2; +		break; +	} + +	return *((uint16_t*) pos); +} + +/** + * Accessor for the data field of a dvb_linkage_data_08. + * + * @param d dvb_linkage_descriptor pointer + * @param d08 dvb_linkage_data_08 pointer. + * @param length Pointer to int destination for data length. + * @return Pointer to the data field, or NULL if invalid + */ +static inline uint8_t * +	dvb_linkage_data_08_data(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08, int *length) +{ +	uint8_t *pos; +	int used = 0; + +	if (d->linkage_type != 0x08) { +		*length = 0; +		return NULL; +	} + +	pos = ((uint8_t*) d08) + sizeof(struct dvb_linkage_data_08); +	switch(d08->hand_over_type) { +	case 1: +	case 2: +	case 3: +		pos += 2; +		used += 2; +		break; +	} +	if (d08->origin_type == 0) { +		pos+=2; +		used+=2; +	} + +	*length = dvb_linkage_descriptor_data_length(d) - (sizeof(struct dvb_linkage_data_08) + used); +	return pos; +} + +/** + * Accessor for a dvb_linkage_data_0b pointer. + * + * @param d dvb_linkage_descriptor pointer. + * @return Pointer to the data field. + */ +static inline struct dvb_linkage_data_0b * +	dvb_linkage_data_0b(struct dvb_linkage_descriptor *d) +{ +	if (d->linkage_type != 0x0b) +		return NULL; +	return (struct dvb_linkage_data_0b *) dvb_linkage_descriptor_data(d); +} + +/** + * Iterator for the platform_id field of a dvb_linkage_data_0b. + * + * @param linkage dvb_linkage_data_0b pointer. + * @param pos Variable containing a pointer to the current dvb_platform_id. + */ +#define dvb_linkage_data_0b_platform_id_for_each(linkage, pos) \ +	for ((pos) = dvb_platform_id_first(linkage); \ +	     (pos); \ +	     (pos) = dvb_platform_id_next(linkage, pos)) + +/** + * Iterator for the platform_name field of a dvb_platform_id. + * + * @param platid dvb_platform_id pointer. + * @param pos Variable containing a pointer to the current dvb_platform_name. + */ +#define dvb_platform_id_platform_name_for_each(platid, pos) \ +	for ((pos) = dvb_platform_name_first(platid); \ +	     (pos); \ +	     (pos) = dvb_platform_name_next(platid, pos)) + +/** + * Accessor for the text field of a dvb_platform_name. + * + * @param p dvb_platform_name pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_platform_name_text(struct dvb_platform_name *p) +{ +	return (uint8_t *) p + sizeof(struct dvb_platform_name); +} + +/** + * Accessor for a dvb_linkage_data_0c pointer. + * + * @param d dvb_linkage_descriptor pointer. + * @return Pointer to the data field. + */ +static inline struct dvb_linkage_data_0c * +		dvb_linkage_data_0c(struct dvb_linkage_descriptor *d) +{ +	if (d->linkage_type != 0x0c) +		return NULL; +	return (struct dvb_linkage_data_0c *) dvb_linkage_descriptor_data(d); +} + +/** + * Accessor for the bouquet_id field of a dvb_linkage_data_0c if table_id == 0x02. + * + * @param l_0c dvb_linkage_data_0c pointer. + * @return The bouquet field, or -1 on error. + */ +static inline int +	dvb_linkage_data_0c_bouquet_id(struct dvb_linkage_data_0c *l_0c) +{ +	if (l_0c->table_type != 0x02) +		return -1; + +	return *((uint16_t *) ((uint8_t*) l_0c + 1)); +} + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_platform_id * +	dvb_platform_id_first(struct dvb_linkage_data_0b *d) +{ +	if (d->platform_id_data_length == 0) +		return NULL; + +	return (struct dvb_platform_id *) ((uint8_t *) d + sizeof(struct dvb_linkage_data_0b)); +} + +static inline struct dvb_platform_id * +	dvb_platform_id_next(struct dvb_linkage_data_0b *d, +				    struct dvb_platform_id *pos) +{ +	uint8_t *end = (uint8_t *) d + d->platform_id_data_length; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_platform_id) + +			pos->platform_name_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_platform_id *) next; +} + +static inline struct dvb_platform_name * +	dvb_platform_name_first(struct dvb_platform_id *p) +{ +	if (p->platform_name_loop_length == 0) +		return NULL; + +	return (struct dvb_platform_name *) ((uint8_t *) p + sizeof(struct dvb_platform_id)); +} + +static inline struct dvb_platform_name * +	dvb_platform_name_next(struct dvb_platform_id *p, +				    struct dvb_platform_name *pos) +{ +	uint8_t *end = (uint8_t *) p + p->platform_name_loop_length; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_platform_name) + +			pos->platform_name_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_platform_name *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/local_time_offset_descriptor.h b/lib/libucsi/dvb/local_time_offset_descriptor.h new file mode 100644 index 0000000..d0eebb3 --- /dev/null +++ b/lib/libucsi/dvb/local_time_offset_descriptor.h @@ -0,0 +1,127 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR +#define _UCSI_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> +#include <libucsi/dvb/types.h> + +/** + * dvb_local_time_offset_descriptor parameter. + */ +struct dvb_local_time_offset_descriptor { +	struct descriptor d; + +	/* struct dvb_local_time_offset offsets[] */ +} __ucsi_packed; + +/** + * Entry in the offsets field of dvb_local_time_offset_descriptor. + */ +struct dvb_local_time_offset { +	iso639country_t country_code; +  EBIT3(uint8_t country_region_id		: 6; , +	uint8_t reserved			: 1; , +	uint8_t local_time_offset_polarity	: 1; ); +	dvbhhmm_t local_time_offset; +	dvbdate_t time_of_change; +	dvbhhmm_t next_time_offset; +} __ucsi_packed; + +/** + * Process a dvb_local_time_offset_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_local_time_offset_descriptor pointer, or NULL on error. + */ +static inline struct dvb_local_time_offset_descriptor* +	dvb_local_time_offset_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; +	uint32_t pos = 0; + +	if (len % sizeof(struct dvb_local_time_offset)) +		return NULL; + +	while(pos < len) { +		pos += sizeof(struct dvb_local_time_offset); +	} + +	return (struct dvb_local_time_offset_descriptor*) d; +} + +/** + * Iterator for the offsets field of a dvb_local_time_offset_descriptor. + * + * @param d dvb_local_time_offset_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_local_time_offset. + */ +#define dvb_local_time_offset_descriptor_offsets_for_each(d, pos) \ +	for ((pos) = dvb_local_time_offset_descriptor_offsets_first(d); \ +	     (pos); \ +	     (pos) = dvb_local_time_offset_descriptor_offsets_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_local_time_offset* +	dvb_local_time_offset_descriptor_offsets_first(struct dvb_local_time_offset_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_local_time_offset *) +		((uint8_t*) d + sizeof(struct dvb_local_time_offset_descriptor)); +} + +static inline struct dvb_local_time_offset* +	dvb_local_time_offset_descriptor_offsets_next(struct dvb_local_time_offset_descriptor *d, +						      struct dvb_local_time_offset *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_local_time_offset); + +	if (next >= end) +		return NULL; + +	return (struct dvb_local_time_offset *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h b/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h new file mode 100644 index 0000000..d79b48c --- /dev/null +++ b/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h @@ -0,0 +1,110 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MHP_DATA_BROADCAST_ID_DESCRIPTOR +#define _UCSI_DVB_MHP_DATA_BROADCAST_ID_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR +#error Must include dvb/data_broadcast_id_descriptor.h first +#endif + +/** + * Broadcast IDs for MHP. + */ +enum { +	DVB_BROADCAST_ID_MHP_OBJECT_CAROUSEL = 0x00f0, +	DVB_BROADCAST_ID_MHP_MPE = 0x00f1, +}; + +/** + * dvb_mhp_data_broadcast_id_descriptor structure. + */ +struct dvb_mhp_data_broadcast_id_descriptor { +	struct dvb_data_broadcast_id_descriptor d; +	/* uint16_t application_type[] */ +} __ucsi_packed; + +/** + * Process a dvb_mhp_data_broadcast_id_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_mhp_data_broadcast_id_descriptor pointer, or NULL on error. + */ +static inline struct dvb_mhp_data_broadcast_id_descriptor* +	dvb_mhp_data_broadcast_id_descriptor_codec(struct dvb_data_broadcast_id_descriptor* d) +{ +	uint8_t * buf; +	int len; +	int pos = 0; +	struct dvb_mhp_data_broadcast_id_descriptor *res = +		(struct dvb_mhp_data_broadcast_id_descriptor *) d; + +	if ((res->d.data_broadcast_id < 0xf0) || (res->d.data_broadcast_id > 0xfe)) +		return NULL; + +	buf = dvb_data_broadcast_id_descriptor_id_selector_byte(d); +	len = dvb_data_broadcast_id_descriptor_id_selector_byte_length(d); + +	if (len % 2) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos+=2; +	} + +	return res; +} + +/** + * Accessor for the application_type field of a dvb_mhp_data_broadcast_id_descriptor. + * + * @param d dvb_mhp_data_broadcast_id_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint16_t * +	dvb_mhp_data_broadcast_id_descriptor_id_application_type(struct dvb_mhp_data_broadcast_id_descriptor *d) +{ +	return (uint16_t *) dvb_data_broadcast_id_descriptor_id_selector_byte((struct dvb_data_broadcast_id_descriptor*) d); +} + +/** + * Determine the number of entries in the application_type field of a dvb_mhp_data_broadcast_id_descriptor. + * + * @param d dvb_data_broadcast_id_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_mhp_data_broadcast_id_descriptor_id_application_type_count(struct dvb_mhp_data_broadcast_id_descriptor *d) +{ +	return dvb_data_broadcast_id_descriptor_id_selector_byte_length((struct dvb_data_broadcast_id_descriptor*) d) >> 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/mosaic_descriptor.h b/lib/libucsi/dvb/mosaic_descriptor.h new file mode 100644 index 0000000..6da1e95 --- /dev/null +++ b/lib/libucsi/dvb/mosaic_descriptor.h @@ -0,0 +1,324 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MOSAIC_DESCRIPTOR +#define _UCSI_DVB_MOSAIC_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_mosaic_descriptor structure. + */ +struct dvb_mosaic_descriptor { +	struct descriptor d; + +  EBIT4(uint8_t mosaic_entry_point		: 1; , +	uint8_t number_of_horiz_elementary_cells: 3; , +	uint8_t reserved			: 1; , +	uint8_t number_of_vert_elementary_cells	: 3; ); +	/* struct dvb_mosaic_info infos[] */ +} __ucsi_packed; + +/** + * An entry in the infos field of a dvb_mosaic_descriptor. + */ +struct dvb_mosaic_info { +  EBIT3(uint16_t logical_cell_id		: 6; , +	uint16_t reserved			: 7; , +	uint16_t logical_cell_presentation_info	: 3; ); +	uint8_t elementary_cell_field_length; +	/* struct dvb_mosaic_elementary_cell_field fields[] */ +	/* struct dvb_mosaic_info_part2 part2 */ +	/* struct dvb_mosaic_linkage linkage */ +} __ucsi_packed; + +/** + * An entry in the fields field of a dvb_mosaic_info. + */ +struct dvb_mosaic_elementary_cell_field { +  EBIT2(uint8_t reserved		: 2; , +	uint8_t elementary_cell_id	: 6; ); +} __ucsi_packed; + +/** + * Part2 of dvb_mosaic_info, following the variable length fields field. + */ +struct dvb_mosaic_info_part2 { +	uint8_t cell_linkage_info; +} __ucsi_packed; + +struct dvb_mosaic_linkage_01 { +	uint16_t bouquet_id; +} __ucsi_packed; + +struct dvb_mosaic_linkage_02 { +	uint16_t original_network_id; +	uint16_t transport_stream_id; +	uint16_t service_id; +} __ucsi_packed; + +struct dvb_mosaic_linkage_03 { +	uint16_t original_network_id; +	uint16_t transport_stream_id; +	uint16_t service_id; +} __ucsi_packed; + +struct dvb_mosaic_linkage_04 { +	uint16_t original_network_id; +	uint16_t transport_stream_id; +	uint16_t service_id; +	uint16_t event_id; +} __ucsi_packed; + +/** + * Structure describing the linkage field of a dvb_mosaic_info + */ +struct dvb_mosaic_linkage { +	union { +		struct dvb_mosaic_linkage_01 linkage_01; +		struct dvb_mosaic_linkage_02 linkage_02; +		struct dvb_mosaic_linkage_03 linkage_03; +		struct dvb_mosaic_linkage_04 linkage_04; +	} u; +} __ucsi_packed; + +/** + * Process a dvb_mosaic_descriptor. + * + * @param d Pointer to a generic descriptor structure. + */ +static inline struct dvb_mosaic_descriptor* +	dvb_mosaic_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; +	struct dvb_mosaic_descriptor * p = +		(struct dvb_mosaic_descriptor *) d; + +	pos += (sizeof(struct dvb_mosaic_descriptor) - 2); + +	if (pos > len) +		return NULL; + +	while(pos < len) { +		struct dvb_mosaic_info *e = +			(struct dvb_mosaic_info*) (buf+pos); +		struct dvb_mosaic_info_part2 *e2; +		struct dvb_mosaic_linkage *linkage; + +		if ((pos + sizeof(struct dvb_mosaic_info)) > len) +			return NULL; + +		bswap16(buf + pos); + +		pos += sizeof(struct dvb_mosaic_info) + +			e->elementary_cell_field_length; + +		if (pos > len) +			return NULL; + +		e2 = (struct dvb_mosaic_info_part2*) (buf+pos); + +		pos += sizeof(struct dvb_mosaic_info_part2); + +		if (pos > len) +			return NULL; + +		linkage = (struct dvb_mosaic_linkage*) (buf+pos); + +		switch(e2->cell_linkage_info) { +		case 0x01: +			if ((pos + sizeof(struct dvb_mosaic_linkage_01)) > len) +				return NULL; +			bswap16(buf+pos); +			pos += sizeof(struct dvb_mosaic_linkage_01); +			break; + +		case 0x02: +			if ((pos + sizeof(struct dvb_mosaic_linkage_02)) > len) +				return NULL; +			bswap16(buf+pos); +			bswap16(buf+pos+2); +			bswap16(buf+pos+4); +			pos += sizeof(struct dvb_mosaic_linkage_02); +			break; + +		case 0x03: +			if ((pos + sizeof(struct dvb_mosaic_linkage_03)) > len) +				return NULL; +			bswap16(buf+pos); +			bswap16(buf+pos+2); +			bswap16(buf+pos+4); +			pos += sizeof(struct dvb_mosaic_linkage_03); +			break; + +		case 0x04: +			if ((pos + sizeof(struct dvb_mosaic_linkage_04)) > len) +				return NULL; +			bswap16(buf+pos); +			bswap16(buf+pos+2); +			bswap16(buf+pos+4); +			bswap16(buf+pos+6); +			pos += sizeof(struct dvb_mosaic_linkage_04); +			break; +		} +	} + +	return p; +} + +/** + * Iterator over the infos field of a dvb_mosaic_descriptor. + * + * @param d dvb_mosaic_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_mosaic_info. + */ +#define dvb_mosaic_descriptor_infos_for_each(d, pos) \ +	for ((pos) = dvb_mosaic_descriptor_infos_first(d); \ +	     (pos); \ +	     (pos) = dvb_mosaic_descriptor_infos_next(d, pos)) + +/** + * Iterator over the fields field of a dvb_mosaic_info. + * + * @param info dvb_mosaic_info pointer. + * @param pos Variable containing a pointer to the current dvb_mosaic_elementary_cell_field. + */ +#define dvb_mosaic_info_fields_for_each(info, pos) \ +	for ((pos) = dvb_mosaic_info_fields_first(info); \ +	     (pos); \ +	     (pos) = dvb_mosaic_info_fields_next(info, pos)) + +/** + * Accessor for the second part of the dvb_mosaic_info structure. + * + * @param entry dvb_mosaic_info pointer. + * @return dvb_mosaic_info_part2 pointer. + */ +static inline struct dvb_mosaic_info_part2* +	dvb_mosaic_info_part2(struct dvb_mosaic_info* entry) +{ +	return (struct dvb_mosaic_info_part2*) +		((uint8_t*) entry + sizeof(struct dvb_mosaic_info) + +		 entry->elementary_cell_field_length); +} + +/** + * Accessor for the linkage field a dvb_mosaic_info structure. + * + * @param entry dvb_mosaic_info_part2 pointer. + * @return dvb_mosaic_linkage pointer, or NULL on error. + */ +static inline struct dvb_mosaic_linkage* +	dvb_mosaic_linkage(struct dvb_mosaic_info_part2* entry) +{ +	if ((entry->cell_linkage_info != 0x01) && +	    (entry->cell_linkage_info != 0x02) && +	    (entry->cell_linkage_info != 0x03) && +	    (entry->cell_linkage_info != 0x04)) +		return NULL; + +	return (struct dvb_mosaic_linkage*) +		((uint8_t*) entry + sizeof(struct dvb_mosaic_info_part2)); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_mosaic_info* +	dvb_mosaic_descriptor_infos_first(struct dvb_mosaic_descriptor *d) +{ +	if (d->d.len == 1) +		return NULL; + +	return (struct dvb_mosaic_info *) +		((uint8_t*) d + sizeof(struct dvb_mosaic_descriptor)); +} + +static inline struct dvb_mosaic_info* +	dvb_mosaic_descriptor_infos_next(struct dvb_mosaic_descriptor *d, +					 struct dvb_mosaic_info *pos) +{ +	struct dvb_mosaic_info_part2* part2 = dvb_mosaic_info_part2(pos); +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_mosaic_info) + +			pos->elementary_cell_field_length + +			sizeof(struct dvb_mosaic_info_part2); + +	if (part2->cell_linkage_info == 0x01) +		next += sizeof(struct dvb_mosaic_linkage_01); +	else if (part2->cell_linkage_info == 0x02) +		next += sizeof(struct dvb_mosaic_linkage_02); +	else if (part2->cell_linkage_info == 0x03) +		next += sizeof(struct dvb_mosaic_linkage_03); +	else if (part2->cell_linkage_info == 0x04) +		next += sizeof(struct dvb_mosaic_linkage_04); + +	if (next >= end) +		return NULL; + +	return (struct dvb_mosaic_info *) next; +} + +static inline struct dvb_mosaic_elementary_cell_field* +	dvb_mosaic_info_fields_first(struct dvb_mosaic_info *d) +{ +	if (d->elementary_cell_field_length == 0) +		return NULL; + +	return (struct dvb_mosaic_elementary_cell_field*) +		((uint8_t*) d + sizeof(struct dvb_mosaic_info)); +} + +static inline struct dvb_mosaic_elementary_cell_field* +	dvb_mosaic_info_fields_next(struct dvb_mosaic_info *d, +				    struct dvb_mosaic_elementary_cell_field* pos) +{ +	uint8_t *end = (uint8_t*) d + sizeof(struct dvb_mosaic_info) + +			d->elementary_cell_field_length; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_mosaic_elementary_cell_field); + +	if (next >= end) +		return NULL; + +	return (struct dvb_mosaic_elementary_cell_field *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h b/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h new file mode 100644 index 0000000..0d8deb1 --- /dev/null +++ b/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h @@ -0,0 +1,145 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR +#define _UCSI_DVB_MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_multilingual_bouquet_name_descriptor structure. + */ +struct dvb_multilingual_bouquet_name_descriptor { +	struct descriptor d; + +	/* struct dvb_multilingual_bouquet_name names[]*/ +} __ucsi_packed; + +/** + * An entry in the names field of a dvb_multilingual_bouquet_name_descriptor. + */ +struct dvb_multilingual_bouquet_name { +	iso639lang_t language_code; +	uint8_t bouquet_name_length; +	/* uint8_t name[] */ +} __ucsi_packed; + +/** + * Process a dvb_multilingual_bouquet_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_multilingual_bouquet_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_multilingual_bouquet_name_descriptor* +	dvb_multilingual_bouquet_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_multilingual_bouquet_name *e = +			(struct dvb_multilingual_bouquet_name*) (buf+pos); + +		pos += sizeof(struct dvb_multilingual_bouquet_name); + +		if (pos > len) +			return NULL; + +		pos += e->bouquet_name_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_multilingual_bouquet_name_descriptor*) d; +} + +/** + * Iterator for entries in the names field of a dvb_multilingual_bouquet_name_descriptor. + * + * @param d dvb_multilingual_bouquet_name_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_multilingual_bouquet_name. + */ +#define dvb_multilingual_bouquet_name_descriptor_names_for_each(d, pos) \ +	for ((pos) = dvb_multilingual_bouquet_name_descriptor_names_first(d); \ +	     (pos); \ +	     (pos) = dvb_multilingual_bouquet_name_descriptor_names_next(d, pos)) + +/** + * Accessor for the name field of a dvb_multilingual_bouquet_name. + * + * @param e dvb_multilingual_bouquet_name pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_multilingual_bouquet_name_name(struct dvb_multilingual_bouquet_name *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_multilingual_bouquet_name); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_multilingual_bouquet_name* +	dvb_multilingual_bouquet_name_descriptor_names_first(struct dvb_multilingual_bouquet_name_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_multilingual_bouquet_name *) +		((uint8_t*) d + sizeof(struct dvb_multilingual_bouquet_name_descriptor)); +} + +static inline struct dvb_multilingual_bouquet_name* +	dvb_multilingual_bouquet_name_descriptor_names_next(struct dvb_multilingual_bouquet_name_descriptor *d, +							    struct dvb_multilingual_bouquet_name *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_multilingual_bouquet_name) + +			pos->bouquet_name_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_multilingual_bouquet_name *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/multilingual_component_descriptor.h b/lib/libucsi/dvb/multilingual_component_descriptor.h new file mode 100644 index 0000000..ab156af --- /dev/null +++ b/lib/libucsi/dvb/multilingual_component_descriptor.h @@ -0,0 +1,149 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MULTILINGUAL_COMPONENT_DESCRIPTOR +#define _UCSI_DVB_MULTILINGUAL_COMPONENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_multilingual_component_descriptor structure. + */ +struct dvb_multilingual_component_descriptor { +	struct descriptor d; + +	uint8_t component_tag; +	/* struct dvb_multilingual_component components[] */ +} __ucsi_packed; + +/** + * An entry in the components field of a dvb_multilingual_component_descriptor. + */ +struct dvb_multilingual_component { +	iso639lang_t language_code; +	uint8_t text_description_length; +	/* uint8_t text_char[] */ +} __ucsi_packed; + +/** + * Process a dvb_multilingual_component_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_multilingual_component_descriptor pointer, or NULL on error. + */ +static inline struct dvb_multilingual_component_descriptor* +	dvb_multilingual_component_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = sizeof(struct dvb_multilingual_component_descriptor) - 2; +	uint32_t len = d->len; + +	if (pos > len) +		return NULL; + +	while(pos < len) { +		struct dvb_multilingual_component *e = +			(struct dvb_multilingual_component*) (buf+pos); + +		pos += sizeof(struct dvb_multilingual_component); + +		if (pos > len) +			return NULL; + +		pos += e->text_description_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_multilingual_component_descriptor*) d; +} + +/** + * Iterator for entries in the components field of a dvb_multilingual_component_descriptor. + * + * @param d Generic descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_multilingual_component. + */ +#define dvb_multilingual_component_descriptor_components_for_each(d, pos) \ +	for ((pos) = dvb_multilingual_component_descriptor_components_first(d); \ +	     (pos); \ +	     (pos) = dvb_multilingual_component_descriptor_components_next(d, pos)) + +/** + * Accessor for the text_char field in a dvb_multilingual_component. + * + * @param e dvb_multilingual_component pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_multilingual_component_text_char(struct dvb_multilingual_component *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_multilingual_component); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_multilingual_component* +	dvb_multilingual_component_descriptor_components_first(struct dvb_multilingual_component_descriptor *d) +{ +	if (d->d.len == 1) +		return NULL; + +	return (struct dvb_multilingual_component *) +		((uint8_t*) d + sizeof(struct dvb_multilingual_component_descriptor)); +} + +static inline struct dvb_multilingual_component* +	dvb_multilingual_component_descriptor_components_next(struct dvb_multilingual_component_descriptor *d, +							      struct dvb_multilingual_component *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_multilingual_component) + +			pos->text_description_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_multilingual_component *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/multilingual_network_name_descriptor.h b/lib/libucsi/dvb/multilingual_network_name_descriptor.h new file mode 100644 index 0000000..1a7b8c4 --- /dev/null +++ b/lib/libucsi/dvb/multilingual_network_name_descriptor.h @@ -0,0 +1,145 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MULTILINGUAL_NETWORK_NAME_DESCRIPTOR +#define _UCSI_DVB_MULTILINGUAL_NETWORK_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_multilingual_network_name_descriptor structure. + */ +struct dvb_multilingual_network_name_descriptor { +	struct descriptor d; + +	/* struct dvb_multilingual_network_name names[] */ +} __ucsi_packed; + +/** + * An entry in the names field of a dvb_multilingual_network_name_descriptor. + */ +struct dvb_multilingual_network_name { +	iso639lang_t language_code; +	uint8_t network_name_length; +	/* uint8_t name[] */ +} __ucsi_packed; + +/** + * Process a dvb_multilingual_network_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_multilingual_network_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_multilingual_network_name_descriptor* +	dvb_multilingual_network_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_multilingual_network_name *e = +			(struct dvb_multilingual_network_name*) (buf + pos); + +		pos += sizeof(struct dvb_multilingual_network_name); + +		if (pos > len) +			return NULL; + +		pos += e->network_name_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_multilingual_network_name_descriptor*) d; +} + +/** + * Iterator for entries in the names field of a dvb_multilingual_network_name_descriptor. + * + * @param d dvb_multilingual_network_name_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_multilingual_network_name. + */ +#define dvb_multilingual_network_name_descriptor_names_for_each(d, pos) \ +	for ((pos) = dvb_multilingual_network_name_descriptor_names_first(d); \ +	     (pos); \ +	     (pos) = dvb_multilingual_network_name_descriptor_names_next(d, pos)) + +/** + * Accessor for the name field of a dvb_multilingual_network_name. + * + * @param e dvb_multilingual_network_name pointer. + * @return Pointer to the name field. + */ +static inline uint8_t * +	dvb_multilingual_network_name_name(struct dvb_multilingual_network_name *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_multilingual_network_name); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_multilingual_network_name* +	dvb_multilingual_network_name_descriptor_names_first(struct dvb_multilingual_network_name_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_multilingual_network_name *) +		((uint8_t*) d + sizeof(struct dvb_multilingual_network_name_descriptor)); +} + +static inline struct dvb_multilingual_network_name* +	dvb_multilingual_network_name_descriptor_names_next(struct dvb_multilingual_network_name_descriptor *d, +							    struct dvb_multilingual_network_name *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + +			sizeof(struct dvb_multilingual_network_name) + +			pos->network_name_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_multilingual_network_name *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/multilingual_service_name_descriptor.h b/lib/libucsi/dvb/multilingual_service_name_descriptor.h new file mode 100644 index 0000000..31bb9c3 --- /dev/null +++ b/lib/libucsi/dvb/multilingual_service_name_descriptor.h @@ -0,0 +1,197 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_MULTILINGUAL_SERVICE_NAME_DESCRIPTOR +#define _UCSI_DVB_MULTILINGUAL_SERVICE_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_multilingual_service_name_descriptor structure. + */ +struct dvb_multilingual_service_name_descriptor { +	struct descriptor d; + +	/* struct dvb_multilingual_service_name names[] */ +} __ucsi_packed; + +/** + * An entry in the service_names field of a dvb_multilingual_service_name_descriptor. + */ +struct dvb_multilingual_service_name { +	iso639lang_t language_code; +	uint8_t service_provider_name_length; +	/* uint8_t service_provider_name[] */ +	/* struct dvb_multilingual_service_name_part2 part2 */ +} __ucsi_packed; + +/** + * Second part of a dvb_multilingual_service_name following the variable length + * service_provider_name. + */ +struct dvb_multilingual_service_name_part2 { +	uint8_t service_name_length; +	/* uint8_t service_name[] */ +} __ucsi_packed; + +/** + * Process a dvb_multilingual_service_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_multilingual_service_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_multilingual_service_name_descriptor* +	dvb_multilingual_service_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_multilingual_service_name *e = +			(struct dvb_multilingual_service_name*) (buf+pos); +		struct dvb_multilingual_service_name_part2 *e2; + +		pos += sizeof(struct dvb_multilingual_service_name); + +		if (pos > len) +			return NULL; + +		pos += e->service_provider_name_length; + +		if (pos > len) +			return NULL; + +		e2 = (struct dvb_multilingual_service_name_part2*) (buf+pos); + +		pos += sizeof(struct dvb_multilingual_service_name_part2); + +		if (pos > len) +			return NULL; + +		pos += e2->service_name_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_multilingual_service_name_descriptor*) d; +} + +/** + * Iterator for entries in the service_name field of a dvb_multilingual_service_name_descriptor. + * + * @param d dvb_multilingual_service_name_descriptor pointer, + * @param pos Variable containing pointer to the current dvb_multilingual_service_name. + */ +#define dvb_multilingual_service_name_descriptor_names_for_each(d, pos) \ +	for ((pos) = dvb_multilingual_service_name_descriptor_names_first(d); \ +	     (pos); \ +	     (pos) = dvb_multilingual_service_name_descriptor_names_next(d, pos)) + +/** + * Accessor for the service_provider_name field of a dvb_multilingual_service_name. + * + * @param e dvb_multilingual_service_name pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_multilingual_service_name_service_provider_name(struct dvb_multilingual_service_name *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_multilingual_service_name); +} + +/** + * Accessor for the dvb_multilingual_service_name_part2 - second part of a + * dvb_multilingual_service_name following the service_name field. + * + * @param e dvb_multilingual_service_name Pointer. + * @return dvb_multilingual_service_name_part2 pointer. + */ +static inline struct dvb_multilingual_service_name_part2 * +	dvb_multilingual_service_name_part2(struct dvb_multilingual_service_name *e) +{ +	return (struct dvb_multilingual_service_name_part2 *) +		((uint8_t *) e + sizeof(struct dvb_multilingual_service_name) + +		 e->service_provider_name_length); +} + +/** + * Accessor for the service_name field of a dvb_multilingual_service_name_part2. + * + * @param e dvb_multilingual_service_name_part2 pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_multilingual_service_name_service_name(struct dvb_multilingual_service_name_part2 *e) +{ +	return (uint8_t *) e + sizeof(struct dvb_multilingual_service_name_part2); +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_multilingual_service_name* +	dvb_multilingual_service_name_descriptor_names_first(struct dvb_multilingual_service_name_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_multilingual_service_name *) +		((uint8_t*) d + sizeof(struct dvb_multilingual_service_name_descriptor)); +} + +static inline struct dvb_multilingual_service_name* +	dvb_multilingual_service_name_descriptor_names_next(struct dvb_multilingual_service_name_descriptor *d, +							    struct dvb_multilingual_service_name *pos) +{ +	struct dvb_multilingual_service_name_part2 * part2 = +			dvb_multilingual_service_name_part2(pos); +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) part2+ +			sizeof(struct dvb_multilingual_service_name_part2) + +			part2->service_name_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_multilingual_service_name *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/network_name_descriptor.h b/lib/libucsi/dvb/network_name_descriptor.h new file mode 100644 index 0000000..0754597 --- /dev/null +++ b/lib/libucsi/dvb/network_name_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_NETWORK_NAME_DESCRIPTOR +#define _UCSI_DVB_NETWORK_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_network_name_descriptor structure. + */ +struct dvb_network_name_descriptor { +	struct descriptor d; + +	/* char name[] */ +} __ucsi_packed; + +/** + * Process a dvb_network_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_network_name_descriptor pointer, or NULL on error. + */ +static inline struct dvb_network_name_descriptor* +	dvb_network_name_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_network_name_descriptor*) d; +} + +/** + * Accessor for the name field in a dvb_network_name_descriptor. + * + * @param d dvb_network_name_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_network_name_descriptor_name(struct dvb_network_name_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_network_name_descriptor); +} + +/** + * Calculate the length of the name field in a dvb_network_name_descriptor. + * + * @param d dvb_network_name_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_network_name_descriptor_name_length(struct dvb_network_name_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/nit_section.c b/lib/libucsi/dvb/nit_section.c new file mode 100644 index 0000000..664a0cb --- /dev/null +++ b/lib/libucsi/dvb/nit_section.c @@ -0,0 +1,78 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/nit_section.h> + +struct dvb_nit_section *dvb_nit_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	struct dvb_nit_section * ret = (struct dvb_nit_section *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct dvb_nit_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	if ((pos + ret->network_descriptors_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, ret->network_descriptors_length)) +		return NULL; + +	pos += ret->network_descriptors_length; + +	if ((pos + sizeof(struct dvb_nit_section_part2)) > len) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	while (pos < len) { +		struct dvb_nit_transport *transport = +			(struct dvb_nit_transport *)(buf + pos); + +		if ((pos + sizeof(struct dvb_nit_transport)) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 2); +		bswap16(buf + pos + 4); + +		pos += sizeof(struct dvb_nit_transport); + +		if ((pos + transport->transport_descriptors_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, +					transport->transport_descriptors_length)) +			return NULL; + +		pos += transport->transport_descriptors_length; +	} + +	if (pos != len) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/nit_section.h b/lib/libucsi/dvb/nit_section.h new file mode 100644 index 0000000..77ab1a0 --- /dev/null +++ b/lib/libucsi/dvb/nit_section.h @@ -0,0 +1,207 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_NIT_SECTION_H +#define _UCSI_DVB_NIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_nit_section structure. + */ +struct dvb_nit_section { +	struct section_ext head; + +  EBIT2(uint16_t reserved_1			: 4; , +	uint16_t network_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +	/* struct dvb_nit_section_part2 part2 */ +}; + +/** + * Second part of a dvb_nit_section, following the variable length descriptors field. + */ +struct dvb_nit_section_part2 { +  EBIT2(uint16_t reserved_2			: 4; , +	uint16_t transport_stream_loop_length	:12; ); +	/* struct dvb_nit_transport transports[] */ +} __ucsi_packed; + +/** + * An entry in the transports field of a dvb_nit_section_part2 + */ +struct dvb_nit_transport { +	uint16_t transport_stream_id; +	uint16_t original_network_id; +  EBIT2(uint16_t reserved			: 4; , +	uint16_t transport_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a dvb_nit_section. + * + * @param section Generic section_ext pointer. + * @return dvb_nit_section pointer, or NULL on error. + */ +struct dvb_nit_section * dvb_nit_section_codec(struct section_ext *section); + +/** + * Accessor for the network_id field of a NIT. + * + * @param nit NIT pointer. + * @return The network_id. + */ +static inline uint16_t dvb_nit_section_network_id(struct dvb_nit_section *nit) +{ +	return nit->head.table_id_ext; +} + +/** + * Iterator over the descriptors field in a dvb_nit_section. + * + * @param nit dvb_nit_section pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define dvb_nit_section_descriptors_for_each(nit, pos) \ +	for ((pos) = dvb_nit_section_descriptors_first(nit); \ +	     (pos); \ +	     (pos) = dvb_nit_section_descriptors_next(nit, pos)) + +/** + * Accessor for a pointer to the dvb_nit_section_part2 structure. + * + * @param nit dvb_nit_section pointer. + * @return dvb_nit_section_part2 pointer. + */ +static inline struct dvb_nit_section_part2 *dvb_nit_section_part2(struct dvb_nit_section * nit) +{ +	return (struct dvb_nit_section_part2 *) +		((uint8_t*) nit + sizeof(struct dvb_nit_section) + +		 nit->network_descriptors_length); +} + +/** + * Iterator over the transports field in a dvb_nit_section_part2. + * + * @param nit dvb_nit_section pointer. + * @param part2 dvb_nit_section_part2 pointer. + * @param pos Pointer to the current dvb_nit_transport. + */ +#define dvb_nit_section_transports_for_each(nit, part2, pos) \ +	for ((pos) = dvb_nit_section_transports_first(part2); \ +	     (pos); \ +	     (pos) = dvb_nit_section_transports_next(part2, pos)) + +/** + * Iterator over the descriptors field in a dvb_nit_transport. + * + * @param transport dvb_nit_transport pointer. + * @param pos Pointer to the current descriptor. + */ +#define dvb_nit_transport_descriptors_for_each(transport, pos) \ +	for ((pos) = dvb_nit_transport_descriptors_first(transport); \ +	     (pos); \ +	     (pos) = dvb_nit_transport_descriptors_next(transport, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	dvb_nit_section_descriptors_first(struct dvb_nit_section * nit) +{ +	if (nit->network_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) nit + sizeof(struct dvb_nit_section)); +} + +static inline struct descriptor * +	dvb_nit_section_descriptors_next(struct dvb_nit_section * nit, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) nit + sizeof(struct dvb_nit_section), +			      nit->network_descriptors_length, +			      pos); +} + +static inline struct dvb_nit_transport * +	dvb_nit_section_transports_first(struct dvb_nit_section_part2 *part2) +{ +	if (part2->transport_stream_loop_length == 0) +		return NULL; + +	return (struct dvb_nit_transport *) +		((uint8_t *)part2 + sizeof(struct dvb_nit_section_part2)); +} + +static inline struct dvb_nit_transport * +	dvb_nit_section_transports_next(struct dvb_nit_section_part2 *part2, +					struct dvb_nit_transport *pos) +{ +	uint8_t *end = (uint8_t*) part2 + sizeof(struct dvb_nit_section_part2) + +		part2->transport_stream_loop_length; +	uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_nit_transport) + +		pos->transport_descriptors_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_nit_transport *) next; +} + +static inline struct descriptor * +	dvb_nit_transport_descriptors_first(struct dvb_nit_transport *t) +{ +	if (t->transport_descriptors_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t*) t + sizeof(struct dvb_nit_transport)); +} + +static inline struct descriptor * +	dvb_nit_transport_descriptors_next(struct dvb_nit_transport *t, +					   struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) t + sizeof(struct dvb_nit_transport), +			      t->transport_descriptors_length, +			      pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/nvod_reference_descriptor.h b/lib/libucsi/dvb/nvod_reference_descriptor.h new file mode 100644 index 0000000..6180514 --- /dev/null +++ b/lib/libucsi/dvb/nvod_reference_descriptor.h @@ -0,0 +1,125 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_NVOD_REFERENCE_DESCRIPTOR +#define _UCSI_DVB_NVOD_REFERENCE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_nvod_reference_descriptor structure. + */ +struct dvb_nvod_reference_descriptor { +	struct descriptor d; + +	/* struct dvb_nvod_reference references[] */ +} __ucsi_packed; + +/** + * An entry in the references field of a dvb_nvod_reference_descriptor. + */ +struct dvb_nvod_reference { +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint16_t service_id; +} __ucsi_packed; + +/** + * Process a dvb_nvod_reference_descriptor. + * + * @param d Pointer to a generic descriptor structure pointer. + * @return dvb_nvod_reference_descriptor pointer, or NULL on error. + */ +static inline struct dvb_nvod_reference_descriptor* +	dvb_nvod_reference_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_nvod_reference)) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		bswap16(buf+pos+4); +		pos += sizeof(struct dvb_nvod_reference); +	} + +	return (struct dvb_nvod_reference_descriptor*) d; +} + +/** + * Iterator over the references field in a dvb_nvod_reference_descriptor. + * + * @param d dvb_nvod_reference_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_nvod_reference. + */ +#define dvb_nvod_reference_descriptor_references_for_each(d, pos) \ +	for ((pos) = dvb_nvod_reference_descriptor_references_first(d); \ +	     (pos); \ +	     (pos) = dvb_nvod_reference_descriptor_references_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_nvod_reference* +	dvb_nvod_reference_descriptor_references_first(struct dvb_nvod_reference_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_nvod_reference *) +		((uint8_t*) d + sizeof(struct dvb_nvod_reference_descriptor)); +} + +static inline struct dvb_nvod_reference* +	dvb_nvod_reference_descriptor_references_next(struct dvb_nvod_reference_descriptor *d, +						      struct dvb_nvod_reference *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_nvod_reference); + +	if (next >= end) +		return NULL; + +	return (struct dvb_nvod_reference *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/parental_rating_descriptor.h b/lib/libucsi/dvb/parental_rating_descriptor.h new file mode 100644 index 0000000..72ecd0a --- /dev/null +++ b/lib/libucsi/dvb/parental_rating_descriptor.h @@ -0,0 +1,135 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_PARENTAL_RATING_DESCRIPTOR +#define _UCSI_DVB_PARENTAL_RATING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Defined values for the rating field. + */ +enum { +	DVB_PARENTAL_RATING_MIN_3YEARS		= 0x01, +	DVB_PARENTAL_RATING_MIN_4YEARS		= 0x02, +	DVB_PARENTAL_RATING_MIN_5YEARS		= 0x03, +	DVB_PARENTAL_RATING_MIN_6YEARS		= 0x04, +	DVB_PARENTAL_RATING_MIN_7YEARS		= 0x05, +	DVB_PARENTAL_RATING_MIN_8YEARS		= 0x06, +	DVB_PARENTAL_RATING_MIN_9YEARS		= 0x07, +	DVB_PARENTAL_RATING_MIN_10YEARS		= 0x08, +	DVB_PARENTAL_RATING_MIN_11YEARS		= 0x09, +	DVB_PARENTAL_RATING_MIN_12YEARS		= 0x0a, +	DVB_PARENTAL_RATING_MIN_13YEARS		= 0x0b, +	DVB_PARENTAL_RATING_MIN_14YEARS		= 0x0c, +	DVB_PARENTAL_RATING_MIN_15YEARS		= 0x0d, +	DVB_PARENTAL_RATING_MIN_16YEARS		= 0x0e, +	DVB_PARENTAL_RATING_MIN_17YEARS		= 0x0f, +}; + +/** + * dvb_parental_rating_descriptor structure. + */ +struct dvb_parental_rating_descriptor { +	struct descriptor d; + +	/* struct dvb_parental_rating ratings[] */ +} __ucsi_packed; + +/** + * An entry in the ratings field of a dvb_parental_rating_descriptor. + */ +struct dvb_parental_rating { +	iso639country_t country_code; +	uint8_t rating; +} __ucsi_packed; + +/** + * Process a dvb_parental_rating_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_parental_rating_descriptor pointer, or NULL on error. + */ +static inline struct dvb_parental_rating_descriptor* +	dvb_parental_rating_descriptor_codec(struct descriptor* d) +{ +	if (d->len % sizeof(struct dvb_parental_rating)) +		return NULL; + +	return (struct dvb_parental_rating_descriptor*) d; +} + +/** + * Iterator for entries in the ratings field of a dvb_parental_rating_descriptor. + * + * @param d dvb_parental_rating_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_parental_rating. + */ +#define dvb_parental_rating_descriptor_ratings_for_each(d, pos) \ +	for ((pos) = dvb_parental_rating_descriptor_ratings_first(d); \ +	     (pos); \ +	     (pos) = dvb_parental_rating_descriptor_ratings_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_parental_rating* +	dvb_parental_rating_descriptor_ratings_first(struct dvb_parental_rating_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_parental_rating *) +		((uint8_t*) d + sizeof(struct dvb_parental_rating_descriptor)); +} + +static inline struct dvb_parental_rating* +	dvb_parental_rating_descriptor_ratings_next(struct dvb_parental_rating_descriptor *d, +						    struct dvb_parental_rating *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_parental_rating); + +	if (next >= end) +		return NULL; + +	return (struct dvb_parental_rating *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/partial_transport_stream_descriptor.h b/lib/libucsi/dvb/partial_transport_stream_descriptor.h new file mode 100644 index 0000000..6e3aa96 --- /dev/null +++ b/lib/libucsi/dvb/partial_transport_stream_descriptor.h @@ -0,0 +1,68 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_PARTIAL_TRANSPORT_STREAM_DESCRIPTOR +#define _UCSI_DVB_PARTIAL_TRANSPORT_STREAM_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_partial_transport_stream_descriptor structure. + */ +struct dvb_partial_transport_stream_descriptor { +	struct descriptor d; + +  EBIT6(uint64_t reserved				: 2;  , +	uint64_t peak_rate				:22;  , +  	uint64_t reserved_2				: 2;  , +	uint64_t minimum_overall_smoothing_rate		:22;  , +  	uint64_t reserved_3				: 2;  , +	uint64_t maximum_overall_smoothing_rate		:14;  ); +} __ucsi_packed; + +/** + * Process a dvb_partial_transport_stream_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_partial_transport_stream_descriptor pointer, or NULL on error. + */ +static inline struct dvb_partial_transport_stream_descriptor* +	dvb_partial_transport_stream_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_partial_transport_stream_descriptor) - 2)) +		return NULL; + +	bswap64((uint8_t*) d + 2); + +	return (struct dvb_partial_transport_stream_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/pdc_descriptor.h b/lib/libucsi/dvb/pdc_descriptor.h new file mode 100644 index 0000000..68190be --- /dev/null +++ b/lib/libucsi/dvb/pdc_descriptor.h @@ -0,0 +1,64 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_PDC_DESCRIPTOR +#define _UCSI_DVB_PDC_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_pdc_descriptor structure. + */ +struct dvb_pdc_descriptor { +	struct descriptor d; + +  EBIT2(uint32_t reserved		: 4; , +	uint32_t programme_id_label	:20; ); +} __ucsi_packed; + +/** + * Process a dvb_pdc_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return dvb_pdc_descriptor pointer, or NULL on error. + */ +static inline struct dvb_pdc_descriptor* +	dvb_pdc_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_pdc_descriptor) - 2)) +		return NULL; + +	bswap24((uint8_t*) d + 2); + +	return (struct dvb_pdc_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/private_data_specifier_descriptor.h b/lib/libucsi/dvb/private_data_specifier_descriptor.h new file mode 100644 index 0000000..f4cc03c --- /dev/null +++ b/lib/libucsi/dvb/private_data_specifier_descriptor.h @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR +#define _UCSI_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_private_data_specifier_descriptor structure. + */ +struct dvb_private_data_specifier_descriptor { +	struct descriptor d; + +	uint32_t private_data_specifier; +} __ucsi_packed; + +/** + * Process a dvb_private_data_specifier_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_private_data_specifier_descriptor pointer, or NULL on error. + */ +static inline struct dvb_private_data_specifier_descriptor* +	dvb_private_data_specifier_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_private_data_specifier_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct dvb_private_data_specifier_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/related_content_descriptor.h b/lib/libucsi/dvb/related_content_descriptor.h new file mode 100644 index 0000000..fd6a358 --- /dev/null +++ b/lib/libucsi/dvb/related_content_descriptor.h @@ -0,0 +1,56 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_RELATED_CONTENT_DESCRIPTOR +#define _UCSI_DVB_RELATED_CONTENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_related_content_descriptor structure. + */ +struct dvb_related_content_descriptor { +	struct descriptor d; +} __ucsi_packed; + +/** + * Process a dvb_related_content_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_related_content_descriptor pointer, or NULL on error. + */ +static inline struct dvb_related_content_descriptor* +	dvb_related_content_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_related_content_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h b/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h new file mode 100644 index 0000000..ba42d12 --- /dev/null +++ b/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h @@ -0,0 +1,110 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_RNT_RAR_OVER_DVB_STREAM_DESCRIPTOR +#define _UCSI_DVB_RNT_RAR_OVER_DVB_STREAM_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_rnt_rar_over_dvb_stream_descriptor structure. + */ +struct dvb_rnt_rar_over_dvb_stream_descriptor { +	struct descriptor d; + +	dvbdate_t first_valid_date; +	dvbdate_t last_valid_date; +  EBIT3(uint8_t weighting		: 6; , +	uint8_t complete_flag		: 1; , +	uint8_t scheduled_flag		: 1; ); +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint16_t service_id; +	uint8_t component_tag; +	/* struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info scheduled_info */ +} __ucsi_packed; + +/** + * The scheduled_info field of a dvb_rnt_rar_over_dvb_stream_descriptor (only appears + * if scheduled_flag = 1). + */ +struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info { +	dvbdate_t download_start_time; +	uint8_t download_period_duration; +	uint8_t download_cycle_time; +} __ucsi_packed; + +/** + * Process a dvb_rnt_rar_over_dvb_stream_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_rnt_rar_over_dvb_stream_descriptor pointer, or NULL on error. + */ +static inline struct dvb_rnt_rar_over_dvb_stream_descriptor* +	dvb_rnt_rar_over_dvb_stream_descriptor_codec(struct descriptor* d) +{ +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len + 2; +	struct dvb_rnt_rar_over_dvb_stream_descriptor *ret = +		(struct dvb_rnt_rar_over_dvb_stream_descriptor *) buf; + +	if (len < sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor)) +		return NULL; + +	bswap16(buf + 13); +	bswap16(buf + 15); +	bswap16(buf + 17); + +	if (ret->scheduled_flag == 1) { +		if (len < (sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor)+ +			   sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info))) +			return NULL; +	} + +	return ret; +} + +/** + * Accessor for the scheduled_info field of a dvb_rnt_rar_over_dvb_stream_descriptor. + * + * @param d dvb_rnt_rar_over_dvb_stream_descriptor pointer. + * @return Pointer, or NULL on error. + */ +static inline struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info* +	dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info(struct dvb_rnt_rar_over_dvb_stream_descriptor *d) +{ +	if (d->scheduled_flag != 1) +		return NULL; +	return (struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info*) +			((uint8_t*) d + sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h b/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h new file mode 100644 index 0000000..b1f2da4 --- /dev/null +++ b/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h @@ -0,0 +1,87 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_RNT_RAR_OVER_IP_DESCRIPTOR +#define _UCSI_DVB_RNT_RAR_OVER_IP_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_rnt_rar_over_ip_descriptor structure. + */ +struct dvb_rnt_rar_over_ip_descriptor { +	struct descriptor d; + +	dvbdate_t first_valid_date; +	dvbdate_t last_valid_date; +  EBIT3(uint8_t weighting		: 6; , +	uint8_t complete_flag		: 1; , +	uint8_t reserved		: 1; ); +	uint8_t url_length; +	/* uint8_t url[] */ +} __ucsi_packed; + +/** + * Process a dvb_rnt_rar_over_ip_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_rnt_rar_over_ip_descriptor pointer, or NULL on error. + */ +static inline struct dvb_rnt_rar_over_ip_descriptor* +	dvb_rnt_rar_over_ip_descriptor_codec(struct descriptor* d) +{ +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len + 2; +	struct dvb_rnt_rar_over_ip_descriptor *ret = +		(struct dvb_rnt_rar_over_ip_descriptor *) buf; + +	if (len < sizeof(struct dvb_rnt_rar_over_ip_descriptor)) +		return NULL; +	if (len < (sizeof(struct dvb_rnt_rar_over_ip_descriptor) + buf[13])) +		return NULL; + +	return ret; +} + +/** + * Accessor for the url field of a dvb_rnt_rar_over_ip_descriptor. + * + * @param d dvb_rnt_rar_over_ip_descriptor pointer. + * @return Pointer. + */ +static inline uint8_t* +	dvb_rnt_rar_over_ip_descriptor_url(struct dvb_rnt_rar_over_ip_descriptor *d) +{ +	return (uint8_t*) +		((uint8_t*) d + sizeof(struct dvb_rnt_rar_over_ip_descriptor)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h b/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h new file mode 100644 index 0000000..cb74f75 --- /dev/null +++ b/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h @@ -0,0 +1,125 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_RNT_RNT_SCAN_DESCRIPTOR +#define _UCSI_DVB_RNT_RNT_SCAN_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_rnt_rnt_scan_descriptor structure. + */ +struct dvb_rnt_rnt_scan_descriptor { +	struct descriptor d; + +	/* struct dvb_rnt_rnt_scan_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_rnt_rnt_scan_descriptor. + */ +struct dvb_rnt_rnt_scan_entry { +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint8_t scan_weighting; +} __ucsi_packed; + +/** + * Process a dvb_rnt_rnt_scan_descriptor. + * + * @param d Generic descriptor. + * @return dvb_rnt_rnt_scan_descriptor pointer, or NULL on error. + */ +static inline struct dvb_rnt_rnt_scan_descriptor* +	dvb_rnt_rnt_scan_descriptor_codec(struct descriptor* d) +{ +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len +2; +	uint32_t pos = 2; + +	if ((len-2) % sizeof(struct dvb_rnt_rnt_scan_entry)) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		pos += sizeof(struct dvb_rnt_rnt_scan_entry); +	} + +	return (struct dvb_rnt_rnt_scan_descriptor*) d; +} + +/** + * Iterator for entries field of a dvb_rnt_rnt_scan_descriptor. + * + * @param d dvb_rnt_rnt_scan_descriptor pointer. + * @param pos Variable holding a pointer to the current dvb_rnt_rnt_scan_entry. + */ +#define dvb_rnt_rnt_scan_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_rnt_rnt_scan_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_rnt_rnt_scan_descriptor_entries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_rnt_rnt_scan_entry* +	dvb_rnt_rnt_scan_descriptor_entries_first(struct dvb_rnt_rnt_scan_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_rnt_rnt_scan_entry *) +		((uint8_t*) d + sizeof(struct dvb_rnt_rnt_scan_descriptor)); +} + +static inline struct dvb_rnt_rnt_scan_entry* +	dvb_rnt_rnt_scan_descriptor_entries_next(struct dvb_rnt_rnt_scan_descriptor *d, +					     struct dvb_rnt_rnt_scan_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_rnt_rnt_scan_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_rnt_rnt_scan_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/rst_section.c b/lib/libucsi/dvb/rst_section.c new file mode 100644 index 0000000..259d2b0 --- /dev/null +++ b/lib/libucsi/dvb/rst_section.c @@ -0,0 +1,47 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/rst_section.h> + +struct dvb_rst_section * dvb_rst_section_codec(struct section *section) +{ +	uint8_t * buf = (uint8_t *) section; +	size_t pos = sizeof(struct section); +	size_t len = section_length(section); +	struct dvb_rst_section * ret = (struct dvb_rst_section *) section; + +	while (pos < len) { +		if ((pos + sizeof(struct dvb_rst_status)) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 2); +		bswap16(buf + pos + 4); +		bswap16(buf + pos + 6); + +		pos += sizeof(struct dvb_rst_status); +	} + +	if (pos != len) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/rst_section.h b/lib/libucsi/dvb/rst_section.h new file mode 100644 index 0000000..4b3360b --- /dev/null +++ b/lib/libucsi/dvb/rst_section.h @@ -0,0 +1,110 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_RST_SECTION_H +#define _UCSI_DVB_RST_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_rst_section structure. + */ +struct dvb_rst_section { +	struct section head; + +	/* struct dvb_rst_status statuses[] */ +}; + +/** + * An entry in the statuses field of a dvb_rst_section structure. + */ +struct dvb_rst_status { +	uint16_t transport_stream_id; +	uint16_t original_network_id; +	uint16_t service_id; +	uint16_t event_id; +  EBIT2(uint8_t reserved	: 5;  , +	uint8_t running_status	: 3;  ); +}; + +/** + * Process a dvb_rst_section. + * + * @param section Pointer to a generic section strcuture. + * @return dvb_rst_section pointer, or NULL on error. + */ +struct dvb_rst_section *dvb_rst_section_codec(struct section *section); + +/** + * Iterator for entries in the statuses field of a dvb_rst_section. + * + * @param rst dvb_rst_section pointer. + * @param pos Variable containing a pointer to the current dvb_rst_status. + */ +#define dvb_rst_section_statuses_for_each(rst, pos) \ +	for ((pos) = dvb_rst_section_statuses_first(rst); \ +	     (pos); \ +	     (pos) = dvb_rst_section_statuses_next(rst, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_rst_status * +	dvb_rst_section_statuses_first(struct dvb_rst_section *rst) +{ +	size_t pos = sizeof(struct dvb_rst_section); + +	if (pos >= section_length(&rst->head)) +		return NULL; + +	return (struct dvb_rst_status*) ((uint8_t *) rst + pos); +} + +static inline struct dvb_rst_status * +	dvb_rst_section_statuses_next(struct dvb_rst_section * rst, +				      struct dvb_rst_status * pos) +{ +	uint8_t *end = (uint8_t*) rst + section_length(&rst->head); +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_rst_status); + +	if (next >= end) +		return NULL; + +	return (struct dvb_rst_status *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h b/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h new file mode 100644 index 0000000..8f9fea8 --- /dev/null +++ b/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_S2_SATELLITE_DELIVERY_DESCRIPTOR +#define _UCSI_DVB_S2_SATELLITE_DELIVERY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_s2_satellite_delivery_descriptor structure. + */ +struct dvb_s2_satellite_delivery_descriptor { +	struct descriptor d; + +  EBIT4(uint8_t scrambling_sequence_selector	: 1; , +	uint8_t multiple_input_stream		: 1; , +	uint8_t backwards_compatability		: 1; , +	uint8_t reserved			: 5; ); +	/* uint32_t scrambling_sequence_index if scrambling_sequence_selector = 1 */ +	/* uint8_t input_stream_id if multiple_input_stream = 1 */ +} __ucsi_packed; + +/** + * Process a dvb_s2_satellite_delivery_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return dvb_s2_satellite_delivery_descriptor pointer, or NULL on error. + */ +static inline struct dvb_s2_satellite_delivery_descriptor* +	dvb_s2_satellite_delivery_descriptor_codec(struct descriptor* d) +{ +	struct dvb_s2_satellite_delivery_descriptor *s2 = +			(struct dvb_s2_satellite_delivery_descriptor*) d; + +	if (d->len < (sizeof(struct dvb_s2_satellite_delivery_descriptor) - 2)) +		return NULL; + +	int len = sizeof(struct dvb_s2_satellite_delivery_descriptor); +	if (s2->scrambling_sequence_selector) { +		len += 3; +	} +	if (s2->multiple_input_stream) { +		len += 1; +	} + +	if (d->len < len) +		return NULL; + +	return s2; +} + +/** + * Accessor for the scrambling_sequence_index field of a dvb_s2_satellite_delivery_descriptor. + * + * @param s2 dvb_s2_satellite_delivery_descriptor pointer. + * @return The scrambling_sequence_index. + */ +static inline uint32_t dvb_s2_satellite_delivery_descriptor_scrambling_sequence_index(struct dvb_s2_satellite_delivery_descriptor *s2) +{ +	uint8_t *tmp = (uint8_t*) s2; + +	if (s2->scrambling_sequence_selector) { +		return ((tmp[4] & 0x03) << 16) | (tmp[5] << 8) | tmp[6]; +	} +	return 0; +} + +/** + * Accessor for the input_stream_id field of a dvb_s2_satellite_delivery_descriptor. + * + * @param s2 dvb_s2_satellite_delivery_descriptor pointer. + * @return The input_stream_id. + */ +static inline uint8_t dvb_s2_satellite_delivery_descriptor_input_stream_id(struct dvb_s2_satellite_delivery_descriptor *s2) +{ +	uint8_t *tmp = (uint8_t*) s2; + +	if (!s2->multiple_input_stream) +		return 0; + +	int off = 3; +	if (s2->scrambling_sequence_selector) { +		off += 3; +	} +	return tmp[off]; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/satellite_delivery_descriptor.h b/lib/libucsi/dvb/satellite_delivery_descriptor.h new file mode 100644 index 0000000..b93d052 --- /dev/null +++ b/lib/libucsi/dvb/satellite_delivery_descriptor.h @@ -0,0 +1,73 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SATELLITE_DELIVERY_DESCRIPTOR +#define _UCSI_DVB_SATELLITE_DELIVERY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_satellite_delivery_descriptor structure. + */ +struct dvb_satellite_delivery_descriptor { +	struct descriptor d; + +	uint32_t frequency;			// BCD, units 10kHz +	uint16_t orbital_position; +  EBIT5(uint8_t west_east_flag		: 1; , +	uint8_t polarization  	  	: 2; , +	uint8_t roll_off	  	: 2; , +	uint8_t modulation_system 	: 1; , +	uint8_t modulation_type 	: 2; ); +  EBIT2(uint32_t symbol_rate		: 28; , // BCD, units 100Hz +	uint32_t fec_inner		: 4;  ); +} __ucsi_packed; + +/** + * Process a dvb_satellite_delivery_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return dvb_satellite_delivery_descriptor pointer, or NULL on error. + */ +static inline struct dvb_satellite_delivery_descriptor* +	dvb_satellite_delivery_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_satellite_delivery_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 6); +	bswap32((uint8_t*) d + 9); + +	return (struct dvb_satellite_delivery_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/scrambling_descriptor.h b/lib/libucsi/dvb/scrambling_descriptor.h new file mode 100644 index 0000000..4669bc8 --- /dev/null +++ b/lib/libucsi/dvb/scrambling_descriptor.h @@ -0,0 +1,61 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SCRAMBLING_DESCRIPTOR +#define _UCSI_DVB_SCRAMBLING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_scrambling_descriptor structure. + */ +struct dvb_scrambling_descriptor { +	struct descriptor d; + +	uint8_t scrambling_mode; +} __ucsi_packed; + +/** + * Process a dvb_scrambling_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to dvb_scrambling_descriptor, or NULL on error. + */ +static inline struct dvb_scrambling_descriptor* +	dvb_scrambling_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_scrambling_descriptor) - 2)) +		return NULL; + +	return (struct dvb_scrambling_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/sdt_section.c b/lib/libucsi/dvb/sdt_section.c new file mode 100644 index 0000000..4c7824c --- /dev/null +++ b/lib/libucsi/dvb/sdt_section.c @@ -0,0 +1,60 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/sdt_section.h> + +struct dvb_sdt_section * dvb_sdt_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct dvb_sdt_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 3; + +	while (pos < len) { +		struct dvb_sdt_service * service = +			(struct dvb_sdt_service *)(buf + pos); + +		if ((pos + sizeof(struct dvb_sdt_service)) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 3); +		pos += sizeof(struct dvb_sdt_service); + +		if ((pos + service->descriptors_loop_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, service->descriptors_loop_length)) +			return NULL; + +		pos += service->descriptors_loop_length; +	} + +	if (pos != len) +		return NULL; + +	return (struct dvb_sdt_section *) ext; +} diff --git a/lib/libucsi/dvb/sdt_section.h b/lib/libucsi/dvb/sdt_section.h new file mode 100644 index 0000000..03a8569 --- /dev/null +++ b/lib/libucsi/dvb/sdt_section.h @@ -0,0 +1,157 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SDT_SECTION_H +#define _UCSI_DVB_SDT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_sdt_section structure. + */ +struct dvb_sdt_section { +	struct section_ext head; + +	uint16_t original_network_id; +	uint8_t reserved; +	/* struct dvb_sdt_service services[] */ +} __ucsi_packed; + +/** + * An entry in the services field of a dvb_sdt_section. + */ +struct dvb_sdt_service { +	uint16_t service_id; +  EBIT3(uint8_t	reserved			: 6; , +	uint8_t eit_schedule_flag		: 1; , +	uint8_t eit_present_following_flag	: 1; ); +  EBIT3(uint16_t running_status			: 3; , +	uint16_t free_ca_mode			: 1; , +	uint16_t descriptors_loop_length	:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a dvb_sdt_section. + * + * @param section Pointer to a generic section_ext structure. + * @return dvb_sdt_section pointer, or NULL on error. + */ +struct dvb_sdt_section * dvb_sdt_section_codec(struct section_ext *section); + +/** + * Accessor for the transport_stream_id field of an SDT. + * + * @param sdt SDT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t dvb_sdt_section_transport_stream_id(struct dvb_sdt_section *sdt) +{ +	return sdt->head.table_id_ext; +} + +/** + * Iterator for the services field in a dvb_sdt_section. + * + * @param sdt dvb_sdt_section pointer. + * @param pos Variable containing a pointer to the current dvb_sdt_service. + */ +#define dvb_sdt_section_services_for_each(sdt, pos) \ +	for ((pos) = dvb_sdt_section_services_first(sdt); \ +	     (pos); \ +	     (pos) = dvb_sdt_section_services_next(sdt, pos)) + +/** + * Iterator for the descriptors field in a dvb_sdt_service. + * + * @param service dvb_sdt_service pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define dvb_sdt_service_descriptors_for_each(service, pos) \ +	for ((pos) = dvb_sdt_service_descriptors_first(service); \ +	     (pos); \ +	     (pos) = dvb_sdt_service_descriptors_next(service, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_sdt_service * +	dvb_sdt_section_services_first(struct dvb_sdt_section * sdt) +{ +	size_t pos = sizeof(struct dvb_sdt_section); + +	if (pos >= section_ext_length(&sdt->head)) +		return NULL; + +	return (struct dvb_sdt_service*) ((uint8_t *) sdt + pos); +} + +static inline struct dvb_sdt_service * +	dvb_sdt_section_services_next(struct dvb_sdt_section * sdt, +				      struct dvb_sdt_service * pos) +{ +	uint8_t *end = (uint8_t*) sdt + section_ext_length(&sdt->head); +	uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_sdt_service) + +			pos->descriptors_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_sdt_service *) next; +} + +static inline struct descriptor * +	dvb_sdt_service_descriptors_first(struct dvb_sdt_service *svc) +{ +	if (svc->descriptors_loop_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t*) svc + sizeof(struct dvb_sdt_service)); +} + +static inline struct descriptor * +	dvb_sdt_service_descriptors_next(struct dvb_sdt_service *svc, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) svc + sizeof(struct dvb_sdt_service), +			       svc->descriptors_loop_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/section.h b/lib/libucsi/dvb/section.h new file mode 100644 index 0000000..8488d71 --- /dev/null +++ b/lib/libucsi/dvb/section.h @@ -0,0 +1,107 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SECTION_H +#define _UCSI_DVB_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/dvb/bat_section.h> +#include <libucsi/dvb/dit_section.h> +#include <libucsi/dvb/eit_section.h> +#include <libucsi/dvb/nit_section.h> +#include <libucsi/dvb/rst_section.h> +#include <libucsi/dvb/sdt_section.h> +#include <libucsi/dvb/sit_section.h> +#include <libucsi/dvb/st_section.h> +#include <libucsi/dvb/tdt_section.h> +#include <libucsi/dvb/tot_section.h> +#include <libucsi/dvb/tva_container_section.h> +#include <libucsi/dvb/int_section.h> + +/** + * The following are not implemented just now. + */ +/* +#include <libucsi/dvb/tva_related_content_section.h> +#include <libucsi/dvb/tva_content_identifier_section.h> +#include <libucsi/dvb/tva_resolution_provider_notification_section.h> +#include <libucsi/dvb/ait_section.h> +#include <libucsi/dvb/cit_section.h> +#include <libucsi/dvb/rct_section.h> +#include <libucsi/dvb/rnt_section.h> +*/ + +#define TRANSPORT_NIT_PID 0x10 +#define TRANSPORT_SDT_PID 0x11 +#define TRANSPORT_BAT_PID 0x11 +#define TRANSPORT_EIT_PID 0x12 +#define TRANSPORT_CIT_PID 0x12 +#define TRANSPORT_RST_PID 0x13 +#define TRANSPORT_TDT_PID 0x14 +#define TRANSPORT_TOT_PID 0x14 +#define TRANSPORT_RNT_PID 0x16 +#define TRANSPORT_DIT_PID 0x1e +#define TRANSPORT_SIT_PID 0x1f + +/** + * Enumeration of DVB section tags. + */ +enum dvb_section_tag { +	stag_dvb_network_information_actual			= 0x40, +	stag_dvb_network_information_other			= 0x41, + +	stag_dvb_service_description_actual			= 0x42, +	stag_dvb_service_description_other			= 0x46, + +	stag_dvb_bouquet_association				= 0x4a, +	stag_dvb_update_notification				= 0x4b, /* same syntax as IP_MAC */ +	stag_dvb_ip_mac_notification				= 0x4c, + +	stag_dvb_event_information_nownext_actual		= 0x4e, +	stag_dvb_event_information_nownext_other		= 0x4f, +	stag_dvb_event_information_schedule_actual		= 0x50, /* 0x50->0x5f */ +	stag_dvb_event_information_schedule_other		= 0x60, /* 0x60->0x6f */ + +	stag_dvb_time_date					= 0x70, +	stag_dvb_running_status					= 0x71, +	stag_dvb_stuffing					= 0x72, +	stag_dvb_time_offset					= 0x73, +	stag_dvb_application_information			= 0x74, +	stag_dvb_tva_container					= 0x75, +	stag_dvb_tva_related_content				= 0x76, +	stag_dvb_tva_content_identifier				= 0x77, +	stag_dvb_mpe_fec					= 0x78, +	stag_dvb_tva_resolution_provider_notification		= 0x79, + +	stag_dvb_discontinuity_information			= 0x7e, +	stag_dvb_selection_information				= 0x7f, + +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/service_availability_descriptor.h b/lib/libucsi/dvb/service_availability_descriptor.h new file mode 100644 index 0000000..64def75 --- /dev/null +++ b/lib/libucsi/dvb/service_availability_descriptor.h @@ -0,0 +1,98 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SERVICE_AVAILABILITY_DESCRIPTOR +#define _UCSI_DVB_SERVICE_AVAILABILITY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_service_availability_descriptor structure. + */ +struct dvb_service_availability_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t availability_flag	: 1; , +	uint8_t reserved		: 7; ); +	/* uint16_t cell_ids[] */ +} __ucsi_packed; + +/** + * Process a dvb_service_availability_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return dvb_service_availability_descriptor pointer, or NULL on error. + */ +static inline struct dvb_service_availability_descriptor* +	dvb_service_availability_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* buf = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	pos += sizeof(struct dvb_service_availability_descriptor) - 2; + +	if ((len - pos) % 2) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos += 2; +	} + +	return (struct dvb_service_availability_descriptor*) d; +} + +/** + * Accessor for the cell_ids field of a dvb_service_availability_descriptor. + * + * @param d dvb_service_availability_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint16_t * +	dvb_service_availability_descriptor_cell_ids(struct dvb_service_availability_descriptor *d) +{ +	return (uint16_t *) ((uint8_t *) d + sizeof(struct dvb_service_availability_descriptor)); +} + +/** + * Determine the number of entries in the cell_ids field of a dvb_service_availability_descriptor. + * + * @param d dvb_service_availability_descriptor pointer. + * @return The number of entries. + */ +static inline int +	dvb_service_availability_descriptor_cell_ids_count(struct dvb_service_availability_descriptor *d) +{ +	return (d->d.len - 1) >> 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/service_descriptor.h b/lib/libucsi/dvb/service_descriptor.h new file mode 100644 index 0000000..dd0f0ec --- /dev/null +++ b/lib/libucsi/dvb/service_descriptor.h @@ -0,0 +1,163 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SERVICE_DESCRIPTOR +#define _UCSI_DVB_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for service_type. + */ +enum { +	DVB_SERVICE_TYPE_DIGITAL_TV		= 0x01, +	DVB_SERVICE_TYPE_DIGITAL_RADIO		= 0x02, +	DVB_SERVICE_TYPE_TELETEXT		= 0x03, +	DVB_SERVICE_TYPE_NVOD_REF		= 0x04, +	DVB_SERVICE_TYPE_NVOD_TIMESHIFT		= 0x05, +	DVB_SERVICE_TYPE_MOSAIC			= 0x06, +	DVB_SERVICE_TYPE_PAL			= 0x07, +	DVB_SERVICE_TYPE_SECAM			= 0x08, +	DVB_SERVICE_TYPE_D_D2_MAC		= 0x09, +	DVB_SERVICE_TYPE_FM_RADIO		= 0x0a, +	DVB_SERVICE_TYPE_NTSC			= 0x0b, +	DVB_SERVICE_TYPE_DATA_BCAST		= 0x0c, +	DVB_SERVICE_TYPE_EN50221		= 0x0d, +	DVB_SERVICE_TYPE_RCS_MAP		= 0x0e, +	DVB_SERVICE_TYPE_RCS_FLS		= 0x0f, +	DVB_SERVICE_TYPE_MHP			= 0x10, +	DVB_SERVICE_TYPE_MPEG2_HD_DIGITAL_TV	= 0x11, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_DIGITAL_TV = 0x16, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_NVOD_TIMESHIFT = 0x17, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_NVOD_REF = 0x18, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_DIGITAL_TV = 0x19, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_NVOD_TIMESHIFT = 0x1a, +	DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_NVOD_REF = 0x1b, +}; + +/** + * dvb_service_descriptor structure. + */ +struct dvb_service_descriptor { +	struct descriptor d; + +	uint8_t service_type; +	uint8_t service_provider_name_length; +	/* uint8_t service_provider_name[] */ +	/* struct dvb_service_descriptor_part2 part2 */ +} __ucsi_packed; + +/** + * Second part of a dvb_service_descriptor following the variable length + * service_provider_name field. + */ +struct dvb_service_descriptor_part2 { +	uint8_t service_name_length; +	/* uint8_t service_name[] */ +} __ucsi_packed; + +/** + * Process a dvb_service_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_service_descriptor pointer, or NULL on error. + */ +static inline struct dvb_service_descriptor* +	dvb_service_descriptor_codec(struct descriptor* d) +{ +	struct dvb_service_descriptor *p = +		(struct dvb_service_descriptor *) d; +	struct dvb_service_descriptor_part2 *p2; +	uint32_t pos = sizeof(struct dvb_service_descriptor) - 2; +	uint32_t len = d->len; + +	if (pos > len) +		return NULL; + +	pos += p->service_provider_name_length; + +	if (pos > len) +		return NULL; + +	p2 = (struct dvb_service_descriptor_part2*) ((uint8_t*) d + 2 + pos); + +	pos += sizeof(struct dvb_service_descriptor_part2); + +	if (pos > len) +		return NULL; + +	pos += p2->service_name_length; + +	if (pos != len) +		return NULL; + +	return p; +} + +/** + * Accessor for the service_provider_name field of a dvb_service_descriptor. + * + * @param d dvb_service_descriptor pointer. + * @return Pointer to the service_provider_name field. + */ +static inline uint8_t * +	dvb_service_descriptor_service_provider_name(struct dvb_service_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_service_descriptor); +} + +/** + * Accessor for the second part of a dvb_service_descriptor. + * + * @param d dvb_service_descriptor pointer. + * @return dvb_service_descriptor_part2 pointer. + */ +static inline struct dvb_service_descriptor_part2 * +	dvb_service_descriptor_part2(struct dvb_service_descriptor *d) +{ +	return (struct dvb_service_descriptor_part2 *) +		((uint8_t*) d + sizeof(struct dvb_service_descriptor) + +		 d->service_provider_name_length); +} + +/** + * Accessor for the service_name field of a dvb_service_descriptor_part2. + * + * @param d dvb_service_descriptor_part2 pointer. + * @return Pointer to the service_name field. + */ +static inline uint8_t * +	dvb_service_descriptor_service_name(struct dvb_service_descriptor_part2 *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_service_descriptor_part2); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/service_identifier_descriptor.h b/lib/libucsi/dvb/service_identifier_descriptor.h new file mode 100644 index 0000000..2037a05 --- /dev/null +++ b/lib/libucsi/dvb/service_identifier_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SERVICE_IDENTIFIER_DESCRIPTOR +#define _UCSI_DVB_SERVICE_IDENTIFIER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_service_identifier_descriptor. + */ +struct dvb_service_identifier_descriptor { +	struct descriptor d; + +	/* uint8_t identifier[] */ +} __ucsi_packed; + +/** + * Process a dvb_service_identifier_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_service_identifier_descriptor pointer, or NULL on error. + */ +static inline struct dvb_service_identifier_descriptor* +	dvb_service_identifier_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_service_identifier_descriptor*) d; +} + +/** + * Retrieve a pointer to the identifier field of a dvb_service_identifier_descriptor. + * + * @param d dvb_service_identifier_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_service_identifier_descriptor_identifier(struct dvb_service_identifier_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_service_identifier_descriptor); +} + +/** + * Calculate length of the identifier field of a dvb_service_identifier_descriptor. + * + * @param d dvb_service_identifier_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	dvb_service_identifier_descriptor_identifier_length(struct dvb_service_identifier_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/service_list_descriptor.h b/lib/libucsi/dvb/service_list_descriptor.h new file mode 100644 index 0000000..0086b25 --- /dev/null +++ b/lib/libucsi/dvb/service_list_descriptor.h @@ -0,0 +1,122 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SERVICE_LIST_DESCRIPTOR +#define _UCSI_DVB_SERVICE_LIST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_service_list_descriptor structure. + */ +struct dvb_service_list_descriptor { +	struct descriptor d; + +	/* struct dvb_service_list_service services[] */ +} __ucsi_packed; + +/** + * An entry in the services field of a dvb_service_list_descriptor. + */ +struct dvb_service_list_service { +	uint16_t service_id; +	uint8_t service_type; +} __ucsi_packed; + +/** + * Process a dvb_service_list_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_service_list_descriptor pointer, or NULL on error. + */ +static inline struct dvb_service_list_descriptor* +	dvb_service_list_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t len = d->len; +	uint8_t *p = (uint8_t*) d + 2; + +	if (len % sizeof(struct dvb_service_list_service)) +		return NULL; + +	while(pos < len) { +		bswap16(p+pos); +		pos += sizeof(struct dvb_service_list_service); +	} + +	return (struct dvb_service_list_descriptor*) d; +} + +/** + * Iterator for services field in a dvb_service_list_descriptor. + * + * @param d dvb_service_list_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_service_list_service. + */ +#define dvb_service_list_descriptor_services_for_each(d, pos) \ +	for ((pos) = dvb_service_list_descriptor_services_first(d); \ +	     (pos); \ +	     (pos) = dvb_service_list_descriptor_services_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_service_list_service* +	dvb_service_list_descriptor_services_first(struct dvb_service_list_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_service_list_service *) +		((uint8_t*) d + sizeof(struct dvb_service_list_descriptor)); +} + +static inline struct dvb_service_list_service* +	dvb_service_list_descriptor_services_next(struct dvb_service_list_descriptor *d, +						  struct dvb_service_list_service *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_service_list_service); + +	if (next >= end) +		return NULL; + +	return (struct dvb_service_list_service *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/service_move_descriptor.h b/lib/libucsi/dvb/service_move_descriptor.h new file mode 100644 index 0000000..7685e65 --- /dev/null +++ b/lib/libucsi/dvb/service_move_descriptor.h @@ -0,0 +1,67 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SERVICE_MOVE_DESCRIPTOR +#define _UCSI_DVB_SERVICE_MOVE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_service_move_descriptor structure. + */ +struct dvb_service_move_descriptor { +	struct descriptor d; + +	uint16_t new_original_network_id; +	uint16_t new_transport_stream_id; +	uint16_t new_service_id; +} __ucsi_packed; + +/** + * Process a dvb_service_move_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to dvb_service_move_descriptor, or NULL on error. + */ +static inline struct dvb_service_move_descriptor* +	dvb_service_move_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_service_move_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 4); +	bswap16((uint8_t*) d + 6); + +	return (struct dvb_service_move_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/short_event_descriptor.h b/lib/libucsi/dvb/short_event_descriptor.h new file mode 100644 index 0000000..449c6f0 --- /dev/null +++ b/lib/libucsi/dvb/short_event_descriptor.h @@ -0,0 +1,135 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SHORT_EVENT_DESCRIPTOR +#define _UCSI_DVB_SHORT_EVENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_short_event_descriptor structure. + */ +struct dvb_short_event_descriptor { +	struct descriptor d; + +	iso639lang_t language_code; +	uint8_t event_name_length; +	/* uint8_t event_name[] */ +	/* struct dvb_short_event_descriptor_part2 part2 */ +} __ucsi_packed; + +/** + * Second part of a dvb_short_event_descriptor, following the variable length + * name field. + */ +struct dvb_short_event_descriptor_part2 { +	uint8_t text_length; +	/* uint8_t text[] */ +} __ucsi_packed; + +/** + * Process a dvb_short_event_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_short_event_descriptor pointer, or NULL on error. + */ +static inline struct dvb_short_event_descriptor* +	dvb_short_event_descriptor_codec(struct descriptor* d) +{ +	struct dvb_short_event_descriptor *p = +		(struct dvb_short_event_descriptor*) d; +	struct dvb_short_event_descriptor_part2 *p2; +	uint32_t pos = sizeof(struct dvb_short_event_descriptor) - 2; +	uint32_t len = d->len; + +	if (pos > len) +		return NULL; + +	pos += p->event_name_length; + +	if (pos > len) +		return NULL; + +	p2 = (struct dvb_short_event_descriptor_part2*) ((uint8_t*) d + 2 + pos); + +	pos += sizeof(struct dvb_short_event_descriptor_part2); + +	if (pos > len) +		return NULL; + +	pos += p2->text_length; + +	if (pos != len) +		return NULL; + +	return p; +} + +/** + * Accessor for name field in a dvb_short_event_descriptor. + * + * @param d dvb_short_event_descriptor pointer. + * @return Pointer to name field. + */ +static inline uint8_t * +	dvb_short_event_descriptor_event_name(struct dvb_short_event_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_short_event_descriptor); +} + +/** + * Accessor for second part of a dvb_short_event_descriptor. + * + * @param d dvb_short_event_descriptor pointer. + * @return dvb_short_event_descriptor_part2 pointer. + */ +static inline struct dvb_short_event_descriptor_part2 * +	dvb_short_event_descriptor_part2(struct dvb_short_event_descriptor *d) +{ +	return (struct dvb_short_event_descriptor_part2 *) +		((uint8_t*) d + sizeof(struct dvb_short_event_descriptor) + +		 d->event_name_length); +} + +/** + * Accessor for text field in a dvb_short_event_descriptor_part2. + * + * @param d dvb_short_event_descriptor_part2 pointer. + * @return Pointer to text field. + */ +static inline uint8_t * +	dvb_short_event_descriptor_text(struct dvb_short_event_descriptor_part2 *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_short_event_descriptor_part2); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h b/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h new file mode 100644 index 0000000..e52d20a --- /dev/null +++ b/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h @@ -0,0 +1,87 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SHORT_SMOOTHING_BUFFER_DESCRIPTOR +#define _UCSI_DVB_SHORT_SMOOTHING_BUFFER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_short_smoothing_buffer_descriptor structure. + */ +struct dvb_short_smoothing_buffer_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t sb_size		: 2; , +	uint8_t sb_leak_rate	: 6; ); +	/* uint8_t reserved [] */ +} __ucsi_packed; + +/** + * Process a dvb_short_smoothing_buffer_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_short_smoothing_buffer_descriptor pointer, or NULL on error. + */ +static inline struct dvb_short_smoothing_buffer_descriptor* +	dvb_short_smoothing_buffer_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct dvb_short_smoothing_buffer_descriptor) - 2)) +		return NULL; + +	return (struct dvb_short_smoothing_buffer_descriptor*) d; +} + +/** + * Accessor for reserved field in a dvb_short_smoothing_buffer_descriptor. + * + * @param d dvb_short_smoothing_buffer_descriptor pointer. + * @return Pointer to reserved field. + */ +static inline uint8_t * +	dvb_short_smoothing_buffer_descriptor_reserved(struct dvb_short_smoothing_buffer_descriptor *d) +{ +	return (uint8_t*) d + sizeof(struct dvb_short_smoothing_buffer_descriptor); +} + +/** + * Calculate length of reserved field in a dvb_short_smoothing_buffer_descriptor. + * + * @param d dvb_short_smoothing_buffer_descriptor pointer. + * @return Length of the field in bytes. + */ +static inline int +	dvb_short_smoothing_buffer_descriptor_reserved_length(struct dvb_short_smoothing_buffer_descriptor *d) +{ +	return d->d.len - 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/sit_section.c b/lib/libucsi/dvb/sit_section.c new file mode 100644 index 0000000..06c228c --- /dev/null +++ b/lib/libucsi/dvb/sit_section.c @@ -0,0 +1,69 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/sit_section.h> + +struct dvb_sit_section * dvb_sit_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	struct dvb_sit_section * ret = (struct dvb_sit_section *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct dvb_sit_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	if ((pos + ret->transmission_info_loop_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, ret->transmission_info_loop_length)) +		return NULL; + +	pos += ret->transmission_info_loop_length; + +	while (pos < len) { +		struct dvb_sit_service * service = (void*)(buf + pos); + +		if ((pos + sizeof(struct dvb_sit_service)) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 2); +		bswap16(buf + pos + 4); +		pos += sizeof(struct dvb_sit_service); + +		if ((pos + service->service_loop_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, service->service_loop_length)) +			return NULL; + +		pos += service->service_loop_length; +	} + +	if (pos != len) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/sit_section.h b/lib/libucsi/dvb/sit_section.h new file mode 100644 index 0000000..e06d596 --- /dev/null +++ b/lib/libucsi/dvb/sit_section.h @@ -0,0 +1,173 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SIT_SECTION_H +#define _UCSI_DVB_SIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_sit_section structure. + */ +struct dvb_sit_section { +	struct section_ext head; + +  EBIT2(uint16_t reserved			: 4; , +	uint16_t transmission_info_loop_length  :12; ); +	/* struct descriptor descriptors[] */ +	/* struct dvb_sit_service services[] */ +}; + +/** + * An entry in the services field of a dvb_sit_section. + */ +struct dvb_sit_service { +	uint16_t service_id; +  EBIT3(uint16_t reserved		: 1; , +	uint16_t running_status		: 3; , +	uint16_t service_loop_length    :12; ); +	/* struct descriptor descriptors[] */ +}; + +/** + * Process a dvb_sit_section. + * + * @param section Generic section_ext structure. + * @return dvb_sit_section pointer, or NULL on error. + */ +struct dvb_sit_section * dvb_sit_section_codec(struct section_ext *section); + +/** + * Iterator for descriptors field in a dvb_sit_section. + * + * @param sit dvb_sit_section Pointer. + * @param pos Variable holding pointer to current descriptor. + */ +#define dvb_sit_section_descriptors_for_each(sit, pos) \ +	for ((pos) = dvb_sit_section_descriptors_first(sit); \ +	     (pos); \ +	     (pos) = dvb_sit_section_descriptors_first(sit)) + +/** + * Iterator for services field in a dvb_sit_section. + * + * @param sit dvb_sit_section Pointer. + * @param pos Variable holding pointer to current dvb_sit_service. + */ +#define dvb_sit_section_services_for_each(sit, pos) \ +	for ((pos) = dvb_sit_section_services_first(sit); \ +	     (pos); \ +	     (pos) = dvb_sit_section_services_next(sit, pos)) + +/** + * Iterator for descriptors field in a dvb_sit_service. + * + * @param service dvb_sit_service Pointer. + * @param pos Variable holding pointer to current descriptor. + */ +#define dvb_sit_service_descriptors_for_each(service, pos) \ +	for ((pos) = dvb_sit_service_descriptors_first(service); \ +	     (pos); \ +	     (pos) = dvb_sit_service_descriptors_next(service, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	dvb_sit_section_descriptors_first(struct dvb_sit_section *sit) +{ +	if (sit->transmission_info_loop_length == 0) +		return NULL; + +	return (struct descriptor *) +			((uint8_t *) sit + sizeof(struct dvb_sit_section)); +} + +static inline struct descriptor * +	dvb_sit_section_descriptors_next(struct dvb_sit_section *sit, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) sit + sizeof(struct dvb_sit_section), +			       sit->transmission_info_loop_length, +			       pos); +} + +static inline struct dvb_sit_service * +	dvb_sit_section_services_first(struct dvb_sit_section *sit) +{ +	size_t pos = sizeof(struct dvb_sit_section) + sit->transmission_info_loop_length; + +	if (pos >= section_ext_length(&sit->head)) +		return NULL; + +	return (struct dvb_sit_service*) ((uint8_t *) sit + pos); +} + +static inline struct dvb_sit_service * +	dvb_sit_section_services_next(struct dvb_sit_section *sit, +				      struct dvb_sit_service *pos) +{ +	uint8_t *end = (uint8_t*) sit + section_ext_length(&sit->head); +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_sit_service) + +			pos->service_loop_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_sit_service *) next; +} + +static inline struct descriptor * +	dvb_sit_service_descriptors_first(struct dvb_sit_service * t) +{ +	if (t->service_loop_length == 0) +		return NULL; + +	return (struct descriptor *) +			((uint8_t *) t + sizeof(struct dvb_sit_service)); +} + +static inline struct descriptor * +	dvb_sit_service_descriptors_next(struct dvb_sit_service *t, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t*) t + sizeof(struct dvb_sit_service), +			       t->service_loop_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/st_section.c b/lib/libucsi/dvb/st_section.c new file mode 100644 index 0000000..0e60aa1 --- /dev/null +++ b/lib/libucsi/dvb/st_section.c @@ -0,0 +1,29 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/st_section.h> + +struct dvb_st_section * dvb_st_section_codec(struct section * section) +{ +	struct dvb_st_section * ret = (struct dvb_st_section *)section; + +	return ret; +} diff --git a/lib/libucsi/dvb/st_section.h b/lib/libucsi/dvb/st_section.h new file mode 100644 index 0000000..52ba888 --- /dev/null +++ b/lib/libucsi/dvb/st_section.h @@ -0,0 +1,77 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_ST_SECTION_H +#define _UCSI_DVB_ST_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * dvb_st_section structure. + */ +struct dvb_st_section { +	struct section head; + +	/* uint8_t data[] */ +}; + +/** + * Process a dvb_st_section. + * + * @param section Generic section header. + * @return dvb_st_section pointer, or NULL on error. + */ +struct dvb_st_section *dvb_st_section_codec(struct section *section); + +/** + * Accessor for data field of dvb_st_section. + * + * @param st dvb_st_section Pointer. + * @return Pointer to field. + */ +static inline uint8_t* +	dvb_st_section_data(struct dvb_st_section* st) +{ +	return (uint8_t*) st + sizeof(struct dvb_st_section); +} + +/** + * Calculate length of data field of dvb_st_section. + * + * @param st dvb_st_section Pointer. + * @return Length in bytes. + */ +static inline int +	dvb_st_section_data_length(struct dvb_st_section* st) +{ +	return st->head.length; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/stream_identifier_descriptor.h b/lib/libucsi/dvb/stream_identifier_descriptor.h new file mode 100644 index 0000000..262c7e2 --- /dev/null +++ b/lib/libucsi/dvb/stream_identifier_descriptor.h @@ -0,0 +1,61 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_STREAM_IDENTIFIER_DESCRIPTOR +#define _UCSI_DVB_STREAM_IDENTIFIER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_stream_identifier_descriptor structure. + */ +struct dvb_stream_identifier_descriptor { +	struct descriptor d; + +	uint8_t component_tag; +} __ucsi_packed; + +/** + * Process a dvb_stream_identifier_descriptor. + * + * @param d Pointer to generic descriptor structure. + * @return dvb_stream_identifier_descriptor pointer, or NULL on error. + */ +static inline struct dvb_stream_identifier_descriptor* +	dvb_stream_identifier_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_stream_identifier_descriptor) - 2)) +		return NULL; + +	return (struct dvb_stream_identifier_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/stuffing_descriptor.h b/lib/libucsi/dvb/stuffing_descriptor.h new file mode 100644 index 0000000..48e415d --- /dev/null +++ b/lib/libucsi/dvb/stuffing_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_STUFFING_DESCRIPTOR +#define _UCSI_DVB_STUFFING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_stuffing_descriptor. + */ +struct dvb_stuffing_descriptor { +	struct descriptor d; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process a dvb_stuffing_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_stuffing_descriptor pointer, or NULL on error. + */ +static inline struct dvb_stuffing_descriptor* +	dvb_stuffing_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_stuffing_descriptor*) d; +} + +/** + * Retrieve a pointer to the data field of a dvb_stuffing_descriptor. + * + * @param d dvb_stuffing_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	dvb_stuffing_descriptor_data(struct dvb_stuffing_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_stuffing_descriptor); +} + +/** + * Calculate length of the data field of a dvb_stuffing_descriptor. + * + * @param d dvb_stuffing_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	dvb_stuffing_descriptor_data_length(struct dvb_stuffing_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/subtitling_descriptor.h b/lib/libucsi/dvb/subtitling_descriptor.h new file mode 100644 index 0000000..74fc25a --- /dev/null +++ b/lib/libucsi/dvb/subtitling_descriptor.h @@ -0,0 +1,126 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_SUBTITLING_DESCRIPTOR +#define _UCSI_DVB_SUBTITLING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_subtitling_descriptor structure. + */ +struct dvb_subtitling_descriptor { +	struct descriptor d; + +	/* struct dvb_subtitling_entry subtitles[] */ +} __ucsi_packed; + +/** + * An entry in the subtitles field of the a dvb_subtitling_descriptor. + */ +struct dvb_subtitling_entry { +	iso639lang_t language_code; +	uint8_t subtitling_type; +	uint16_t composition_page_id; +	uint16_t ancillary_page_id; +} __ucsi_packed; + +/** + * Process a dvb_subtitling_descriptor. + * + * @param d Generic descriptor. + * @return dvb_subtitling_descriptor pointer, or NULL on error. + */ +static inline struct dvb_subtitling_descriptor* +	dvb_subtitling_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint8_t* ptr = (uint8_t*) d + 2; +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_subtitling_entry)) +		return NULL; + +	while(pos < len) { +		bswap16(ptr+pos+4); +		bswap16(ptr+pos+6); +		pos += sizeof(struct dvb_subtitling_entry); +	} + +	return (struct dvb_subtitling_descriptor*) d; +} + +/** + * Iterator for subtitles field in dvb_subtitling_descriptor. + * + * @param d dvb_subtitling_descriptor pointer. + * @param pos Variable containing a pointer to current dvb_subtitling_entry. + */ +#define dvb_subtitling_descriptor_subtitles_for_each(d, pos) \ +	for ((pos) = dvb_subtitling_descriptor_subtitles_first(d); \ +	     (pos); \ +	     (pos) = dvb_subtitling_descriptor_subtitles_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_subtitling_entry* +	dvb_subtitling_descriptor_subtitles_first(struct dvb_subtitling_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_subtitling_entry *) +		((uint8_t*) d + sizeof(struct dvb_subtitling_descriptor)); +} + +static inline struct dvb_subtitling_entry* +	dvb_subtitling_descriptor_subtitles_next(struct dvb_subtitling_descriptor *d, +						 struct dvb_subtitling_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_subtitling_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_subtitling_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ip_address_descriptor.h b/lib/libucsi/dvb/target_ip_address_descriptor.h new file mode 100644 index 0000000..c08b60e --- /dev/null +++ b/lib/libucsi/dvb/target_ip_address_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IP_ADDRESS_DESCRIPTOR +#define _UCSI_DVB_TARGET_IP_ADDRESS_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ip_address_descriptor structure. + */ +struct dvb_target_ip_address_descriptor { +	struct descriptor d; + +	uint8_t ipv4_addr_mask[4]; +	/* struct dvb_ipv4_addr ipv4_addr[] */ +} __ucsi_packed; + +/** + * An entry in the ipv4_addr field of a dvb_target_ip_address_descriptor. + */ +struct dvb_ipv4_addr { +	uint8_t ipv4_addr[4]; +} __ucsi_packed; + +/** + * Process a dvb_target_ip_address_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ip_address_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ip_address_descriptor* +	dvb_target_ip_address_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len - 4; + +	if (len % sizeof(struct dvb_ipv4_addr)) +		return NULL; + +	return (struct dvb_target_ip_address_descriptor*) d; +} + +/** + * Iterator for entries in the ipv4_addr field of a dvb_target_ip_address_descriptor. + * + * @param d dvb_target_ip_address_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv4_addr. + */ +#define dvb_target_ip_address_descriptor_ipv4_addr_for_each(d, pos) \ +	for ((pos) = dvb_target_ip_address_descriptor_ipv4_addr_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ip_address_descriptor_ipv4_addr_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv4_addr* +	dvb_target_ip_address_descriptor_ipv4_addr_first(struct dvb_target_ip_address_descriptor *d) +{ +	if (d->d.len == 4) +		return NULL; + +	return (struct dvb_ipv4_addr *) +		((uint8_t*) d + sizeof(struct dvb_target_ip_address_descriptor)); +} + +static inline struct dvb_ipv4_addr* +	dvb_target_ip_address_descriptor_ipv4_addr_next(struct dvb_target_ip_address_descriptor *d, +						    struct dvb_ipv4_addr *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len - 4; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv4_addr); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv4_addr *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ip_slash_descriptor.h b/lib/libucsi/dvb/target_ip_slash_descriptor.h new file mode 100644 index 0000000..e5bc76a --- /dev/null +++ b/lib/libucsi/dvb/target_ip_slash_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IP_SLASH_DESCRIPTOR +#define _UCSI_DVB_TARGET_IP_SLASH_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ip_slash_descriptor structure. + */ +struct dvb_target_ip_slash_descriptor { +	struct descriptor d; + +	/* struct dvb_ipv4_slash ipv4_slash[] */ +} __ucsi_packed; + +/** + * An entry in the ipv4_slash field of a dvb_target_ip_slash_descriptor. + */ +struct dvb_ipv4_slash { +	uint8_t ipv4_addr[4]; +	uint8_t ipv4_slash; +} __ucsi_packed; + +/** + * Process a dvb_target_ip_slash_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ip_slash_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ip_slash_descriptor* +	dvb_target_ip_slash_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_ipv4_slash)) +		return NULL; + +	return (struct dvb_target_ip_slash_descriptor*) d; +} + +/** + * Iterator for entries in the ipv4_slash field of a dvb_target_ip_slash_descriptor. + * + * @param d dvb_target_ip_slash_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv4_slash. + */ +#define dvb_target_ip_slash_descriptor_ipv4_slash_for_each(d, pos) \ +	for ((pos) = dvb_target_ip_slash_descriptor_ipv4_slash_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ip_slash_descriptor_ipv4_slash_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv4_slash* +	dvb_target_ip_slash_descriptor_ipv4_slash_first(struct dvb_target_ip_slash_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ipv4_slash *) +		((uint8_t*) d + sizeof(struct dvb_target_ip_slash_descriptor)); +} + +static inline struct dvb_ipv4_slash* +	dvb_target_ip_slash_descriptor_ipv4_slash_next(struct dvb_target_ip_slash_descriptor *d, +						    struct dvb_ipv4_slash *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv4_slash); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv4_slash *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ip_source_slash_descriptor.h b/lib/libucsi/dvb/target_ip_source_slash_descriptor.h new file mode 100644 index 0000000..8cade48 --- /dev/null +++ b/lib/libucsi/dvb/target_ip_source_slash_descriptor.h @@ -0,0 +1,118 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IP_SOURCE_SLASH_DESCRIPTOR +#define _UCSI_DVB_TARGET_IP_SOURCE_SLASH_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ip_source_slash_descriptor structure. + */ +struct dvb_target_ip_source_slash_descriptor { +	struct descriptor d; + +	/* struct dvb_ipv4_source_slash ipv4_source_slash[] */ +} __ucsi_packed; + +/** + * An entry in the ipv4_source_slash field of a dvb_target_ip_source_slash_descriptor. + */ +struct dvb_ipv4_source_slash { +	uint8_t ipv4_source_addr[4]; +	uint8_t ipv4_source_slash; +	uint8_t ipv4_dest_addr[4]; +	uint8_t ipv4_dest_slash; +} __ucsi_packed; + +/** + * Process a dvb_target_ip_source_slash_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ip_source_slash_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ip_source_slash_descriptor* +	dvb_target_ip_source_slash_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_ipv4_source_slash)) +		return NULL; + +	return (struct dvb_target_ip_source_slash_descriptor*) d; +} + +/** + * Iterator for entries in the ipv4_source_slash field of a dvb_target_ip_source_slash_descriptor. + * + * @param d dvb_target_ip_source_slash_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv4_source_slash. + */ +#define dvb_target_ip_source_slash_descriptor_ipv4_source_slash_for_each(d, pos) \ +	for ((pos) = dvb_target_ip_source_slash_descriptor_ipv4_source_slash_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ip_source_slash_descriptor_ipv4_source_slash_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv4_source_slash* +	dvb_target_ip_source_slash_descriptor_ipv4_source_slash_first(struct dvb_target_ip_source_slash_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ipv4_source_slash *) +		((uint8_t*) d + sizeof(struct dvb_target_ip_source_slash_descriptor)); +} + +static inline struct dvb_ipv4_source_slash* +	dvb_target_ip_source_slash_descriptor_ipv4_source_slash_next(struct dvb_target_ip_source_slash_descriptor *d, +						    struct dvb_ipv4_source_slash *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv4_source_slash); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv4_source_slash *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ipv6_address_descriptor.h b/lib/libucsi/dvb/target_ipv6_address_descriptor.h new file mode 100644 index 0000000..1b28b48 --- /dev/null +++ b/lib/libucsi/dvb/target_ipv6_address_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IPV6_ADDRESS_DESCRIPTOR +#define _UCSI_DVB_TARGET_IPV6_ADDRESS_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ipv6_address_descriptor structure. + */ +struct dvb_target_ipv6_address_descriptor { +	struct descriptor d; + +	uint8_t ipv6_addr_mask[16]; +	/* struct dvb_ipv6_addr ipv6_addr[] */ +} __ucsi_packed; + +/** + * An entry in the ipv6_addr field of a dvb_target_ipv6_address_descriptor. + */ +struct dvb_ipv6_addr { +	uint8_t ipv6_addr[16]; +} __ucsi_packed; + +/** + * Process a dvb_target_ipv6_address_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ipv6_address_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ipv6_address_descriptor* +	dvb_target_ipv6_address_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len - 16; + +	if (len % sizeof(struct dvb_ipv6_addr)) +		return NULL; + +	return (struct dvb_target_ipv6_address_descriptor*) d; +} + +/** + * Iterator for entries in the ipv6_addr field of a dvb_target_ipv6_address_descriptor. + * + * @param d dvb_target_ipv6_address_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv6_addr. + */ +#define dvb_target_ipv6_address_descriptor_ipv6_addr_for_each(d, pos) \ +	for ((pos) = dvb_target_ipv6_address_descriptor_ipv6_addr_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ipv6_address_descriptor_ipv6_addr_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv6_addr* +	dvb_target_ipv6_address_descriptor_ipv6_addr_first(struct dvb_target_ipv6_address_descriptor *d) +{ +	if (d->d.len == 16) +		return NULL; + +	return (struct dvb_ipv6_addr *) +		((uint8_t*) d + sizeof(struct dvb_target_ipv6_address_descriptor)); +} + +static inline struct dvb_ipv6_addr* +	dvb_target_ipv6_address_descriptor_ipv6_addr_next(struct dvb_target_ipv6_address_descriptor *d, +						    struct dvb_ipv6_addr *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len - 16; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv6_addr); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv6_addr *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ipv6_slash_descriptor.h b/lib/libucsi/dvb/target_ipv6_slash_descriptor.h new file mode 100644 index 0000000..3dc6d75 --- /dev/null +++ b/lib/libucsi/dvb/target_ipv6_slash_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IPV6_SLASH_DESCRIPTOR +#define _UCSI_DVB_TARGET_IPV6_SLASH_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ipv6_slash_descriptor structure. + */ +struct dvb_target_ipv6_slash_descriptor { +	struct descriptor d; + +	/* struct dvb_ipv6_slash ipv6_slash[] */ +} __ucsi_packed; + +/** + * An entry in the ipv6_slash field of a dvb_target_ipv6_slash_descriptor. + */ +struct dvb_ipv6_slash { +	uint8_t ipv6_addr[16]; +	uint8_t ipv6_slash; +} __ucsi_packed; + +/** + * Process a dvb_target_ipv6_slash_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ipv6_slash_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ipv6_slash_descriptor* +	dvb_target_ipv6_slash_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_ipv6_slash)) +		return NULL; + +	return (struct dvb_target_ipv6_slash_descriptor*) d; +} + +/** + * Iterator for entries in the ipv6_slash field of a dvb_target_ipv6_slash_descriptor. + * + * @param d dvb_target_ipv6_slash_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv6_slash. + */ +#define dvb_target_ipv6_slash_descriptor_ipv6_slash_for_each(d, pos) \ +	for ((pos) = dvb_target_ipv6_slash_descriptor_ipv6_slash_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ipv6_slash_descriptor_ipv6_slash_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv6_slash* +	dvb_target_ipv6_slash_descriptor_ipv6_slash_first(struct dvb_target_ipv6_slash_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ipv6_slash *) +		((uint8_t*) d + sizeof(struct dvb_target_ipv6_slash_descriptor)); +} + +static inline struct dvb_ipv6_slash* +	dvb_target_ipv6_slash_descriptor_ipv6_slash_next(struct dvb_target_ipv6_slash_descriptor *d, +						    struct dvb_ipv6_slash *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv6_slash); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv6_slash *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h b/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h new file mode 100644 index 0000000..3a4b38e --- /dev/null +++ b/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h @@ -0,0 +1,118 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr) + * + * 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 _UCSI_DVB_TARGET_IPV6_SOURCE_SLASH_DESCRIPTOR +#define _UCSI_DVB_TARGET_IPV6_SOURCE_SLASH_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/types.h> + +/** + * dvb_target_ipv6_source_slash_descriptor structure. + */ +struct dvb_target_ipv6_source_slash_descriptor { +	struct descriptor d; + +	/* struct dvb_ipv6_source_slash ipv6_source_slash[] */ +} __ucsi_packed; + +/** + * An entry in the ipv6_source_slash field of a dvb_target_ipv6_source_slash_descriptor. + */ +struct dvb_ipv6_source_slash { +	uint8_t ipv6_source_addr[16]; +	uint8_t ipv6_source_slash; +	uint8_t ipv6_dest_addr[16]; +	uint8_t ipv6_dest_slash; +} __ucsi_packed; + +/** + * Process a dvb_target_ipv6_source_slash_descriptor. + * + * @param d Generic descriptor structure pointer. + * @return dvb_target_ipv6_source_slash_descriptor pointer, or NULL on error. + */ +static inline struct dvb_target_ipv6_source_slash_descriptor* +	dvb_target_ipv6_source_slash_descriptor_codec(struct descriptor* d) +{ +	uint32_t len = d->len; + +	if (len % sizeof(struct dvb_ipv6_source_slash)) +		return NULL; + +	return (struct dvb_target_ipv6_source_slash_descriptor*) d; +} + +/** + * Iterator for entries in the ipv6_source_slash field of a dvb_target_ipv6_source_slash_descriptor. + * + * @param d dvb_target_ipv6_source_slash_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_ipv6_source_slash. + */ +#define dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_for_each(d, pos) \ +	for ((pos) = dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_first(d); \ +	     (pos); \ +	     (pos) = dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_ipv6_source_slash* +	dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_first(struct dvb_target_ipv6_source_slash_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_ipv6_source_slash *) +		((uint8_t*) d + sizeof(struct dvb_target_ipv6_source_slash_descriptor)); +} + +static inline struct dvb_ipv6_source_slash* +	dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_next(struct dvb_target_ipv6_source_slash_descriptor *d, +						    struct dvb_ipv6_source_slash *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_ipv6_source_slash); + +	if (next >= end) +		return NULL; + +	return (struct dvb_ipv6_source_slash *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/tdt_section.c b/lib/libucsi/dvb/tdt_section.c new file mode 100644 index 0000000..ba64fe9 --- /dev/null +++ b/lib/libucsi/dvb/tdt_section.c @@ -0,0 +1,33 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/tdt_section.h> + +struct dvb_tdt_section * dvb_tdt_section_codec(struct section * section) +{ +	size_t len = section_length(section); +	struct dvb_tdt_section * ret = (struct dvb_tdt_section *) section; + +	if (len != sizeof(struct dvb_tdt_section)) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/tdt_section.h b/lib/libucsi/dvb/tdt_section.h new file mode 100644 index 0000000..fc2bcb8 --- /dev/null +++ b/lib/libucsi/dvb/tdt_section.h @@ -0,0 +1,54 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TDT_SECTION_H +#define _UCSI_DVB_TDT_SECTION_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> +#include <libucsi/dvb/types.h> + +/** + * dvb_tdt_section structure. + */ +struct dvb_tdt_section { +	struct section head; + +	dvbdate_t utc_time; +} __ucsi_packed; + +/** + * Process a dvb_tdt_section. + * + * @param section Generic section header. + * @return dvb_tdt_section pointer, or NULL on error. + */ +struct dvb_tdt_section *dvb_tdt_section_codec(struct section *section); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/telephone_descriptor.h b/lib/libucsi/dvb/telephone_descriptor.h new file mode 100644 index 0000000..3dc43a1 --- /dev/null +++ b/lib/libucsi/dvb/telephone_descriptor.h @@ -0,0 +1,150 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TELEPHONE_DESCRIPTOR +#define _UCSI_DVB_TELEPHONE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_telephone_descriptor stucture. + */ +struct dvb_telephone_descriptor { +	struct descriptor d; + +  EBIT3(uint8_t reserved_1			: 2; , +	uint8_t foreign_availability		: 1; , +	uint8_t connection_type			: 5; ); +  EBIT4(uint8_t reserved_2			: 1; , +	uint8_t country_prefix_length		: 2; , +	uint8_t international_area_code_length	: 3; , +	uint8_t operator_code_length		: 2; ); +  EBIT3(uint8_t reserved_3			: 1; , +	uint8_t national_area_code_length	: 3; , +	uint8_t core_number_length		: 4; ); +	/* uint8_t country_prefix[] */ +	/* uint8_t international_area_code[] */ +	/* uint8_t operator_code[] */ +	/* uint8_t national_area_code[] */ +	/* uint8_t core_number[] */ +} __ucsi_packed; + + +/** + * Process a dvb_telephone_descriptor. + * + * @param d Generic descriptor. + * @return dvb_telephone_descriptor pointer, or NULL on error. + */ +static inline struct dvb_telephone_descriptor* +	dvb_telephone_descriptor_codec(struct descriptor* d) +{ +	struct dvb_telephone_descriptor* p = +		(struct dvb_telephone_descriptor*) d; +	uint32_t pos = sizeof(struct dvb_telephone_descriptor) - 2; +	uint32_t len = d->len; + +	if (pos > len) +		return NULL; + +	pos +=  p->country_prefix_length + +		p->international_area_code_length + +		p->operator_code_length + +		p->national_area_code_length + +		p->core_number_length; + +	if (pos != len) +		return NULL; + +	return p; +} + +/** + * Retrieve pointer to country_prefix field of a dvb_telephone_descriptor. + * + * @param d dvb_telephone_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_telephone_descriptor_country_prefix(struct dvb_telephone_descriptor* d) +{ +	return (uint8_t*) d + sizeof(struct dvb_telephone_descriptor); +} + +/** + * Retrieve pointer to international_area_code field of a dvb_telephone_descriptor. + * + * @param d dvb_telephone_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_telephone_descriptor_international_area_code(struct dvb_telephone_descriptor* d) +{ +	return dvb_telephone_descriptor_country_prefix(d) + d->country_prefix_length; +} + +/** + * Retrieve pointer to operator_code field of a dvb_telephone_descriptor. + * + * @param d dvb_telephone_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_telephone_descriptor_operator_code(struct dvb_telephone_descriptor* d) +{ +	return dvb_telephone_descriptor_international_area_code(d) + d->international_area_code_length; +} + +/** + * Retrieve pointer to national_area_code field of a dvb_telephone_descriptor. + * + * @param d dvb_telephone_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_telephone_descriptor_national_area_code(struct dvb_telephone_descriptor* d) +{ +	return dvb_telephone_descriptor_operator_code(d) + d->operator_code_length; +} + +/** + * Retrieve pointer to core_number field of a dvb_telephone_descriptor. + * + * @param d dvb_telephone_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t* +	dvb_telephone_descriptor_core_number(struct dvb_telephone_descriptor* d) +{ +	return dvb_telephone_descriptor_national_area_code(d) + d->national_area_code_length; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/teletext_descriptor.h b/lib/libucsi/dvb/teletext_descriptor.h new file mode 100644 index 0000000..424c1cb --- /dev/null +++ b/lib/libucsi/dvb/teletext_descriptor.h @@ -0,0 +1,127 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TELETEXT_DESCRIPTOR +#define _UCSI_DVB_TELETEXT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Possible values for the type field. + */ +enum { +	DVB_TELETEXT_TYPE_INITIAL		= 0x01, +	DVB_TELETEXT_TYPE_SUBTITLE		= 0x02, +	DVB_TELETEXT_TYPE_ADDITIONAL		= 0x03, +	DVB_TELETEXT_TYPE_SCHEDULE		= 0x04, +	DVB_TELETEXT_TYPE_SUBTITLE_HEARING_IMPAIRED= 0x05, +}; + +/** + * dvb_teletext_descriptor structure. + */ +struct dvb_teletext_descriptor { +	struct descriptor d; + +	/* struct dvb_teletext_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_teletext_descriptor. + */ +struct dvb_teletext_entry { +	iso639lang_t language_code; +  EBIT2(uint8_t type		: 5; , +	uint8_t magazine_number: 3; ); +	uint8_t page_number; +} __ucsi_packed; + +/** + * Process a dvb_teletext_descriptor. + * + * @param d Generic descriptor. + * @return dvb_teletext_descriptor pointer, or NULL on error. + */ +static inline struct dvb_teletext_descriptor* +	dvb_teletext_descriptor_codec(struct descriptor* d) +{ +	if (d->len % sizeof(struct dvb_teletext_entry)) +		return NULL; + +	return (struct dvb_teletext_descriptor*) d; +} + +/** + * Iterator for entries field of a dvb_teletext_descriptor. + * + * @param d dvb_teletext_descriptor pointer. + * @param pos Variable holding a pointer to the current dvb_teletext_entry. + */ +#define dvb_teletext_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_teletext_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_teletext_descriptor_entries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_teletext_entry* +	dvb_teletext_descriptor_entries_first(struct dvb_teletext_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_teletext_entry *) +		((uint8_t*) d + sizeof(struct dvb_teletext_descriptor)); +} + +static inline struct dvb_teletext_entry* +	dvb_teletext_descriptor_entries_next(struct dvb_teletext_descriptor *d, +					     struct dvb_teletext_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_teletext_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_teletext_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/terrestrial_delivery_descriptor.h b/lib/libucsi/dvb/terrestrial_delivery_descriptor.h new file mode 100644 index 0000000..c624dab --- /dev/null +++ b/lib/libucsi/dvb/terrestrial_delivery_descriptor.h @@ -0,0 +1,77 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TERRESTRIAL_DELIVERY_DESCRIPTOR +#define _UCSI_DVB_TERRESTRIAL_DELIVERY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_terrestrial_delivery_descriptor structure. + */ +struct dvb_terrestrial_delivery_descriptor { +	struct descriptor d; + +	uint32_t centre_frequency;		// Normal integer, units 10Hz +  EBIT5(uint8_t bandwidth		: 3; , +	uint8_t priority		: 1; , +	uint8_t time_slicing_indicator	: 1; , +	uint8_t mpe_fec_indicator	: 1; , +	uint8_t reserved_1		: 2; ); +  EBIT3(uint8_t constellation		: 2; , +	uint8_t hierarchy_information	: 3; , +	uint8_t code_rate_hp_stream	: 3; ); +  EBIT4(uint8_t code_rate_lp_stream	: 3; , +	uint8_t guard_interval		: 2; , +	uint8_t transmission_mode	: 2; , +	uint8_t other_frequency_flag	: 1; ); +	uint32_t reserved_2; +} __ucsi_packed; + +/** + * Process a dvb_terrestrial_delivery_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_terrestrial_delivery_descriptor pointer, or NULL on error. + */ +static inline struct dvb_terrestrial_delivery_descriptor* +	dvb_terrestrial_delivery_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_terrestrial_delivery_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); +	bswap32((uint8_t*) d + 9); + +	return (struct dvb_terrestrial_delivery_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/time_shifted_event_descriptor.h b/lib/libucsi/dvb/time_shifted_event_descriptor.h new file mode 100644 index 0000000..6b4a9f6 --- /dev/null +++ b/lib/libucsi/dvb/time_shifted_event_descriptor.h @@ -0,0 +1,65 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR +#define _UCSI_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_time_shifted_event_descriptor structure. + */ +struct dvb_time_shifted_event_descriptor { +	struct descriptor d; + +	uint16_t reference_service_id; +	uint16_t reference_event_id; +} __ucsi_packed; + +/** + * Process a dvb_time_shifted_event_descriptor. + * + * @param d Generic descriptor. + * @return dvb_time_shifted_event_descriptor pointer, or NULL on error. + */ +static inline struct dvb_time_shifted_event_descriptor* +	dvb_time_shifted_event_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_time_shifted_event_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 4); + +	return (struct dvb_time_shifted_event_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/time_shifted_service_descriptor.h b/lib/libucsi/dvb/time_shifted_service_descriptor.h new file mode 100644 index 0000000..c8dcc0e --- /dev/null +++ b/lib/libucsi/dvb/time_shifted_service_descriptor.h @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR +#define _UCSI_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_time_shifted_service_descriptor structure. + */ +struct dvb_time_shifted_service_descriptor { +	struct descriptor d; + +	uint16_t reference_service_id; +} __ucsi_packed; + +/** + * Process a dvb_time_shifted_service_descriptor. + * + * @param d Generic descriptor. + * @return Pointer to dvb_time_shifted_service_descriptor, or NULL on error. + */ +static inline struct dvb_time_shifted_service_descriptor* +	dvb_time_shifted_service_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct dvb_time_shifted_service_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); + +	return (struct dvb_time_shifted_service_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/tot_section.c b/lib/libucsi/dvb/tot_section.c new file mode 100644 index 0000000..5dc7890 --- /dev/null +++ b/lib/libucsi/dvb/tot_section.c @@ -0,0 +1,50 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/tot_section.h> + +struct dvb_tot_section *dvb_tot_section_codec(struct section *section) +{ +	uint8_t * buf = (uint8_t *)section; +	size_t pos = sizeof(struct section); +	size_t len = section_length(section) - CRC_SIZE; +	struct dvb_tot_section * ret = (struct dvb_tot_section *)section; + +	if (len < sizeof(struct dvb_tot_section)) +		return NULL; + +	pos += 5; +	bswap16(buf + pos); +	pos += 2; + +	if ((pos + ret->descriptors_loop_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, ret->descriptors_loop_length)) +		return NULL; + +	pos += ret->descriptors_loop_length; + +	if (pos != len) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/tot_section.h b/lib/libucsi/dvb/tot_section.h new file mode 100644 index 0000000..3474da1 --- /dev/null +++ b/lib/libucsi/dvb/tot_section.h @@ -0,0 +1,97 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TOT_SECTION_H +#define _UCSI_DVB_TOT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> +#include <libucsi/dvb/types.h> + +/** + * dvb_tot_section structure. + */ +struct dvb_tot_section { +	struct section head; + +	dvbdate_t utc_time; +  EBIT2(uint16_t reserved		: 4; , +	uint16_t descriptors_loop_length:12; ); +  	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a dvb_tot_section. + * + * @param section Pointer to generic section structure. + * @return dvb_tot_section pointer, or NULL on error. + */ +struct dvb_tot_section * dvb_tot_section_codec(struct section *section); + +/** + * Iterator for descriptors field of dvb_tot_section. + * + * @param tot dvb_tot_section pointer. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define dvb_tot_section_descriptors_for_each(tot, pos) \ +	for ((pos) = dvb_tot_section_descriptors_first(tot); \ +	     (pos); \ +	     (pos) = dvb_tot_section_descriptors_next(tot, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	dvb_tot_section_descriptors_first(struct dvb_tot_section * tot) +{ +	if (tot->descriptors_loop_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) tot + sizeof(struct dvb_tot_section)); +} + +static inline struct descriptor * +	dvb_tot_section_descriptors_next(struct dvb_tot_section *tot, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t *) tot + sizeof(struct dvb_tot_section), +			       tot->descriptors_loop_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/transport_stream_descriptor.h b/lib/libucsi/dvb/transport_stream_descriptor.h new file mode 100644 index 0000000..1797ec5 --- /dev/null +++ b/lib/libucsi/dvb/transport_stream_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TRANSPORT_STREAM_DESCRIPTOR +#define _UCSI_DVB_TRANSPORT_STREAM_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_transport_stream_descriptor structure. + */ +struct dvb_transport_stream_descriptor { +	struct descriptor d; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process dvb_transport_stream_descriptor structure. + * + * @param d Pointer to generic descriptor. + * @return dvb_transport_stream_descriptor structure or NULL on error. + */ +static inline struct dvb_transport_stream_descriptor* +	dvb_transport_stream_descriptor_codec(struct descriptor* d) +{ +	return (struct dvb_transport_stream_descriptor*) d; +} + +/** + * Retrieve a pointer to the data field of a dvb_transport_stream_descriptor. + * + * @param d dvb_transport_stream_descriptor structure. + * @return Pointer to data field. + */ +static inline uint8_t * +	dvb_transport_stream_descriptor_data(struct dvb_transport_stream_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_transport_stream_descriptor); +} + +/** + * Calculate the length of the data field of a dvb_transport_stream_descriptor. + * + * @param d dvb_transport_stream_descriptor structure. + * @return length of data field in bytes. + */ +static inline int +	dvb_transport_stream_descriptor_data_length(struct dvb_transport_stream_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/tva_container_section.c b/lib/libucsi/dvb/tva_container_section.c new file mode 100644 index 0000000..f526efc --- /dev/null +++ b/lib/libucsi/dvb/tva_container_section.c @@ -0,0 +1,33 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/dvb/tva_container_section.h> + +struct dvb_tva_container_section *dvb_tva_container_section_codec(struct section_ext *ext) +{ +	size_t len = section_ext_length(ext); +	struct dvb_tva_container_section* ret = (struct dvb_tva_container_section*) ext; + +	if (len < sizeof(struct dvb_tva_container_section)) +		return NULL; + +	return ret; +} diff --git a/lib/libucsi/dvb/tva_container_section.h b/lib/libucsi/dvb/tva_container_section.h new file mode 100644 index 0000000..7d0abb1 --- /dev/null +++ b/lib/libucsi/dvb/tva_container_section.h @@ -0,0 +1,90 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TVA_CONTAINER_SECTION_H +#define _UCSI_DVB_TVA_CONTAINER_SECTION_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> +#include <libucsi/dvb/types.h> + +/** + * dvb_tva_container_section structure. + */ +struct dvb_tva_container_section { +	struct section_ext head; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process a dvb_tva_container_section. + * + * @param section Generic section header. + * @return dvb_tdt_section pointer, or NULL on error. + */ +struct dvb_tva_container_section *dvb_tva_container_section_codec(struct section_ext *ext); + +/** + * Accessor for the container_id field of a tva container section. + * + * @param container dvb_tva_container_section pointer. + * @return The container_id. + */ +static inline uint16_t dvb_tva_container_section_container_id(struct dvb_tva_container_section *container) +{ +	return container->head.table_id_ext; +} + +/** + * Accessor for the data field of a dvb_data_broadcast_id_descriptor. + * + * @param d dvb_data_broadcast_id_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +dvb_tva_container_section_data(struct dvb_tva_container_section *s) +{ +	return (uint8_t *) s + sizeof(struct dvb_tva_container_section); +} + +/** + * Determine the number of bytes in the data field of a dvb_tva_container_section. + * + * @param d dvb_tva_container_section pointer. + * @return Length of the field in bytes. + */ +static inline int +dvb_tva_container_section_data_length(struct dvb_tva_container_section *s) +{ +	return section_ext_length(&s->head) - sizeof(struct dvb_tva_container_section); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/tva_id_descriptor.h b/lib/libucsi/dvb/tva_id_descriptor.h new file mode 100644 index 0000000..3b4f3e8 --- /dev/null +++ b/lib/libucsi/dvb/tva_id_descriptor.h @@ -0,0 +1,124 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_TVA_ID_DESCRIPTOR +#define _UCSI_DVB_TVA_ID_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * dvb_tva_id_descriptor structure. + */ +struct dvb_tva_id_descriptor { +	struct descriptor d; + +	/* struct dvb_tva_id_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a dvb_tva_id_descriptor. + */ +struct dvb_tva_id_entry { +	uint16_t tva_id; +  EBIT2(uint8_t reserved		: 5; , +	uint8_t running_status		: 3; ); +} __ucsi_packed; + +/** + * Process a dvb_tva_id_descriptor. + * + * @param d Generic descriptor pointer. + * @return dvb_tva_id_descriptor pointer, or NULL on error. + */ +static inline struct dvb_tva_id_descriptor* +	dvb_tva_id_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 0; +	uint32_t len = d->len; +	uint8_t* buf = (uint8_t*) d + 2; + +	pos += sizeof(struct dvb_tva_id_descriptor) - 2; +	if (len % sizeof(struct dvb_tva_id_entry)) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos+=3; +	} + +	return (struct dvb_tva_id_descriptor*) d; +} + +/** + * Iterator for the entries field of a dvb_tva_id_descriptor. + * + * @param d dvb_tva_id_descriptor pointer. + * @param pos Variable containing a pointer to the current dvb_tva_id_entry. + */ +#define dvb_tva_id_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_tva_id_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_tva_id_descriptor_entries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_tva_id_entry* +	dvb_tva_id_descriptor_entries_first(struct dvb_tva_id_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_tva_id_entry *) +		((uint8_t*) d + sizeof(struct dvb_tva_id_descriptor)); +} + +static inline struct dvb_tva_id_entry* +	dvb_tva_id_descriptor_entries_next(struct dvb_tva_id_descriptor *d, +							     struct dvb_tva_id_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_tva_id_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_tva_id_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/types.c b/lib/libucsi/dvb/types.c new file mode 100644 index 0000000..c1cf583 --- /dev/null +++ b/lib/libucsi/dvb/types.c @@ -0,0 +1,270 @@ +/* + * section and descriptor parser + * + * 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 <string.h> +#include "types.h" + +time_t dvbdate_to_unixtime(dvbdate_t dvbdate) +{ +	int k = 0; +	struct tm tm; +	double mjd; + +	/* check for the undefined value */ +	if ((dvbdate[0] == 0xff) && +	    (dvbdate[1] == 0xff) && +	    (dvbdate[2] == 0xff) && +	    (dvbdate[3] == 0xff) && +	    (dvbdate[4] == 0xff)) { +		return -1; +	} + +	memset(&tm, 0, sizeof(tm)); +	mjd = (dvbdate[0] << 8) | dvbdate[1]; + +	tm.tm_year = (int) ((mjd - 15078.2) / 365.25); +	tm.tm_mon = (int) (((mjd - 14956.1) - (int) (tm.tm_year * 365.25)) / 30.6001); +	tm.tm_mday = (int) mjd - 14956 - (int) (tm.tm_year * 365.25) - (int) (tm.tm_mon * 30.6001); +	if ((tm.tm_mon == 14) || (tm.tm_mon == 15)) k = 1; +	tm.tm_year += k; +	tm.tm_mon = tm.tm_mon - 2 - k * 12; +	tm.tm_sec = bcd_to_integer(dvbdate[4]); +	tm.tm_min = bcd_to_integer(dvbdate[3]); +	tm.tm_hour = bcd_to_integer(dvbdate[2]); + +	return mktime(&tm); +} + +void unixtime_to_dvbdate(time_t unixtime, dvbdate_t dvbdate) +{ +	struct tm tm; +	double l = 0; +	int mjd; + +	/* the undefined value */ +	if (unixtime == -1) { +		memset(dvbdate, 0xff, 5); +		return; +	} + +	gmtime_r(&unixtime, &tm); +	tm.tm_mon++; +	if ((tm.tm_mon == 1) || (tm.tm_mon == 2)) l = 1; +	mjd = 14956 + tm.tm_mday + (int) ((tm.tm_year - l) * 365.25) + (int) ((tm.tm_mon + 1 + l * 12) * 30.6001); + +	dvbdate[0] = (mjd & 0xff00) >> 8; +	dvbdate[1] = mjd & 0xff; +	dvbdate[2] = integer_to_bcd(tm.tm_hour); +	dvbdate[3] = integer_to_bcd(tm.tm_min); +	dvbdate[4] = integer_to_bcd(tm.tm_sec); +} + +int dvbduration_to_seconds(dvbduration_t dvbduration) +{ +	int seconds = 0; + +	seconds += (bcd_to_integer(dvbduration[0]) * 60 * 60); +	seconds += (bcd_to_integer(dvbduration[1]) * 60); +	seconds += bcd_to_integer(dvbduration[2]); + +	return seconds; +} + +void seconds_to_dvbduration(int seconds, dvbduration_t dvbduration) +{ +	int hours, mins; + +	hours = seconds / (60*60); +	seconds -= (hours * 60 * 60); +	mins = seconds / 60; +	seconds -= (mins * 60); + +	dvbduration[0] = integer_to_bcd(hours); +	dvbduration[1] = integer_to_bcd(mins); +	dvbduration[2] = integer_to_bcd(seconds); +} + +int dvbhhmm_to_seconds(dvbhhmm_t dvbhhmm) +{ +	int seconds = 0; + +	seconds += (bcd_to_integer(dvbhhmm[0]) * 60 * 60); +	seconds += (bcd_to_integer(dvbhhmm[1]) * 60); + +	return seconds; +} + +void seconds_to_dvbhhmm(int seconds, dvbhhmm_t dvbhhmm) +{ +	int hours, mins; + +	hours = seconds / (60*60); +	seconds -= (hours * 60 * 60); +	mins = seconds / 60; + +	dvbhhmm[0] = integer_to_bcd(hours); +	dvbhhmm[1] = integer_to_bcd(mins); +} + +uint32_t integer_to_bcd(uint32_t intval) +{ +	uint32_t val = 0; + +	int i; +	for(i=0; i<=28;i+=4) { +		val |= ((intval % 10) << i); +		intval /= 10; +	} + +	return val; +} + +uint32_t bcd_to_integer(uint32_t bcdval) +{ +	uint32_t val = 0; + +	int i; +	for(i=28; i>=0;i-=4) { +		val += ((bcdval >> i) & 0x0f); +		if (i != 0) val *= 10; +	} + +	return val; +} + +const char *dvb_charset(char *dvb_text, int dvb_text_length, int *consumed) +{ +	char *charset = "ISO6937"; +	int used = 0; + +	if (dvb_text_length == 0) +		goto exit; +	if (dvb_text[0] >= 32) +		goto exit; +	if (dvb_text[0] == 0x10) { +		if (dvb_text_length < 3) +			goto exit; + +		used = 3; +		uint16_t ext = (dvb_text[1] << 8) | dvb_text[2]; +		switch(ext) { +		case 0x01: +			charset = "ISO8859-1"; +			break; +		case 0x02: +			charset = "ISO8859-2"; +			break; +		case 0x03: +			charset = "ISO8859-3"; +			break; +		case 0x04: +			charset = "ISO8859-4"; +			break; +		case 0x05: +			charset = "ISO8859-5"; +			break; +		case 0x06: +			charset = "ISO8859-6"; +			break; +		case 0x07: +			charset = "ISO8859-7"; +			break; +		case 0x08: +			charset = "ISO8859-8"; +			break; +		case 0x09: +			charset = "ISO8859-9"; +			break; +		case 0x0a: +			charset = "ISO8859-10"; +			break; +		case 0x0b: +			charset = "ISO8859-11"; +			break; +		case 0x0d: +			charset = "ISO8859-13"; +			break; +		case 0x0e: +			charset = "ISO8859-14"; +			break; +		case 0x0f: +			charset = "ISO8859-15"; +			break; +		default: +			used = 0; +			break; +		} +	} else { +		used = 1; +		switch(dvb_text[0]) { +		case 0x01: +			charset = "ISO8859-5"; +			break; +		case 0x02: +			charset = "ISO8859-6"; +			break; +		case 0x03: +			charset = "ISO8859-7"; +			break; +		case 0x04: +			charset = "ISO8859-8"; +			break; +		case 0x05: +			charset = "ISO8859-9"; +			break; +		case 0x06: +			charset = "ISO8859-10"; +			break; +		case 0x07: +			charset = "ISO8859-11"; +			break; +		case 0x09: +			charset = "ISO8859-13"; +			break; +		case 0x0a: +			charset = "ISO8859-14"; +			break; +		case 0x0b: +			charset = "ISO8859-15"; +			break; +		case 0x11: +			charset = "UTF16"; +			break; +		case 0x12: +			charset = "EUC-KR"; +			break; +		case 0x13: +			charset = "GB2312"; +			break; +		case 0x14: +			charset = "GBK"; +			break; +		case 0x15: +			charset = "UTF8"; +			break; +		default: +			used = 0; +			break; +		} +	} +exit: +	*consumed = used; +	return charset; +} diff --git a/lib/libucsi/dvb/types.h b/lib/libucsi/dvb/types.h new file mode 100644 index 0000000..437c7c3 --- /dev/null +++ b/lib/libucsi/dvb/types.h @@ -0,0 +1,127 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_DVB_TYPES_H +#define _UCSI_DVB_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <time.h> + +typedef uint8_t dvbdate_t[5]; +typedef uint8_t dvbduration_t[3]; +typedef uint8_t dvbhhmm_t[2]; + +/** + * Running status values. + */ +enum { +	DVB_RUNNING_STATUS_NOT_RUNNING			= 0x01, +	DVB_RUNNING_STATUS_FEW_SECONDS			= 0x02, +	DVB_RUNNING_STATUS_PAUSING			= 0x03, +	DVB_RUNNING_STATUS_RUNNING			= 0x04, +}; + +/** + * Convert from a 5 byte DVB UTC date to unix time. + * Note: this functions expects the DVB date in network byte order. + * + * @param d Pointer to DVB date. + * @return The unix timestamp, or -1 if the dvbdate was set to the 'undefined' value + */ +extern time_t dvbdate_to_unixtime(dvbdate_t dvbdate); + +/** + * Convert from a unix timestemp to a 5 byte DVB UTC date. + * Note: this function will always output the DVB date in + * network byte order. + * + * @param unixtime The unix timestamp, or -1 for the 'undefined' value. + * @param utc Pointer to 5 byte DVB date. + */ +extern void unixtime_to_dvbdate(time_t unixtime, dvbdate_t dvbdate); + +/** + * Convert from a DVB BCD duration to a number of seconds. + * + * @param dvbduration Pointer to 3 byte DVB duration. + * @return Number of seconds. + */ +extern int dvbduration_to_seconds(dvbduration_t dvbduration); + +/** + * Convert from a number of seconds to a DVB 3 byte BCD duration. + * + * @param seconds The number of seconds. + * @param dvbduration Pointer to 3 byte DVB duration. + */ +extern void seconds_to_dvbduration(int seconds, dvbduration_t dvbduration); + +/** + * Convert from a DVB BCD HHMM to a number of seconds. + * + * @param dvbduration Pointer to 2 byte DVB HHMM. + * @return Number of seconds. + */ +extern int dvbhhmm_to_seconds(dvbhhmm_t dvbhhmm); + +/** + * Convert from a number of seconds to a DVB 2 byte BCD HHMM. + * + * @param seconds The number of seconds. + * @param dvbduration Pointer to 2 byte DVB HHMM. + */ +extern void seconds_to_dvbhhmm(int seconds, dvbhhmm_t dvbhhmm); + +/** + * Convert a __ucsi_packed BCD value into a normal integer. + * + * @param bcd The value to convert. + * @return The value. + */ +extern uint32_t bcd_to_integer(uint32_t bcd); + +/** + * Convert a normal integer into a __ucsi_packed BCD value. + * + * @param integer The value to convert. + * @return The value. + */ +extern uint32_t integer_to_bcd(uint32_t integer); + +/** + * Determine the (iconv compatable) character set of a dvb string. + * + * @param dvb_text DVB text concerned. + * @param dvb_text_length Length of text. + * @param consumed Out parameter of number of bytes used to encode the character set. + * @return Name of the character set. + */ +extern const char *dvb_charset(char *dvb_text, int dvb_text_length, int *consumed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/vbi_data_descriptor.h b/lib/libucsi/dvb/vbi_data_descriptor.h new file mode 100644 index 0000000..b1d8703 --- /dev/null +++ b/lib/libucsi/dvb/vbi_data_descriptor.h @@ -0,0 +1,186 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_VBI_DATA_DESCRIPTOR +#define _UCSI_DVB_VBI_DATA_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for the data_service_id field. + */ +enum { +	DVB_VBI_DATA_SERVICE_ID_EBU		= 0x01, +	DVB_VBI_DATA_SERVICE_ID_INVERTED	= 0x02, +	DVB_VBI_DATA_SERVICE_ID_VPS		= 0x04, +	DVB_VBI_DATA_SERVICE_ID_WSS		= 0x05, +	DVB_VBI_DATA_SERVICE_ID_CC		= 0x06, +	DVB_VBI_DATA_SERVICE_ID_MONO_422	= 0x07, +}; + +/** + * dvb_vbi_data_descriptor structure + */ +struct dvb_vbi_data_descriptor { +	struct descriptor d; + +	/* struct dvb_vbi_data_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the dvb_vbi_data_descriptor entries field. + */ +struct dvb_vbi_data_entry { +	uint8_t data_service_id; +	uint8_t data_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Format of the dvb_vbi_data_entry data field, if data_service_id == 1,2,4,5,6,7. + */ +struct dvb_vbi_data_x { +  EBIT3(uint8_t reserved 	: 2; , +	uint8_t field_parity 	: 1; , +	uint8_t line_offset	: 5; ); +} __ucsi_packed; + +/** + * Process a dvb_vbi_data_descriptor. + * + * @param d Generic descriptor structure. + * @return dvb_vbi_data_descriptor pointer, or NULL on error. + */ +static inline struct dvb_vbi_data_descriptor* +	dvb_vbi_data_descriptor_codec(struct descriptor* d) +{ +	uint8_t* p = (uint8_t*) d + 2; +	uint32_t pos = 0; +	uint32_t len = d->len; + +	while(pos < len) { +		struct dvb_vbi_data_entry *e = +			(struct dvb_vbi_data_entry*) (p+pos); + +		pos += sizeof(struct dvb_vbi_data_entry); + +		if (pos > len) +			return NULL; + +		pos += e->data_length; + +		if (pos > len) +			return NULL; +	} + +	return (struct dvb_vbi_data_descriptor*) d; +} + +/** + * Iterator for entries field in a dvb_vbi_data_descriptor structure. + * + * @param d Pointer to dvb_vbi_data_descriptor structure. + * @param pos Variable holding pointer to the current dvb_vbi_data_entry structure. + */ +#define dvb_vbi_data_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_vbi_data_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_vbi_data_descriptor_entries_next(d, pos)) + +/** + * Get a pointer to the data field of a dvb_vbi_data_entry. + * + * @param d dvb_vbi_data_entry structure. + * @return Pointer to the data field. + */ +static inline uint8_t * +	dvb_vbi_data_entry_data(struct dvb_vbi_data_entry *d) +{ +	return (uint8_t *) d + sizeof(struct dvb_vbi_data_entry); +} + +/** + * Get a pointer to the data field of a dvb_vbi_data_x for id 1,2,4,5,6,7. + * + * @param d dvb_vbi_data_entry structure. + * @return Pointer to the data field, or NULL if invalid + */ +static inline struct dvb_vbi_data_x* +	dvb_vbi_data_entry_data_x(struct dvb_vbi_data_entry *d) +{ +	switch(d->data_service_id) { +	case 1: +	case 2: +	case 4: +	case 5: +	case 6: +	case 7: +		return (struct dvb_vbi_data_x*) ((uint8_t *) d + sizeof(struct dvb_vbi_data_entry)); +	} + +	return NULL; +} + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_vbi_data_entry* +	dvb_vbi_data_descriptor_entries_first(struct dvb_vbi_data_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_vbi_data_entry *) +		((uint8_t*) d + sizeof(struct dvb_vbi_data_descriptor)); +} + +static inline struct dvb_vbi_data_entry* +	dvb_vbi_data_descriptor_entries_next(struct dvb_vbi_data_descriptor *d, +					     struct dvb_vbi_data_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_vbi_data_entry) + +			pos->data_length; + +	if (next >= end) +		return NULL; + +	return (struct dvb_vbi_data_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/dvb/vbi_teletext_descriptor.h b/lib/libucsi/dvb/vbi_teletext_descriptor.h new file mode 100644 index 0000000..fd779d7 --- /dev/null +++ b/lib/libucsi/dvb/vbi_teletext_descriptor.h @@ -0,0 +1,116 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_DVB_VBI_TELETEXT_DESCRIPTOR +#define _UCSI_DVB_VBI_TELETEXT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * dvb_vbi_teletext_descriptor structure + */ +struct dvb_vbi_teletext_descriptor { +	struct descriptor d; + +	/* struct dvb_vbi_teletext_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in a dvb_vbi_teletext_descriptor structure. + */ +struct dvb_vbi_teletext_entry { +	iso639lang_t language_code; +  EBIT2(uint8_t type		: 5; , +	uint8_t magazine_number: 3;  ); +	uint8_t page_number; +} __ucsi_packed; + +/** + * Process an dvb_vbi_teletext_descriptor. + * + * @param d Generic descriptor. + * @return dvb_vbi_teletext_descriptor pointer, or NULL on error. + */ +static inline struct dvb_vbi_teletext_descriptor* +	dvb_vbi_teletext_descriptor_codec(struct descriptor* d) +{ +	if (d->len % sizeof(struct dvb_vbi_teletext_entry)) +		return NULL; + +	return (struct dvb_vbi_teletext_descriptor*) d; +} + +/** + * Iterator for entries field of a dvb_vbi_teletext_descriptor. + * + * @param d Pointer to dvb_vbi_teletext_descriptor. + * @param pos Variable holding a pointer to the current dvb_vbi_teletext_entry. + */ +#define dvb_vbi_teletext_descriptor_entries_for_each(d, pos) \ +	for ((pos) = dvb_vbi_teletext_descriptor_entries_first(d); \ +	     (pos); \ +	     (pos) = dvb_vbi_teletext_descriptor_entries_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct dvb_vbi_teletext_entry* +	dvb_vbi_teletext_descriptor_entries_first(struct dvb_vbi_teletext_descriptor *d) +{ +	if (d->d.len == 0) +		return NULL; + +	return (struct dvb_vbi_teletext_entry *) +		((uint8_t*) d +	sizeof(struct dvb_vbi_teletext_descriptor)); +} + +static inline struct dvb_vbi_teletext_entry* +	dvb_vbi_teletext_descriptor_entries_next(struct dvb_vbi_teletext_descriptor *d, +					         struct dvb_vbi_teletext_entry *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct dvb_vbi_teletext_entry); + +	if (next >= end) +		return NULL; + +	return (struct dvb_vbi_teletext_entry *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/endianops.h b/lib/libucsi/endianops.h new file mode 100644 index 0000000..23b418b --- /dev/null +++ b/lib/libucsi/endianops.h @@ -0,0 +1,128 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_COMMON_H +#define _UCSI_COMMON_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <byteswap.h> +#include <endian.h> + +#define __ucsi_packed __attribute__((packed)) + + + + +#if __BYTE_ORDER == __BIG_ENDIAN +#define EBIT2(x1,x2) x1 x2 +#define EBIT3(x1,x2,x3) x1 x2 x3 +#define EBIT4(x1,x2,x3,x4) x1 x2 x3 x4 +#define EBIT5(x1,x2,x3,x4,x5) x1 x2 x3 x4 x5 +#define EBIT6(x1,x2,x3,x4,x5,x6) x1 x2 x3 x4 x5 x6 +#define EBIT7(x1,x2,x3,x4,x5,x6,x7) x1 x2 x3 x4 x5 x6 x7 +#define EBIT8(x1,x2,x3,x4,x5,x6,x7,x8) x1 x2 x3 x4 x5 x6 x7 x8 + +static inline void bswap16(uint8_t *buf) { +	(void) buf; +} + +static inline void bswap32(uint8_t *buf) { +	(void) buf; +} + +static inline void bswap64(uint8_t *buf) { +	(void) buf; +} + +static inline void bswap24(uint8_t *buf) { +	(void) buf; +} + +static inline void bswap40(uint8_t *buf) { +	(void) buf; +} + +static inline void bswap48(uint8_t *buf) { +	(void) buf; +} + +#else +#define EBIT2(x1,x2) x2 x1 +#define EBIT3(x1,x2,x3) x3 x2 x1 +#define EBIT4(x1,x2,x3,x4) x4 x3 x2 x1 +#define EBIT5(x1,x2,x3,x4,x5) x5 x4 x3 x2 x1 +#define EBIT6(x1,x2,x3,x4,x5,x6) x6 x5 x4 x3 x2 x1 +#define EBIT7(x1,x2,x3,x4,x5,x6,x7) x7 x6 x5 x4 x3 x2 x1 +#define EBIT8(x1,x2,x3,x4,x5,x6,x7,x8) x8 x7 x6 x5 x4 x3 x2 x1 + +static inline void bswap16(uint8_t * buf) { +	*((uint16_t*)buf) = bswap_16((*(uint16_t*)buf)); +} + +static inline void bswap32(uint8_t * buf) { +	*((uint32_t*)buf) = bswap_32((*(uint32_t*)buf)); +} + +static inline void bswap64(uint8_t * buf) { +	*((uint64_t*)buf) = bswap_64((*(uint64_t*)buf)); +} + +static inline void bswap24(uint8_t * buf) { +	uint8_t tmp0 = buf[0]; + +	buf[0] = buf[2]; +	buf[2] = tmp0; +} + +static inline void bswap40(uint8_t * buf) { +	uint8_t tmp0 = buf[0]; +	uint8_t tmp1 = buf[1]; + +	buf[0] = buf[4]; +	buf[1] = buf[3]; +	buf[3] = tmp1; +	buf[4] = tmp0; +} + +static inline void bswap48(uint8_t * buf) { +	uint8_t tmp0 = buf[0]; +	uint8_t tmp1 = buf[1]; +	uint8_t tmp2 = buf[2]; + +	buf[0] = buf[5]; +	buf[1] = buf[4]; +	buf[2] = buf[3]; +	buf[3] = tmp2; +	buf[4] = tmp1; +	buf[5] = tmp0; +} + +#endif // __BYTE_ORDER + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/Makefile b/lib/libucsi/mpeg/Makefile new file mode 100644 index 0000000..ace8808 --- /dev/null +++ b/lib/libucsi/mpeg/Makefile @@ -0,0 +1,65 @@ +# Makefile for linuxtv.org dvb-apps/lib/libucsi/mpeg + +.PHONY: sub-error-mpeg + +sub-error-mpeg: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += mpeg/cat_section.o      \ +           mpeg/metadata_section.o \ +           mpeg/odsmt_section.o    \ +           mpeg/pat_section.o      \ +           mpeg/pmt_section.o      \ +           mpeg/tsdt_section.o + +sub-install += mpeg + +else + +includes = audio_stream_descriptor.h                 \ +           ca_descriptor.h                           \ +           cat_section.h                             \ +           content_labelling_descriptor.h            \ +           copyright_descriptor.h                    \ +           data_stream_alignment_descriptor.h        \ +           descriptor.h                              \ +           external_es_id_descriptor.h               \ +           fmc_descriptor.h                          \ +           fmxbuffer_size_descriptor.h               \ +           hierarchy_descriptor.h                    \ +           ibp_descriptor.h                          \ +           iod_descriptor.h                          \ +           iso_639_language_descriptor.h             \ +           maximum_bitrate_descriptor.h              \ +           metadata_descriptor.h                     \ +           metadata_pointer_descriptor.h             \ +           metadata_section.h                        \ +           metadata_std_descriptor.h                 \ +           mpeg4_audio_descriptor.h                  \ +           mpeg4_video_descriptor.h                  \ +           multiplex_buffer_descriptor.h             \ +           multiplex_buffer_utilization_descriptor.h \ +           muxcode_descriptor.h                      \ +           odsmt_section.h                           \ +           pat_section.h                             \ +           pmt_section.h                             \ +           private_data_indicator_descriptor.h       \ +           registration_descriptor.h                 \ +           section.h                                 \ +           sl_descriptor.h                           \ +           smoothing_buffer_descriptor.h             \ +           std_descriptor.h                          \ +           system_clock_descriptor.h                 \ +           target_background_grid_descriptor.h       \ +           tsdt_section.h                            \ +           types.h                                   \ +           video_stream_descriptor.h                 \ +           video_window_descriptor.h + +include ../../../Make.rules + +lib_name = libucsi/mpeg + +endif diff --git a/lib/libucsi/mpeg/audio_stream_descriptor.h b/lib/libucsi/mpeg/audio_stream_descriptor.h new file mode 100644 index 0000000..7e6ea07 --- /dev/null +++ b/lib/libucsi/mpeg/audio_stream_descriptor.h @@ -0,0 +1,65 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_AUDIO_STREAM_DESCRIPTOR +#define _UCSI_MPEG_AUDIO_STREAM_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_audio_stream_descriptor structure + */ +struct mpeg_audio_stream_descriptor { +	struct descriptor d; + +  EBIT5(uint8_t free_format_flag		: 1; , +	uint8_t id				: 1; , +	uint8_t layer				: 2; , +	uint8_t variable_rate_audio_indicator	: 1; , +	uint8_t reserved			: 3; ); +} __ucsi_packed; + +/** + * Process an mpeg_audio_stream_descriptor. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_audio_stream_descriptor structure, or NULL on error. + */ +static inline struct mpeg_audio_stream_descriptor* +	mpeg_audio_stream_descriptor_codec(struct descriptor *d) +{ +	if (d->len != (sizeof(struct mpeg_audio_stream_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_audio_stream_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/ca_descriptor.h b/lib/libucsi/mpeg/ca_descriptor.h new file mode 100644 index 0000000..88a65dd --- /dev/null +++ b/lib/libucsi/mpeg/ca_descriptor.h @@ -0,0 +1,91 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_CA_DESCRIPTOR +#define _UCSI_MPEG_CA_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_ca_descriptor structure + */ +struct mpeg_ca_descriptor { +	struct descriptor d; + +	uint16_t ca_system_id; +  EBIT2(uint16_t reserved	: 3;  , +	uint16_t ca_pid		: 13; ); +	/* uint8_t  data[] */ +} __ucsi_packed; + +/** + * Process an mpeg_ca_descriptor. + * + * @param d Generic descriptor. + * @return Pointer to an mpeg_ca_descriptor, or NULL on error. + */ +static inline struct mpeg_ca_descriptor* +	mpeg_ca_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct mpeg_ca_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 4); + +	return (struct mpeg_ca_descriptor*) d; +} + +/** + * Accessor for pointer to data field of an mpeg_ca_descriptor. + * + * @param d The mpeg_ca_descriptor structure. + * @return Pointer to the field. + */ +static inline uint8_t * +	mpeg_ca_descriptor_data(struct mpeg_ca_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_ca_descriptor); +} + +/** + * Determine length of data field of an mpeg_ca_descriptor. + * + * @param d The mpeg_ca_descriptor structure. + * @return Length of the field in bytes. + */ +static inline int +	mpeg_ca_descriptor_data_length(struct mpeg_ca_descriptor *d) +{ +	return d->d.len - 4; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/cat_section.c b/lib/libucsi/mpeg/cat_section.c new file mode 100644 index 0000000..8c974b8 --- /dev/null +++ b/lib/libucsi/mpeg/cat_section.c @@ -0,0 +1,34 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/cat_section.h> + +struct mpeg_cat_section * mpeg_cat_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *)ext; +	size_t pos = sizeof(struct section_ext); + +	if (verify_descriptors(buf + pos, +	    		       section_ext_length(ext) - sizeof(struct mpeg_cat_section))) +		return NULL; + +	return (struct mpeg_cat_section *)ext; +} diff --git a/lib/libucsi/mpeg/cat_section.h b/lib/libucsi/mpeg/cat_section.h new file mode 100644 index 0000000..7ed34a3 --- /dev/null +++ b/lib/libucsi/mpeg/cat_section.h @@ -0,0 +1,94 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_CAT_SECTION_H +#define _UCSI_MPEG_CAT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_cat_section structure. + */ +struct mpeg_cat_section { +	struct section_ext head; + +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process an mpeg_cat_section. + * + * @param section The generic section_ext structure. + * @return Pointer to an mpeg_cat_section structure, or NULL on error. + */ +extern struct mpeg_cat_section *mpeg_cat_section_codec(struct section_ext *section); + +/** + * Convenience iterator for descriptors field of an mpeg_cat_section. + * + * @param cat The mpeg_cat_section pointer. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define mpeg_cat_section_descriptors_for_each(cat, pos) \ +	for ((pos) = mpeg_cat_section_descriptors_first(cat); \ +	     (pos); \ +	     (pos) = mpeg_cat_section_descriptors_next(cat, pos)) + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	mpeg_cat_section_descriptors_first(struct mpeg_cat_section *cat) +{ +	size_t pos = sizeof(struct mpeg_cat_section); + +	if (pos >= section_ext_length(&cat->head)) +		return NULL; + +	return (struct descriptor*)((uint8_t *) cat + pos); +} + + +static inline struct descriptor * +	mpeg_cat_section_descriptors_next(struct mpeg_cat_section *cat, +					  struct descriptor* pos) +{ +	return next_descriptor((uint8_t *) cat + sizeof(struct mpeg_cat_section), +			       section_ext_length(&cat->head) - sizeof(struct mpeg_cat_section), +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/content_labelling_descriptor.h b/lib/libucsi/mpeg/content_labelling_descriptor.h new file mode 100644 index 0000000..06738ab --- /dev/null +++ b/lib/libucsi/mpeg/content_labelling_descriptor.h @@ -0,0 +1,356 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_CONTENT_LABELLING_DESCRIPTOR +#define _UCSI_MPEG_CONTENT_LABELLING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for content_time_base_indicator. + */ +enum { +	MPEG_CONTENT_TIME_BASE_STC			= 0x01, +	MPEG_CONTENT_TIME_BASE_NPT			= 0x02, +}; + +/** + * mpeg_content_labelling_descriptor structure. + */ +struct mpeg_content_labelling_descriptor { +	struct descriptor d; + +	uint16_t metadata_application_format; +	/* struct mpeg_content_labelling_descriptor_application_format_identifier id */ +	/* struct mpeg_content_labelling_descriptor_flags flags */ +	/* struct mpeg_content_labelling_descriptor_reference_id reference_id */ +	/* struct mpeg_content_labelling_descriptor_time_base time_base */ +	/* struct mpeg_content_labelling_descriptor_content_id content_id */ +	/* struct mpeg_content_labelling_descriptor_time_base_association time_base_assoc */ +	/* uint8_t private_data[] */ +} __ucsi_packed; + +/** + * id field of a content_labelling_descriptor. + */ +struct mpeg_content_labelling_descriptor_application_format_identifier { +	uint32_t id; +} __ucsi_packed; + +/** + * Flags field of a content_labelling_descriptor + */ +struct mpeg_content_labelling_descriptor_flags { +  EBIT3(uint8_t content_reference_id_record_flag		: 1;  , +	uint8_t content_time_base_indicator			: 4;  , +	uint8_t reserved					: 3;  ); +} __ucsi_packed; + +/** + * Reference_id field of a content_labelling_descriptor. + */ +struct mpeg_content_labelling_descriptor_reference_id { +	uint8_t content_reference_id_record_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * time_base field of a content_labelling_descriptor. + */ +struct mpeg_content_labelling_descriptor_time_base { +  EBIT2(uint64_t reserved_1					: 7;  , +	uint64_t content_time_base_value			:33;  ); +  EBIT2(uint64_t reserved_2					: 7;  , +	uint64_t metadata_time_base_value			:33;  ); +} __ucsi_packed; + +/** + * content_id field of a content_labelling_descriptor. + */ +struct mpeg_content_labelling_descriptor_content_id { +  EBIT2(uint8_t reserved					: 1;  , +	uint8_t contentId					: 7;  ); +} __ucsi_packed; + +/** + * time_base_assoc field of a content_labelling_descriptor. + */ +struct mpeg_content_labelling_descriptor_time_base_association { +	uint8_t time_base_association_data_length; +	/* uint8_t data[] */ +} __ucsi_packed; + + + +/** + * Process an mpeg_content_labelling_descriptor. + * + * @param d Generic descriptor. + * @return Pointer to an mpeg_content_labelling_descriptor, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor* +	mpeg_content_labelling_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 2; +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len + 2; +	struct mpeg_content_labelling_descriptor_flags *flags; +	int id; + +	if (len < sizeof(struct mpeg_content_labelling_descriptor)) +		return NULL; + +	bswap16(buf + pos); +	id = *((uint16_t*) (buf+pos)); +	pos += 2; + +	if (id == 0xffff) { +		if (len < (pos+4)) +			return NULL; +		bswap32(buf+pos); +		pos += 4; +	} + +	if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_flags))) +		return NULL; +	flags = (struct mpeg_content_labelling_descriptor_flags*) (buf+pos); +	pos += sizeof(struct mpeg_content_labelling_descriptor_flags); + +	if (flags->content_reference_id_record_flag == 1) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if ((flags->content_time_base_indicator == 1) || +	    (flags->content_time_base_indicator == 2)) { +		if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_time_base))) +			return NULL; +		bswap40(buf+pos); +		bswap40(buf+pos+5); +		pos += sizeof(struct mpeg_content_labelling_descriptor_time_base); +	} + +	if (flags->content_time_base_indicator == 2) { +		if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_content_id))) +			return NULL; +		pos += sizeof(struct mpeg_content_labelling_descriptor_content_id); +	} + +	if (flags->content_time_base_indicator > 2) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (len < pos) +		return NULL; + +	return (struct mpeg_content_labelling_descriptor*) d; +} + +/** + * Accessor for pointer to id field of an mpeg_content_labelling_descriptor. + * + * @param d The mpeg_content_labelling_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_application_format_identifier* +	mpeg_content_labelling_descriptor_id(struct mpeg_content_labelling_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d; + +	if (d->metadata_application_format != 0xffff) +		return NULL; +	return (struct mpeg_content_labelling_descriptor_application_format_identifier*) +		(buf + sizeof(struct mpeg_content_labelling_descriptor)); +} + +/** + * Accessor for pointer to flags field of an mpeg_content_labelling_descriptor. + * + * @param d The mpeg_content_labelling_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_flags* +        mpeg_content_labelling_descriptor_flags(struct mpeg_content_labelling_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor); + +	if (d->metadata_application_format != 0xffff) +		buf += 4; + +	return (struct mpeg_content_labelling_descriptor_flags *) buf; +} + +/** + * Accessor for reference_id field of an mpeg_content_labelling_descriptor. + * + * @param flags Pointer to the mpeg_content_labelling_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_reference_id* +	mpeg_content_labelling_descriptor_reference_id(struct mpeg_content_labelling_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags); + +	if (flags->content_reference_id_record_flag != 1) +		return NULL; + +	return (struct mpeg_content_labelling_descriptor_reference_id *) buf; +} + +/** + * Accessor for data field of an mpeg_content_reference_id. + * + * @param d The mpeg_content_reference_id structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_content_reference_id_data(struct mpeg_content_labelling_descriptor_reference_id *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor_reference_id); +} + +/** + * Accessor for time_base field of an mpeg_content_labelling_descriptor. + * + * @param flags Pointer to the mpeg_content_labelling_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_time_base* +	mpeg_content_labelling_descriptor_time_base(struct mpeg_content_labelling_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags); + +	if ((flags->content_time_base_indicator!=1) && (flags->content_time_base_indicator!=2)) +		return NULL; + +	if (flags->content_reference_id_record_flag == 1) +		buf += 1 + buf[1]; + +	return (struct mpeg_content_labelling_descriptor_time_base *) buf; +} + +/** + * Accessor for content_id field of an mpeg_content_labelling_descriptor. + * + * @param flags Pointer to the mpeg_content_labelling_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_content_id* +	mpeg_content_labelling_descriptor_content_id(struct mpeg_content_labelling_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags); + +	if (flags->content_time_base_indicator!=2) +		return NULL; + +	if (flags->content_reference_id_record_flag == 1) +		buf += 1 + buf[1]; +	if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2)) +		buf += sizeof(struct mpeg_content_labelling_descriptor_time_base); + +	return (struct mpeg_content_labelling_descriptor_content_id *) buf; +} + +/** + * Accessor for time_base_association field of an mpeg_content_labelling_descriptor. + * + * @param flags Pointer to the mpeg_content_labelling_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_content_labelling_descriptor_time_base_association* +	mpeg_content_labelling_descriptor_time_base_assoc(struct mpeg_content_labelling_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags); + +	if (flags->content_time_base_indicator<3) +		return NULL; + +	if (flags->content_reference_id_record_flag == 1) +		buf += 1 + buf[1]; +	if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2)) +		buf += sizeof(struct mpeg_content_labelling_descriptor_time_base); +	if (flags->content_time_base_indicator==2) +		buf += sizeof(struct mpeg_content_labelling_descriptor_content_id); + +	return (struct mpeg_content_labelling_descriptor_time_base_association *) buf; +} + +/** + * Accessor for data field of an mpeg_time_base_association. + * + * @param d The mpeg_time_base_association structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_time_base_association_data(struct mpeg_content_labelling_descriptor_time_base_association *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor_time_base_association); +} + + +/** + * Accessor for private_data field of an mpeg_content_labelling_descriptor. + * + * @param d The mpeg_content_labelling_descriptor structure. + * @param flags Pointer to the mpeg_content_labelling_descriptor_flags. + * @param length Where the number of bytes in the field should be stored. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_content_labelling_descriptor_data(struct mpeg_content_labelling_descriptor *d, +					       struct mpeg_content_labelling_descriptor_flags *flags, +					       int *length) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags); +	uint8_t *end = (uint8_t*) d + d->d.len + 2; + +	if (flags->content_reference_id_record_flag == 1) +		buf += 1 + buf[1]; +	if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2)) +		buf += sizeof(struct mpeg_content_labelling_descriptor_time_base); +	if (flags->content_time_base_indicator==2) +		buf += sizeof(struct mpeg_content_labelling_descriptor_content_id); +	if (flags->content_time_base_indicator<3) +		buf += 1 + buf[1]; + +	*length = end - buf; + +	return buf; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/copyright_descriptor.h b/lib/libucsi/mpeg/copyright_descriptor.h new file mode 100644 index 0000000..5991fe9 --- /dev/null +++ b/lib/libucsi/mpeg/copyright_descriptor.h @@ -0,0 +1,89 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_COPYRIGHT_DESCRIPTOR +#define _UCSI_MPEG_COPYRIGHT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_copyright_descriptor structure. + */ +struct mpeg_copyright_descriptor { +	struct descriptor d; + +	uint32_t copyright_identifier; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process an mpeg_copyright_descriptor. + * + * @param d Generic descriptor. + * @return mpeg_copyright_descriptor pointer, or NULL on error. + */ +static inline struct mpeg_copyright_descriptor* +	mpeg_copyright_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct mpeg_copyright_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct mpeg_copyright_descriptor*) d; +} + +/** + * Retrieve pointer to data field of an mpeg_copyright_descriptor. + * + * @param d mpeg_copyright_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	mpeg_copyright_descriptor_data(struct mpeg_copyright_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_copyright_descriptor); +} + + +/** + * Determine length of the data field of an mpeg_copyright_descriptor. + * + * @param d mpeg_copyright_descriptor pointer. + * @return Length of field in bytes. + */ +static inline int +	mpeg_copyright_descriptor_data_length(struct mpeg_copyright_descriptor *d) +{ +	return d->d.len - 4; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/data_stream_alignment_descriptor.h b/lib/libucsi/mpeg/data_stream_alignment_descriptor.h new file mode 100644 index 0000000..887495f --- /dev/null +++ b/lib/libucsi/mpeg/data_stream_alignment_descriptor.h @@ -0,0 +1,73 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_DATA_STREAM_ALIGNMENT_DESCRIPTOR +#define _UCSI_MPEG_DATA_STREAM_ALIGNMENT_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for alignment_type. + */ +enum { +	MPEG_DATA_STREAM_ALIGNMENT_VIDEO_SLICE_OR_AU		= 0x01, +	MPEG_DATA_STREAM_ALIGNMENT_VIDEO_AU			= 0x02, +	MPEG_DATA_STREAM_ALIGNMENT_VIDEO_GOP_OR_SEQ		= 0x03, +	MPEG_DATA_STREAM_ALIGNMENT_VIDEO_SEQ			= 0x04, + +	MPEG_DATA_STREAM_ALIGNMENT_AUDIO_SYNC_WORD		= 0x01, +}; + +/** + * mpeg_data_stream_alignment_descriptor structure. + */ +struct mpeg_data_stream_alignment_descriptor { +	struct descriptor d; + +	uint8_t alignment_type; +} __ucsi_packed; + +/** + * Process an mpeg_data_stream_alignment_descriptor. + * + * @param d Pointer to generic descriptor structure. + * @return Pointer to mpeg_data_stream_alignment_descriptor, or NULL on error. + */ +static inline struct mpeg_data_stream_alignment_descriptor* +	mpeg_data_stream_alignment_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_data_stream_alignment_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_data_stream_alignment_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/descriptor.h b/lib/libucsi/mpeg/descriptor.h new file mode 100644 index 0000000..c32775f --- /dev/null +++ b/lib/libucsi/mpeg/descriptor.h @@ -0,0 +1,102 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_DESCRIPTOR_H +#define _UCSI_MPEG_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/mpeg/mpeg4_audio_descriptor.h> +#include <libucsi/mpeg/mpeg4_video_descriptor.h> +#include <libucsi/mpeg/audio_stream_descriptor.h> +#include <libucsi/mpeg/ca_descriptor.h> +#include <libucsi/mpeg/content_labelling_descriptor.h> +#include <libucsi/mpeg/copyright_descriptor.h> +#include <libucsi/mpeg/data_stream_alignment_descriptor.h> +#include <libucsi/mpeg/external_es_id_descriptor.h> +#include <libucsi/mpeg/fmc_descriptor.h> +#include <libucsi/mpeg/fmxbuffer_size_descriptor.h> +#include <libucsi/mpeg/hierarchy_descriptor.h> +#include <libucsi/mpeg/ibp_descriptor.h> +#include <libucsi/mpeg/iod_descriptor.h> +#include <libucsi/mpeg/iso_639_language_descriptor.h> +#include <libucsi/mpeg/maximum_bitrate_descriptor.h> +#include <libucsi/mpeg/metadata_descriptor.h> +#include <libucsi/mpeg/metadata_pointer_descriptor.h> +#include <libucsi/mpeg/metadata_std_descriptor.h> +#include <libucsi/mpeg/multiplex_buffer_descriptor.h> +#include <libucsi/mpeg/multiplex_buffer_utilization_descriptor.h> +#include <libucsi/mpeg/muxcode_descriptor.h> +#include <libucsi/mpeg/private_data_indicator_descriptor.h> +#include <libucsi/mpeg/registration_descriptor.h> +#include <libucsi/mpeg/sl_descriptor.h> +#include <libucsi/mpeg/smoothing_buffer_descriptor.h> +#include <libucsi/mpeg/std_descriptor.h> +#include <libucsi/mpeg/system_clock_descriptor.h> +#include <libucsi/mpeg/target_background_grid_descriptor.h> +#include <libucsi/mpeg/video_stream_descriptor.h> +#include <libucsi/mpeg/video_window_descriptor.h> +#include <libucsi/endianops.h> + +/** + * Enumeration of MPEG descriptor tags. + */ +enum mpeg_descriptor_tag { +	dtag_mpeg_video_stream			= 0x02, +	dtag_mpeg_audio_stream			= 0x03, +	dtag_mpeg_hierarchy			= 0x04, +	dtag_mpeg_registration			= 0x05, +	dtag_mpeg_data_stream_alignment		= 0x06, +	dtag_mpeg_target_background_grid	= 0x07, +	dtag_mpeg_video_window			= 0x08, +	dtag_mpeg_ca				= 0x09, +	dtag_mpeg_iso_639_language		= 0x0a, +	dtag_mpeg_system_clock			= 0x0b, +	dtag_mpeg_multiplex_buffer_utilization	= 0x0c, +	dtag_mpeg_copyright			= 0x0d, +	dtag_mpeg_maximum_bitrate		= 0x0e, +	dtag_mpeg_private_data_indicator	= 0x0f, +	dtag_mpeg_smoothing_buffer		= 0x10, +	dtag_mpeg_std				= 0x11, +	dtag_mpeg_ibp				= 0x12, +	dtag_mpeg_4_video			= 0x1b, +	dtag_mpeg_4_audio			= 0x1c, +	dtag_mpeg_iod				= 0x1d, +	dtag_mpeg_sl				= 0x1e, +	dtag_mpeg_fmc				= 0x1f, +	dtag_mpeg_external_es_id		= 0x20, +	dtag_mpeg_muxcode			= 0x21, +	dtag_mpeg_fmxbuffer_size		= 0x22, +	dtag_mpeg_multiplex_buffer		= 0x23, +	dtag_mpeg_content_labelling		= 0x24, +	dtag_mpeg_metadata_pointer		= 0x25, +	dtag_mpeg_metadata			= 0x26, +	dtag_mpeg_metadata_std			= 0x27, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/external_es_id_descriptor.h b/lib/libucsi/mpeg/external_es_id_descriptor.h new file mode 100644 index 0000000..3aa3237 --- /dev/null +++ b/lib/libucsi/mpeg/external_es_id_descriptor.h @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_EXTERNAL_ES_ID_DESCRIPTOR +#define _UCSI_MPEG_EXTERNAL_ES_ID_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_external_es_id_descriptor structure. + */ +struct mpeg_external_es_id_descriptor { +	struct descriptor d; + +	uint16_t external_es_id; +} __ucsi_packed; + +/** + * Process an mpeg_external_es_id_descriptor structure. + * + * @param d Generic descriptor structure. + * @return mpeg_external_es_id_descriptor pointer, or NULL on error. + */ +static inline struct mpeg_external_es_id_descriptor* +	mpeg_external_es_id_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_external_es_id_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); + +	return (struct mpeg_external_es_id_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/fmc_descriptor.h b/lib/libucsi/mpeg/fmc_descriptor.h new file mode 100644 index 0000000..5a5bed2 --- /dev/null +++ b/lib/libucsi/mpeg/fmc_descriptor.h @@ -0,0 +1,122 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_FMC_DESCRIPTOR +#define _UCSI_MPEG_FMC_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_fmc_descriptor structure. + */ +struct mpeg_fmc_descriptor { +	struct descriptor d; + +	/* struct mpeg_flex_mux muxes[] */ +} __ucsi_packed; + +/** + * An entry in the muxes field of an mpeg_fmc_descriptor structure. + */ +struct mpeg_flex_mux { +	uint16_t es_id; +	uint8_t flex_mux_channel; +} __ucsi_packed; + +/** + * Process an mpeg_fmc_descriptor structure. + * + * @param d Generic descriptor structure. + * @return Pointer to an mpeg_fmc_descriptor structure, or NULL on error. + */ +static inline struct mpeg_fmc_descriptor* +	mpeg_fmc_descriptor_codec(struct descriptor* d) +{ +	uint8_t* buf = (uint8_t*) d + 2; +	int pos = 0; +	int len = d->len; + +	if (len % sizeof(struct mpeg_flex_mux)) +		return NULL; + +	while(pos < len) { +		bswap16(buf+pos); +		pos += sizeof(struct mpeg_flex_mux); +	} + +	return (struct mpeg_fmc_descriptor*) d; +} + +/** + * Convenience iterator for the muxes field of an mpeg_fmc_descriptor structure. + * + * @param d Generic descriptor structure. + * @param pos Variable holding a pointer to the the current entry within the muxes field. + */ +#define mpeg_fmc_descriptor_muxes_for_each(d, pos) \ +	for ((pos) = mpeg_fmc_descriptor_muxes_first(d); \ +	     (pos); \ +	     (pos) = mpeg_fmc_descriptor_muxes_next(d, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct mpeg_flex_mux* +		mpeg_fmc_descriptor_muxes_first(struct mpeg_fmc_descriptor *d) +{ +	if (d->d.len < sizeof(struct mpeg_flex_mux)) +		return NULL; + +	return (struct mpeg_flex_mux *) +			((uint8_t*) d + sizeof(struct mpeg_fmc_descriptor)); +} + +static inline struct mpeg_flex_mux* +	mpeg_fmc_descriptor_muxes_next(struct mpeg_fmc_descriptor *d, +				       struct mpeg_flex_mux *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct mpeg_flex_mux); + +	if (next >= end) +		return NULL; + +	return (struct mpeg_flex_mux *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h b/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h new file mode 100644 index 0000000..74f643c --- /dev/null +++ b/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h @@ -0,0 +1,83 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_FMXBUFFER_SIZE_DESCRIPTOR +#define _UCSI_MPEG_FMXBUFFER_SIZE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + + +/** + * mpeg_fmxbuffer_size_descriptor structure. + */ +struct mpeg_fmxbuffer_size_descriptor { +	struct descriptor d; + +	/* uint8_t descriptors[] */ +} __ucsi_packed; + +/** + * Process an mpeg_fmxbuffer_size_descriptor structure. + * + * @param d Pointer to a generic descriptor structure. + * @return Pointer to an mpeg_fmxbuffer_size_descriptor structure, or NULL on error. + */ +static inline struct mpeg_fmxbuffer_size_descriptor* +	mpeg_fmxbuffer_size_descriptor_codec(struct descriptor* d) +{ +	return (struct mpeg_fmxbuffer_size_descriptor*) d; +} + +/** + * Retrieve pointer to descriptors field of mpeg_fmxbuffer_size_descriptor structure. + * + * @param d mpeg_fmxbuffer_size_descriptor structure pointer. + * @return Pointer to the descriptors. + */ +static inline uint8_t * +	mpeg_fmxbuffer_size_descriptor_descriptors(struct mpeg_fmxbuffer_size_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_fmxbuffer_size_descriptor); +} + +/** + * Calculate the length of the descriptors field of an mpeg_fmxbuffer_size_descriptor structure. + * + * @param d mpeg_fmxbuffer_size_descriptor structure pointer. + * @return Length of descriptors in bytes. + */ +static inline int +	mpeg_fmxbuffer_size_descriptor_descriptors_length(struct mpeg_fmxbuffer_size_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/hierarchy_descriptor.h b/lib/libucsi/mpeg/hierarchy_descriptor.h new file mode 100644 index 0000000..a38539d --- /dev/null +++ b/lib/libucsi/mpeg/hierarchy_descriptor.h @@ -0,0 +1,83 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_HIERARCHY_DESCRIPTOR +#define _UCSI_MPEG_HIERARCHY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Hierarchy type values. + */ +enum { +	MPEG_HIERARCHY_TYPE_ISO13818_2_SPATIAL_SCALABILITY 	= 0x01, +	MPEG_HIERARCHY_TYPE_ISO13818_2_SNR_SCALABILITY 		= 0x02, +	MPEG_HIERARCHY_TYPE_ISO13818_2_TEMPORAL_SCALABILITY 	= 0x03, +	MPEG_HIERARCHY_TYPE_ISO13818_2_DATA_PARTITIONING 	= 0x04, +	MPEG_HIERARCHY_TYPE_ISO13818_3_EXTENSION_BITSTREAM 	= 0x05, +	MPEG_HIERARCHY_TYPE_ISO13818_1_PRIVATE_BITSTREAM 	= 0x06, +	MPEG_HIERARCHY_TYPE_ISO13818_2_MULTI_VIEW_PROFILE 	= 0x07, +	MPEG_HIERARCHY_TYPE_BASE_LAYER		 		= 0x0f, +}; + + +/** + * mpeg_hierarchy_descriptor structure. + */ +struct mpeg_hierarchy_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved_1			: 4; , +	uint8_t hierarchy_type			: 4; ); +  EBIT2(uint8_t reserved_2			: 2; , +	uint8_t hierarchy_layer_index		: 6; ); +  EBIT2(uint8_t reserved_3			: 2; , +	uint8_t hierarchy_embedded_layer_index	: 6; ); +  EBIT2(uint8_t reserved_4			: 2; , +	uint8_t hierarchy_channel		: 6; ); +} __ucsi_packed; + +/** + * Process an mpeg_hierarchy_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to mpeg_hierarchy_descriptor structure, or NULL on error. + */ +static inline struct mpeg_hierarchy_descriptor* +	mpeg_hierarchy_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_hierarchy_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_hierarchy_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/ibp_descriptor.h b/lib/libucsi/mpeg/ibp_descriptor.h new file mode 100644 index 0000000..e82780a --- /dev/null +++ b/lib/libucsi/mpeg/ibp_descriptor.h @@ -0,0 +1,65 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_IBP_DESCRIPTOR +#define _UCSI_MPEG_IBP_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_ibp_descriptor structure. + */ +struct mpeg_ibp_descriptor { +	struct descriptor d; + +  EBIT3(uint16_t closed_gop_flag	: 1;  , +	uint16_t identical_gop_flag	: 1;  , +	uint16_t max_gop_length		: 14; ); +} __ucsi_packed; + +/** + * Process an mpeg_ibp_descriptor structure. + * + * @param d Generic descriptor structure. + * @return Pointer to the mpeg_ibp_descriptor structure, or NULL on error. + */ +static inline struct mpeg_ibp_descriptor* +	mpeg_ibp_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_ibp_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); + +	return (struct mpeg_ibp_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/iod_descriptor.h b/lib/libucsi/mpeg/iod_descriptor.h new file mode 100644 index 0000000..61de153 --- /dev/null +++ b/lib/libucsi/mpeg/iod_descriptor.h @@ -0,0 +1,87 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_IOD_DESCRIPTOR +#define _UCSI_MPEG_IOD_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_iod_descriptor structure. + */ +struct mpeg_iod_descriptor { +	struct descriptor d; + +	uint8_t scope_of_iod_label; +	uint8_t iod_label; +	/* uint8_t iod[] */ +} __ucsi_packed; + +/** + * Process an mpeg_iod_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to an mpeg_iod_descriptor structure, or NULL on error. + */ +static inline struct mpeg_iod_descriptor* +	mpeg_iod_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct mpeg_iod_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_iod_descriptor*) d; +} + +/** + * Retrieve pointer to iod field of an mpeg_iod_descriptor structure. + * + * @param d Pointer to mpeg_iod_descriptor structure. + * @return Pointer to the iod field. + */ +static inline uint8_t * +	mpeg_iod_descriptor_iod(struct mpeg_iod_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_iod_descriptor); +} + +/** + * Calculate the length of the iod field of an mpeg_iod_descriptor structure. + * + * @param d Pointer to mpeg_iod_descriptor structure. + * @return The number of bytes. + */ +static inline int +	mpeg_iod_descriptor_iod_length(struct mpeg_iod_descriptor *d) +{ +	return d->d.len - 2; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/iso_639_language_descriptor.h b/lib/libucsi/mpeg/iso_639_language_descriptor.h new file mode 100644 index 0000000..5b5aac0 --- /dev/null +++ b/lib/libucsi/mpeg/iso_639_language_descriptor.h @@ -0,0 +1,124 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_ISO_639_LANGUAGE_DESCRIPTOR +#define _UCSI_MPEG_ISO_639_LANGUAGE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * Possible values for audio_type. + */ +enum { +	MPEG_AUDIO_TYPE_CLEAN_EFFECTS 			= 0x01, +	MPEG_AUDIO_TYPE_HEARING_IMPAIRED 		= 0x02, +	MPEG_AUDIO_TYPE_VISUAL_IMPAIRED_COMMENTARY 	= 0x03, +}; + +/** + * mpeg_iso_639_language_descriptor structure. + */ +struct mpeg_iso_639_language_descriptor { +	struct descriptor d; + +	/* struct mpeg_iso_639_language_code languages[] */ +} __ucsi_packed; + +/** + * An entry in the mpeg_iso_639_language_descriptor languages field. + */ +struct mpeg_iso_639_language_code { +	iso639lang_t language_code; +	uint8_t audio_type; +} __ucsi_packed; + +/** + * Process an mpeg_iso_639_language_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to an mpeg_iso_639_language_descriptor structure, or NULL + * on error. + */ +static inline struct mpeg_iso_639_language_descriptor* +	mpeg_iso_639_language_descriptor_codec(struct descriptor* d) +{ +	if (d->len % sizeof(struct mpeg_iso_639_language_code)) +		return NULL; + +	return (struct mpeg_iso_639_language_descriptor*) d; +} + +/** + * Convenience iterator for the languages field of an mpeg_iso_639_language_descriptor + * + * @param d Pointer to the mpeg_iso_639_language_descriptor structure. + * @param pos Variable holding a pointer to the current entry. + */ +#define mpeg_iso_639_language_descriptor_languages_for_each(_d, _pos) \ +	for ((_pos) = mpeg_iso_639_language_descriptor_languages_first(_d); \ +	     (_pos); \ +	     (_pos) = mpeg_iso_639_language_descriptor_languages_next(_d, _pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct mpeg_iso_639_language_code* +	mpeg_iso_639_language_descriptor_languages_first(struct mpeg_iso_639_language_descriptor *d) +{ +	if (d->d.len < sizeof(struct mpeg_iso_639_language_code)) +		return NULL; + +	return (struct mpeg_iso_639_language_code *) +		((uint8_t*) d + sizeof(struct mpeg_iso_639_language_descriptor)); +} + +static inline struct mpeg_iso_639_language_code* +	mpeg_iso_639_language_descriptor_languages_next(struct mpeg_iso_639_language_descriptor *d, +						        struct mpeg_iso_639_language_code *pos) +{ +	uint8_t *end = (uint8_t*) d + 2 + d->d.len; +	uint8_t *next =	(uint8_t *) pos + sizeof(struct mpeg_iso_639_language_code); + +	if (next >= end) +		return NULL; + +	return (struct mpeg_iso_639_language_code *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/maximum_bitrate_descriptor.h b/lib/libucsi/mpeg/maximum_bitrate_descriptor.h new file mode 100644 index 0000000..e0bcddb --- /dev/null +++ b/lib/libucsi/mpeg/maximum_bitrate_descriptor.h @@ -0,0 +1,64 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_MAXIMUM_BITRATE_DESCRIPTOR +#define _UCSI_MPEG_MAXIMUM_BITRATE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_maximum_bitrate_descriptor structure. + */ +struct mpeg_maximum_bitrate_descriptor { +	struct descriptor d; + +  EBIT2(uint32_t reserved		: 2;  , +	uint32_t maximum_bitrate	: 22; ); +} __ucsi_packed; + +/** + * Process an mpeg_maximum_bitrate_descriptor. + * + * @param d Pointer to generic descriptor structure. + * @return Pointer to mpeg_maximum_bitrate_descriptor, or NULL on error. + */ +static inline struct mpeg_maximum_bitrate_descriptor* +	mpeg_maximum_bitrate_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_maximum_bitrate_descriptor) - 2)) +		return NULL; + +	bswap24((uint8_t*) d + 2); + +	return (struct mpeg_maximum_bitrate_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/metadata_descriptor.h b/lib/libucsi/mpeg/metadata_descriptor.h new file mode 100644 index 0000000..5b91e05 --- /dev/null +++ b/lib/libucsi/mpeg/metadata_descriptor.h @@ -0,0 +1,472 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_METADATA_DESCRIPTOR +#define _UCSI_MPEG_METADATA_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Values for the decoder_config_flags field. + */ +enum { +	MPEG_DECODER_CONFIG_NONE				= 0x00, +	MPEG_DECODER_CONFIG_IN_DECODER_CONFIG			= 0x01, +	MPEG_DECODER_CONFIG_SAME_METADATA_SERVICE		= 0x02, +	MPEG_DECODER_CONFIG_DSMCC				= 0x03, +	MPEG_DECODER_CONFIG_SAME_PROGRAM			= 0x04, +}; + +/** + * mpeg_metadata_descriptor structure. + */ +struct mpeg_metadata_descriptor { +	struct descriptor d; + +	uint16_t metadata_application_format; +	/* struct mpeg_metadata_descriptor_application_format_identifier appid */ +	/* uint8_t metadata_format */ +	/* struct mpeg_metadata_descriptor_format_identifier formid */ +	/* struct mpeg_metadata_descriptor_flags flags */ +	/* struct mpeg_metadata_descriptor_service_identifier service_identifier */ +	/* struct mpeg_metadata_descriptor_decoder_config decoder_config */ +	/* struct mpeg_metadata_descriptor_decoder_config_id_record decoder_config_id_record */ +	/* struct mpeg_metadata_descriptor_decoder_config_service_id decoder_config_service_id */ +	/* struct mpeg_metadata_descriptor_decoder_config_reserved decoder_config_reserved */ +	/* uint8_t private_data[] */ +} __ucsi_packed; + +/** + * appid field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_application_format_identifier { +	uint32_t id; +} __ucsi_packed; + +/** + * formid field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_format_identifier { +	uint32_t id; +} __ucsi_packed; + +/** + * Flags field of a metadata_descriptor + */ +struct mpeg_metadata_descriptor_flags { +	uint8_t metadata_service_id; +  EBIT3(uint8_t decoder_config_flags				: 3;  , +	uint8_t dsm_cc_flag					: 1;  , +	uint8_t reserved					: 4;  ); +} __ucsi_packed; + +/** + * service_identifier field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_service_identifier { +	uint8_t service_identification_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * decoder_config field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_decoder_config { +	uint8_t decoder_config_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * decoder_config_id_record field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_decoder_config_id_record { +	uint8_t decoder_config_id_record_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * decoder_config_service_id field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_decoder_config_service_id { +	uint8_t decoder_config_metadata_service_id; +} __ucsi_packed; + +/** + * decoder_config_reserved field of a metadata_descriptor. + */ +struct mpeg_metadata_descriptor_decoder_config_reserved { +	uint8_t reserved_data_length; +	/* uint8_t data[] */ +} __ucsi_packed; + + + + +/** + * Process an mpeg_metadata_descriptor. + * + * @param d Generic descriptor. + * @return Pointer to an mpeg_metadata_descriptor, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor* +	mpeg_metadata_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 2; +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len + 2; +	struct mpeg_metadata_descriptor_flags *flags; +	int id; + +	if (len < sizeof(struct mpeg_metadata_descriptor)) +		return NULL; + +	bswap16(buf + pos); +	id = *((uint16_t*) (buf+pos)); +	pos += 2; + +	if (id == 0xffff) { +		if (len < (pos+4)) +			return NULL; +		bswap32(buf+pos); +		pos += 4; +	} + +	if (len < (pos+1)) +		return NULL; + +	id = buf[pos]; +	pos++; +	if (id == 0xff) { +		if (len < (pos+4)) +			return NULL; +		bswap32(buf+pos); +		pos += 4; +	} + +	if (len < (pos + sizeof(struct mpeg_metadata_descriptor_flags))) +		return NULL; +	flags = (struct mpeg_metadata_descriptor_flags*) (buf+pos); +	pos += sizeof(struct mpeg_metadata_descriptor_flags); + +	if (flags->dsm_cc_flag == 1) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (flags->decoder_config_flags == 1) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (flags->decoder_config_flags == 3) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (flags->decoder_config_flags == 4) { +		if (len < (pos+1)) +			return NULL; +		pos++; +	} + +	if ((flags->decoder_config_flags == 5) || +	    (flags->decoder_config_flags == 6)) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (len < pos) +		return NULL; + +	return (struct mpeg_metadata_descriptor*) d; +} + +/** + * Accessor for pointer to appid field of an mpeg_metadata_descriptor. + * + * @param d The mpeg_metadata_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_application_format_identifier* +	mpeg_metadata_descriptor_appid(struct mpeg_metadata_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor); + +	if (d->metadata_application_format != 0xffff) +		return NULL; +	return (struct mpeg_metadata_descriptor_application_format_identifier*) buf; +} + +/** + * Accessor for metadata_format field of an mpeg_metadata_descriptor. + * + * @param d The mpeg_metadata_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline uint8_t +	mpeg_metadata_descriptor_metadata_format(struct mpeg_metadata_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	return *buf; +} + +/** + * Accessor for pointer to formid field of an mpeg_metadata_descriptor. + * + * @param d The mpeg_metadata_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_format_identifier* +        mpeg_metadata_descriptor_formid(struct mpeg_metadata_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	if (*buf != 0xff) +		return NULL; + +	return (struct mpeg_metadata_descriptor_format_identifier*) (buf+1); +} + +/** + * Accessor for flags field of an mpeg_metadata_descriptor. + * + * @param d The mpeg_metadata_descriptor structure. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_flags* +	mpeg_metadata_descriptor_flags(struct mpeg_metadata_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	if (*buf == 0xff) +		buf+=4; + +	return (struct mpeg_metadata_descriptor_flags*) buf; +} + + +/** + * Accessor for service_identifier field of an mpeg_metadata_descriptor. + * + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_service_identifier* + 	mpeg_metadata_descriptor_sevice_identifier(struct mpeg_metadata_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); + +	if (flags->dsm_cc_flag!=1) +		return NULL; + +	return (struct mpeg_metadata_descriptor_service_identifier *) buf; +} + +/** + * Accessor for data field of an mpeg_metadata_descriptor_service_identifier. + * + * @param d The mpeg_metadata_descriptor_service_identifier structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_descriptor_service_identifier_data(struct mpeg_metadata_descriptor_service_identifier *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_service_identifier); +} + +/** + * Accessor for decoder_config field of an mpeg_metadata_descriptor. + * + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_decoder_config* +	mpeg_metadata_descriptor_decoder_config(struct mpeg_metadata_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); + +	if (flags->decoder_config_flags != 1) +		return NULL; + +	if (flags->dsm_cc_flag==1) +		buf += 1 + buf[1]; + +	return (struct mpeg_metadata_descriptor_decoder_config*) buf; +} + +/** + * Accessor for data field of an mpeg_metadata_descriptor_service_identifier. + * + * @param d The mpeg_metadata_descriptor_service_identifier structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_descriptor_decoder_config_data(struct mpeg_metadata_descriptor_decoder_config *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config); +} + +/** + * Accessor for decoder_config_id_record field of an mpeg_metadata_descriptor. + * + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_decoder_config_id_record* +	mpeg_metadata_descriptor_decoder_config_id_record(struct mpeg_metadata_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); + +	if (flags->decoder_config_flags != 3) +		return NULL; + +	if (flags->dsm_cc_flag==1) +		buf += 1 + buf[1]; + +	return (struct mpeg_metadata_descriptor_decoder_config_id_record *) buf; +} + +/** + * Accessor for data field of an mpeg_metadata_descriptor_decoder_config_id_record. + * + * @param d The mpeg_metadata_descriptor_decoder_config_id_record structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_descriptor_decoder_config_id_record_data(struct mpeg_metadata_descriptor_decoder_config_id_record *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config_id_record); +} + +/** + * Accessor for decoder_config_service_id field of an mpeg_metadata_descriptor. + * + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_decoder_config_service_id* +	mpeg_metadata_descriptor_decoder_config_service_id(struct mpeg_metadata_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); + +	if (flags->decoder_config_flags != 4) +		return NULL; + +	if (flags->dsm_cc_flag==1) +		buf += 1 + buf[1]; + +	return (struct mpeg_metadata_descriptor_decoder_config_service_id *) buf; +} + +/** + * Accessor for decoder_config_reserved field of an mpeg_metadata_descriptor. + * + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_descriptor_decoder_config_reserved* +	mpeg_metadata_descriptor_decoder_config_reserved(struct mpeg_metadata_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); + +	if ((flags->decoder_config_flags != 5) && (flags->decoder_config_flags != 6)) +		return NULL; + +	if (flags->dsm_cc_flag==1) +		buf += 1 + buf[1]; + +	return (struct mpeg_metadata_descriptor_decoder_config_reserved *) buf; +} + +/** + * Accessor for data field of an mpeg_metadata_descriptor_decoder_config_reserved. + * + * @param d The mpeg_metadata_descriptor_decoder_config_reserved structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_descriptor_decoder_config_reserved_data(struct mpeg_metadata_descriptor_decoder_config_reserved *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config_reserved); +} + +/** + * Accessor for private_data field of an mpeg_metadata_descriptor. + * + * @param d The mpeg_metadata_descriptor structure. + * @param flags Pointer to the mpeg_metadata_descriptor_flags. + * @param length Where the number of bytes in the field should be stored. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_descriptor_private_data(struct mpeg_metadata_descriptor *d, +					      struct mpeg_metadata_descriptor_flags *flags, +					      int *length) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags); +	uint8_t *end = (uint8_t*) d + d->d.len + 2; + + +	if (flags->dsm_cc_flag==1) +		buf += 1 + buf[1]; +	if (flags->decoder_config_flags==1) +		buf += 1 + buf[1]; +	if (flags->decoder_config_flags==3) +		buf += 1 + buf[1]; +	if (flags->decoder_config_flags==4) +		buf++; +	if ((flags->decoder_config_flags==5)||(flags->decoder_config_flags==6)) +		buf += 1 + buf[1]; + +	*length = end - buf; +	return buf; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/metadata_pointer_descriptor.h b/lib/libucsi/mpeg/metadata_pointer_descriptor.h new file mode 100644 index 0000000..e4d7503 --- /dev/null +++ b/lib/libucsi/mpeg/metadata_pointer_descriptor.h @@ -0,0 +1,360 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_METADATA_POINTER_DESCRIPTOR +#define _UCSI_MPEG_METADATA_POINTER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * Possible values for the mpeg_carriage_flags field. + */ +enum { +	MPEG_CARRIAGE_SAME_TS					= 0x00, +	MPEG_CARRIAGE_DIFFERENT_TS				= 0x01, +	MPEG_CARRIAGE_PS					= 0x02, +	MPEG_CARRIAGE_OTHER					= 0x03, +}; + +/** + * mpeg_metadata_pointer_descriptor structure. + */ +struct mpeg_metadata_pointer_descriptor { +	struct descriptor d; + +	uint16_t metadata_application_format; +	/* struct mpeg_metadata_pointer_descriptor_application_format_identifier appid */ +	/* uint8_t metadata_format */ +	/* struct mpeg_metadata_pointer_descriptor_format_identifier formid */ +	/* struct mpeg_metadata_pointer_descriptor_flags flags */ +	/* struct mpeg_metadata_pointer_descriptor_locator locator */ +	/* struct mpeg_metadata_pointer_descriptor_program_number program_number */ +	/* struct mpeg_metadata_pointer_descriptor_carriage carriage */ +	/* uint8_t private_data[] */ +} __ucsi_packed; + +/** + * appid field of a metadata_pointer_descriptor. + */ +struct mpeg_metadata_pointer_descriptor_application_format_identifier { +	uint32_t id; +} __ucsi_packed; + +/** + * formid field of a metadata_pointer_descriptor. + */ +struct mpeg_metadata_pointer_descriptor_format_identifier { +	uint32_t id; +} __ucsi_packed; + +/** + * Flags field of a metadata_pointer_descriptor + */ +struct mpeg_metadata_pointer_descriptor_flags { +	uint8_t metadata_service_id; +  EBIT3(uint8_t metadata_locator_record_flag			: 1;  , +	uint8_t mpeg_carriage_flags				: 2;  , +	uint8_t reserved					: 5;  ); +} __ucsi_packed; + +/** + * Reference_id field of a metadata_pointer_descriptor. + */ +struct mpeg_metadata_pointer_descriptor_locator { +	uint8_t metadata_locator_record_length; +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * program_number field of a metadata_pointer_descriptor. + */ +struct mpeg_metadata_pointer_descriptor_program_number { +	uint16_t number; +} __ucsi_packed; + +/** + * carriage field of a metadata_pointer_descriptor. + */ +struct mpeg_metadata_pointer_descriptor_carriage { +	uint16_t transport_stream_location; +	uint16_t transport_stream_id; +} __ucsi_packed; + + + + +/** + * Process an mpeg_metadata_pointer_descriptor. + * + * @param d Generic descriptor. + * @return Pointer to an mpeg_metadata_pointer_descriptor, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor* +	mpeg_metadata_pointer_descriptor_codec(struct descriptor* d) +{ +	uint32_t pos = 2; +	uint8_t *buf = (uint8_t*) d; +	uint32_t len = d->len + 2; +	struct mpeg_metadata_pointer_descriptor_flags *flags; +	int id; + +	if (len < sizeof(struct mpeg_metadata_pointer_descriptor)) +		return NULL; + +	bswap16(buf + pos); +	id = *((uint16_t*) (buf+pos)); +	pos += 2; + +	if (id == 0xffff) { +		if (len < (pos+4)) +			return NULL; +		bswap32(buf+pos); +		pos += 4; +	} + +	if (len < (pos+1)) +		return NULL; + +	id = buf[pos]; +	pos++; +	if (id == 0xff) { +		if (len < (pos+4)) +			return NULL; +		bswap32(buf+pos); +		pos += 4; +	} + +	if (len < (pos + sizeof(struct mpeg_metadata_pointer_descriptor_flags))) +		return NULL; +	flags = (struct mpeg_metadata_pointer_descriptor_flags*) (buf+pos); +	pos += sizeof(struct mpeg_metadata_pointer_descriptor_flags); + +	if (flags->metadata_locator_record_flag == 1) { +		if (len < (pos+1)) +			return NULL; +		if (len < (pos+1+buf[pos])) +			return NULL; +		pos += 1 + buf[pos]; +	} + +	if (flags->mpeg_carriage_flags < 3) { +		if (len < (pos + 2)) +			return NULL; +		bswap16(buf+pos); +		pos += 2; +	} + +	if (flags->mpeg_carriage_flags == 1) { +		if (len < (pos + 4)) +			return NULL; +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		pos += 4; +	} + +	if (len < pos) +		return NULL; + +	return (struct mpeg_metadata_pointer_descriptor*) d; +} + +/** + * Accessor for pointer to appid field of an mpeg_metadata_pointer_descriptor. + * + * @param d The mpeg_metadata_pointer_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_application_format_identifier* +	mpeg_metadata_pointer_descriptor_appid(struct mpeg_metadata_pointer_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor); + +	if (d->metadata_application_format != 0xffff) +		return NULL; +	return (struct mpeg_metadata_pointer_descriptor_application_format_identifier*) buf; +} + +/** + * Accessor for metadata_format field of an mpeg_metadata_pointer_descriptor. + * + * @param d The mpeg_metadata_pointer_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline uint8_t +	mpeg_metadata_pointer_descriptor_metadata_format(struct mpeg_metadata_pointer_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	return *buf; +} + +/** + * Accessor for pointer to formid field of an mpeg_metadata_pointer_descriptor. + * + * @param d The mpeg_metadata_pointer_descriptor structure. + * @return The pointer, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_format_identifier* +        mpeg_metadata_pointer_descriptor_formid(struct mpeg_metadata_pointer_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	if (*buf != 0xff) +		return NULL; + +	return (struct mpeg_metadata_pointer_descriptor_format_identifier*) (buf+1); +} + +/** + * Accessor for flags field of an mpeg_metadata_pointer_descriptor. + * + * @param d The mpeg_metadata_pointer_descriptor structure. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_flags* +	mpeg_metadata_pointer_descriptor_flags(struct mpeg_metadata_pointer_descriptor *d) +{ +	uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor); + +	if (d->metadata_application_format == 0xffff) +		buf+=4; +	if (*buf == 0xff) +		buf+=4; + +	return (struct mpeg_metadata_pointer_descriptor_flags*) buf; +} + + +/** + * Accessor for locator field of an mpeg_metadata_pointer_descriptor. + * + * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_locator* +	mpeg_metadata_pointer_descriptor_locator(struct mpeg_metadata_pointer_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags); + +	if (flags->metadata_locator_record_flag!=1) +		return NULL; + +	return (struct mpeg_metadata_pointer_descriptor_locator *) buf; +} + +/** + * Accessor for data field of an mpeg_metadata_pointer_descriptor_locator. + * + * @param d The mpeg_metadata_pointer_descriptor_locator structure. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_pointer_descriptor_locator_data(struct mpeg_metadata_pointer_descriptor_locator *d) +{ +	return (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor_locator); +} + + +/** + * Accessor for program_number field of an mpeg_metadata_pointer_descriptor. + * + * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_program_number* +	mpeg_metadata_pointer_descriptor_program_number(struct mpeg_metadata_pointer_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags); + +	if (flags->mpeg_carriage_flags < 3) +		return NULL; + +	if (flags->metadata_locator_record_flag==1) +		buf += 1 + buf[1]; + +	return (struct mpeg_metadata_pointer_descriptor_program_number*) buf; +} + +/** + * Accessor for carriage field of an mpeg_metadata_pointer_descriptor. + * + * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags. + * @return Pointer to the field, or NULL on error. + */ +static inline struct mpeg_metadata_pointer_descriptor_carriage* +	mpeg_metadata_pointer_descriptor_carriage(struct mpeg_metadata_pointer_descriptor_flags *flags) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags); + +	if (flags->mpeg_carriage_flags != 1) +		return NULL; + +	if (flags->metadata_locator_record_flag==1) +		buf += 1 + buf[1]; +	if (flags->mpeg_carriage_flags < 3) +		buf += sizeof(struct mpeg_metadata_pointer_descriptor_program_number); + +	return (struct mpeg_metadata_pointer_descriptor_carriage *) buf; +} + +/** + * Accessor for private_data field of an mpeg_metadata_pointer_descriptor. + * + * @param d The mpeg_metadata_pointer_descriptor structure. + * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags. + * @param length Where the number of bytes in the field should be stored. + * @return Pointer to the field. + */ +static inline uint8_t* +	mpeg_metadata_pointer_descriptor_private_data(struct mpeg_metadata_pointer_descriptor *d, +					       	      struct mpeg_metadata_pointer_descriptor_flags *flags, +					       	      int *length) +{ +	uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags); +	uint8_t *end = (uint8_t*) d + d->d.len + 2; + + +	if (flags->metadata_locator_record_flag==1) +		buf += 1 + buf[1]; +	if (flags->mpeg_carriage_flags < 3) +		buf += sizeof(struct mpeg_metadata_pointer_descriptor_program_number); +	if (flags->mpeg_carriage_flags != 1) +		buf += sizeof(struct mpeg_metadata_pointer_descriptor_carriage); + +	*length = end - buf; +	return buf; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/metadata_section.c b/lib/libucsi/mpeg/metadata_section.c new file mode 100644 index 0000000..c1ce019 --- /dev/null +++ b/lib/libucsi/mpeg/metadata_section.c @@ -0,0 +1,27 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/metadata_section.h> + +struct mpeg_metadata_section * mpeg_metadata_section_codec(struct section_ext * ext) +{ +	return (struct mpeg_metadata_section *)ext; +} diff --git a/lib/libucsi/mpeg/metadata_section.h b/lib/libucsi/mpeg/metadata_section.h new file mode 100644 index 0000000..62c4e03 --- /dev/null +++ b/lib/libucsi/mpeg/metadata_section.h @@ -0,0 +1,122 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_METADATA_SECTION_H +#define _UCSI_MPEG_METADATA_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_metadata_section structure. + */ +struct mpeg_metadata_section { +	struct section_ext head; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process an mpeg_metadata_section structure. + * + * @param section Pointer to the section_ext structure. + * @return Pointer to the mpeg_metadata_section structure, or NULL on error. + */ +extern struct mpeg_metadata_section *mpeg_metadata_section_codec(struct section_ext *section); + +/** + * Accessor for the random_access_indicator field of a metadata section. + * + * @param metadata metadata section pointer. + * @return The random_access_indicator. + */ +static inline uint8_t mpeg_metadata_section_random_access_indicator(struct mpeg_metadata_section *metadata) +{ +	return metadata->head.reserved >> 1; +} + +/** + * Accessor for the decoder_config_flag field of a metadata section. + * + * @param metadata metadata section pointer. + * @return The decoder_config_flag. + */ +static inline uint8_t mpeg_metadata_section_decoder_config_flag(struct mpeg_metadata_section *metadata) +{ +	return metadata->head.reserved & 1; +} + +/** + * Accessor for the fragment_indicator field of a metadata section. + * + * @param metadata metadata section pointer. + * @return The fragment_indicator. + */ +static inline uint8_t mpeg_metadata_section_fragment_indicator(struct mpeg_metadata_section *metadata) +{ +	return metadata->head.reserved1; +} + +/** + * Accessor for the service_id field of a metadata section. + * + * @param metadata metadata section pointer. + * @return The service_id. + */ +static inline uint16_t mpeg_metadata_section_service_id(struct mpeg_metadata_section *metadata) +{ +	return metadata->head.table_id_ext >> 8; +} + +/** + * Retrieve pointer to data field of an mpeg_metadata_section. + * + * @param s mpeg_metadata_section pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	mpeg_metadata_section_data(struct mpeg_metadata_section *s) +{ +	return (uint8_t *) s + sizeof(struct mpeg_metadata_section); +} + + +/** + * Determine length of the data field of an mpeg_copyright_descriptor. + * + * @param s mpeg_metadata_section_data pointer. + * @return Length of field in bytes. + */ +static inline int +	mpeg_metadata_section_data_length(struct mpeg_metadata_section *s) +{ +	return section_ext_length(&s->head) - sizeof(struct mpeg_metadata_section); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/metadata_std_descriptor.h b/lib/libucsi/mpeg/metadata_std_descriptor.h new file mode 100644 index 0000000..fc83e6e --- /dev/null +++ b/lib/libucsi/mpeg/metadata_std_descriptor.h @@ -0,0 +1,72 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_METADATA_STD_DESCRIPTOR +#define _UCSI_MPEG_METADATA_STD_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_metadata_std_descriptor structure. + */ +struct mpeg_metadata_std_descriptor { +	struct descriptor d; + +  EBIT2(uint32_t reserved_1			: 2; , +	uint32_t metadata_input_leak_rate	:22; ); +  EBIT2(uint32_t reserved_2			: 2; , +	uint32_t metadata_buffer_size		:22; ); +  EBIT2(uint32_t reserved_3			: 2; , +	uint32_t metadata_output_leak_rate	:22; ); +} __ucsi_packed; + +/** + * Process an mpeg_metadata_std_descriptor. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_metadata_std_descriptor, or NULL on error. + */ +static inline struct mpeg_metadata_std_descriptor* +	mpeg_metadata_std_descriptor_codec(struct descriptor* d) +{ +	uint8_t *buf = (uint8_t*) d; + +	if (d->len != (sizeof(struct mpeg_metadata_std_descriptor) - 2)) +		return NULL; + +	bswap24(buf + 2); +	bswap24(buf + 5); +	bswap24(buf + 8); + +	return (struct mpeg_metadata_std_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/mpeg4_audio_descriptor.h b/lib/libucsi/mpeg/mpeg4_audio_descriptor.h new file mode 100644 index 0000000..f876759 --- /dev/null +++ b/lib/libucsi/mpeg/mpeg4_audio_descriptor.h @@ -0,0 +1,61 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG4_AUDIO_DESCRIPTOR +#define _UCSI_MPEG4_AUDIO_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg4_audio_descriptor structure. + */ +struct mpeg4_audio_descriptor { +	struct descriptor d; + +	uint8_t mpeg4_audio_profile_and_level; +} __ucsi_packed; + +/** + * Process an mpeg4_audio_descriptor. + * + * @param d Generic descriptor structure. + * @return Pointer to an mpeg4_audio_descriptor structure, or NULL on error. + */ +static inline struct mpeg4_audio_descriptor* +	mpeg4_audio_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg4_audio_descriptor) - 2)) +		return NULL; + +	return (struct mpeg4_audio_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/mpeg4_video_descriptor.h b/lib/libucsi/mpeg/mpeg4_video_descriptor.h new file mode 100644 index 0000000..b956b91 --- /dev/null +++ b/lib/libucsi/mpeg/mpeg4_video_descriptor.h @@ -0,0 +1,61 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG4_VIDEO_DESCRIPTOR +#define _UCSI_MPEG4_VIDEO_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg4_video_descriptor structure. + */ +struct mpeg4_video_descriptor { +	struct descriptor d; + +	uint8_t mpeg4_visual_profile_and_level; +} __ucsi_packed; + +/** + * Process an mpeg4_video_descriptor structure. + * + * @param d Pointer to generic descriptor structure. + * @return Pointer to mpeg4_video_descriptor structure, or NULL on error. + */ +static inline struct mpeg4_video_descriptor* +	mpeg4_video_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg4_video_descriptor) - 2)) +		return NULL; + +	return (struct mpeg4_video_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/multiplex_buffer_descriptor.h b/lib/libucsi/mpeg/multiplex_buffer_descriptor.h new file mode 100644 index 0000000..d55ce3d --- /dev/null +++ b/lib/libucsi/mpeg/multiplex_buffer_descriptor.h @@ -0,0 +1,65 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_MULTIPLEX_BUFFER_DESCRIPTOR +#define _UCSI_MPEG_MULTIPLEX_BUFFER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_multiplex_buffer_descriptor descriptor. + */ +struct mpeg_multiplex_buffer_descriptor { +	struct descriptor d; + +  EBIT2(uint64_t mb_buffer_size : 24;  , +	uint64_t tb_leak_rate	: 24;  ); +} __ucsi_packed; + +/** + * Process an mpeg_multiplex_buffer_descriptor. + * + * @param d Pointer to generic descriptor structure. + * @return Pointer to an mpeg_multiplex_buffer_descriptor structure, or NULL on + * error. + */ +static inline struct mpeg_multiplex_buffer_descriptor* +	mpeg_multiplex_buffer_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_multiplex_buffer_descriptor) - 2)) +		return NULL; + +	bswap48((uint8_t*) d + 2); + +	return (struct mpeg_multiplex_buffer_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h b/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h new file mode 100644 index 0000000..16550ed --- /dev/null +++ b/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h @@ -0,0 +1,67 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_MULTIPLEX_BUFFER_UTILIZATION_DESCRIPTOR +#define _UCSI_MPEG_MULTIPLEX_BUFFER_UTILIZATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_multiplex_buffer_utilization_descriptor structure. + */ +struct mpeg_multiplex_buffer_utilization_descriptor { +	struct descriptor d; + +  EBIT2(uint16_t bound_valid_flag		: 1;  , +	uint16_t ltw_offset_lower_bound		: 15; ); +  EBIT2(uint16_t reserved			: 1;  , +	uint16_t ltw_offset_upper_bound		: 15; ); +} __ucsi_packed; + +/** + * Process a mpeg_multiplex_buffer_utilization_descriptor. + * + * @param d Generic descriptor pointer. + * @return mpeg_multiplex_buffer_utilization_descriptor pointer, or NULL on error. + */ +static inline struct mpeg_multiplex_buffer_utilization_descriptor* +	mpeg_multiplex_buffer_utilization_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_multiplex_buffer_utilization_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); +	bswap16((uint8_t*) d + 4); + +	return (struct mpeg_multiplex_buffer_utilization_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/muxcode_descriptor.h b/lib/libucsi/mpeg/muxcode_descriptor.h new file mode 100644 index 0000000..6bed334 --- /dev/null +++ b/lib/libucsi/mpeg/muxcode_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_MUXCODE_DESCRIPTOR +#define _UCSI_MPEG_MUXCODE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_muxcode_descriptor structure + */ +struct mpeg_muxcode_descriptor { +	struct descriptor d; + +	/* uint8_t entries[] */ +} __ucsi_packed; + +/** + * Process an mpeg_muxcode_descriptor. + * + * @param d Pointer to a generic descriptor structure. + * @return Pointer to an mpeg_muxcode_descriptor structure, or NULL on error. + */ +static inline struct mpeg_muxcode_descriptor* +	mpeg_muxcode_descriptor_codec(struct descriptor* d) +{ +	return (struct mpeg_muxcode_descriptor*) d; +} + +/** + * Retrieve pointer to entries field of an mpeg_muxcode_descriptor structure. + * + * @param d Generic descriptor structure. + * @return Pointer to the entries field. + */ +static inline uint8_t * +	mpeg_muxcode_descriptor_entries(struct mpeg_muxcode_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_muxcode_descriptor); +} + +/** + * Determine length of entries field of an mpeg_muxcode_descriptor structure. + * + * @param d Generic descriptor structure. + * @return Number of bytes in the entries field. + */ +static inline int +	mpeg_muxcode_descriptor_entries_length(struct mpeg_muxcode_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/odsmt_section.c b/lib/libucsi/mpeg/odsmt_section.c new file mode 100644 index 0000000..07407f2 --- /dev/null +++ b/lib/libucsi/mpeg/odsmt_section.c @@ -0,0 +1,80 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/odsmt_section.h> + +struct mpeg_odsmt_section *mpeg_odsmt_section_codec(struct section_ext * ext) +{ +	struct mpeg_odsmt_section * odsmt = (struct mpeg_odsmt_section *)ext; +	uint8_t * buf = (uint8_t *)ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); +	int i; + +	if (len < sizeof(struct mpeg_odsmt_section)) +		return NULL; + +	pos++; + +	if (odsmt->stream_count == 0) { +		struct mpeg_odsmt_stream * stream = +			(struct mpeg_odsmt_stream *) (buf + pos); + +		if ((pos + sizeof(struct mpeg_odsmt_stream_single)) > len) +			return NULL; + +		bswap16(buf+pos); +		pos+=3; + +		if ((pos + stream->u.single.es_info_length) >= len) +			return NULL; + +		if (verify_descriptors(buf + pos, stream->u.single.es_info_length)) +			return NULL; + +		pos += stream->u.single.es_info_length; +	} else { +		for (i=0; i< odsmt->stream_count; i++) { +			struct mpeg_odsmt_stream * stream = +				(struct mpeg_odsmt_stream *)(buf + pos); + +			if ((pos + sizeof(struct mpeg_odsmt_stream_multi)) > len) +				return NULL; + +			bswap16(buf+pos); +			pos += sizeof(struct mpeg_odsmt_stream_multi); + +			if ((pos + stream->u.multi.es_info_length) > len) +				return NULL; + +			if (verify_descriptors(buf + pos, +			    stream->u.multi.es_info_length)) +				return NULL; + +			pos += stream->u.multi.es_info_length; +		} +	} + +	if (pos != len) +		return NULL; + +	return (struct mpeg_odsmt_section *) ext; +} diff --git a/lib/libucsi/mpeg/odsmt_section.h b/lib/libucsi/mpeg/odsmt_section.h new file mode 100644 index 0000000..4e01085 --- /dev/null +++ b/lib/libucsi/mpeg/odsmt_section.h @@ -0,0 +1,224 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_ODSMT_SECTION_H +#define _UCSI_MPEG_ODSMT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_odsmt_section structure. + */ +struct mpeg_odsmt_section { +	struct section_ext head; + +	uint8_t stream_count; +	/* stream_count==0 => struct mpeg_odsmt_stream_single streams +	   stream_count>0  => struct mpeg_odsmt_stream_multi streams[] */ +	/* uint8_t object_descriptors[] */ +} __ucsi_packed; + +struct mpeg_odsmt_stream_single +{ +	uint16_t esid; +	uint8_t es_info_length; +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct mpeg_odsmt_stream_multi +{ +	uint16_t esid; +	uint8_t fmc; +	uint8_t es_info_length; +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Structure describing the stream information held in an mpeg_odsmt_section. + */ +struct mpeg_odsmt_stream { +	union { +		struct mpeg_odsmt_stream_single single; +		struct mpeg_odsmt_stream_multi multi; +	} u; +} __ucsi_packed; + +/** + * Process an mpeg_odsmt_section. + * + * @param section Pointer to the generic section_ext structure. + * @return Pointer to a mpeg_odsmt_section structure, or NULL on error. + */ +extern struct mpeg_odsmt_section *mpeg_odsmt_section_codec(struct section_ext *section); + +/** + * Accessor for the PID field of an ODSMT. + * + * @param odsmt odsmt pointer. + * @return The pid. + */ +static inline uint16_t mpeg_odsmt_section_pid(struct mpeg_odsmt_section *odsmt) +{ +	return odsmt->head.table_id_ext & 0x1fff; +} + +/** + * Convenience iterator for the streams field of an mpeg_odsmt_section. + * + * @param osdmt Pointer to the mpeg_odsmt_section structure. + * @param pos Variable holding pointer to the current mpeg_odsmt_stream structure. + * @param index Variable holding the stream index. + */ +#define mpeg_odsmt_section_streams_for_each(osdmt, pos, index) \ +	for (index=0, (pos) = mpeg_odsmt_section_streams_first(odsmt); \ +	     (pos); \ +	     (pos) = mpeg_odsmt_section_streams_next(odsmt, pos, ++index)) + +/** + * Convenience iterator for the descriptors field of an mpeg_odsmt_stream. + * + * @param osdmt Pointer to the mpeg_odsmt_section structure. + * @param stream Pointer to the mpeg_odsmt_stream structure. + * @param pos Variable holding pointer to the current descriptor structure. + */ +#define mpeg_odsmt_stream_descriptors_for_each(osdmt, stream, pos) \ +	for ((pos) = mpeg_odsmt_stream_descriptors_first(odsmt, stream); \ +	     (pos); \ +	     (pos) = mpeg_odsmt_stream_descriptors_next(odsmt, stream, pos)) + +/** + * Retrieve a pointer to the object_descriptors field of an mpeg_odsmt_section. + * + * @param osdmt Pointer to the mpeg_odsmt_section structure. + * @param len On return, will contain the number of bytes in the object descriptors field. + * @return Pointer to the object_descriptors field, or NULL on error. + */ +static inline uint8_t* +	mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt, +					      size_t* len); + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct mpeg_odsmt_stream * +	mpeg_odsmt_section_streams_first(struct mpeg_odsmt_section *odsmt) +{ +	size_t pos = sizeof(struct mpeg_odsmt_section); + +	if (pos >= section_ext_length(&odsmt->head)) +		return NULL; + +	return (struct mpeg_odsmt_stream *) ((uint8_t *) odsmt + pos); +} + +static inline struct mpeg_odsmt_stream * +	mpeg_odsmt_section_streams_next(struct mpeg_odsmt_section *odsmt, +					struct mpeg_odsmt_stream *pos, +				        int _index) +{ +	uint8_t *end = (uint8_t*) odsmt + section_ext_length(&odsmt->head); +	uint8_t *next; + +	if (_index > odsmt->stream_count) +		return NULL; + +	next = (uint8_t *) pos + sizeof(struct mpeg_odsmt_stream_multi) + +		pos->u.multi.es_info_length; + +	if (next >= end) +		return NULL; + +	return (struct mpeg_odsmt_stream *) next; +} + +static inline struct descriptor * +	mpeg_odsmt_stream_descriptors_first(struct mpeg_odsmt_section *odsmt, +				      	    struct mpeg_odsmt_stream *stream) +{ +	if (odsmt->stream_count == 0) { +		if (stream->u.single.es_info_length == 0) +			return NULL; + +		return (struct descriptor *) +			((uint8_t*) stream + sizeof(struct mpeg_odsmt_stream_single)); +	} else { +		if (stream->u.multi.es_info_length == 0) +			return NULL; + +		return (struct descriptor *) +			((uint8_t*) stream + sizeof(struct mpeg_odsmt_stream_multi)); +	} +} + +static inline struct descriptor * +	mpeg_odsmt_stream_descriptors_next(struct mpeg_odsmt_section *odsmt, +					   struct mpeg_odsmt_stream *stream, +					   struct descriptor* pos) +{ +	if (odsmt->stream_count == 0) { +		return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_odsmt_stream_single), +				       stream->u.single.es_info_length, +				       pos); +	} else { +		return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_odsmt_stream_multi), +				       stream->u.multi.es_info_length, +				       pos); +	} +} + +static inline uint8_t* +	mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt, +					      size_t* len) +{ +	struct mpeg_odsmt_stream* pos; +	size_t size = sizeof(struct mpeg_odsmt_section); +	int _index; + +	mpeg_odsmt_section_streams_for_each(odsmt, pos, _index) { +		if (odsmt->stream_count == 0) +			size += sizeof(struct mpeg_odsmt_stream_single) + +					pos->u.single.es_info_length; +		else +			size += sizeof(struct mpeg_odsmt_stream_multi) + +					pos->u.multi.es_info_length; +	} + +	*len = section_ext_length(&odsmt->head) - size; +	return (uint8_t*) odsmt + size; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/pat_section.c b/lib/libucsi/mpeg/pat_section.c new file mode 100644 index 0000000..2e4c2cc --- /dev/null +++ b/lib/libucsi/mpeg/pat_section.c @@ -0,0 +1,46 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/pat_section.h> + +struct mpeg_pat_section *mpeg_pat_section_codec(struct section_ext * ext) +{ +	uint8_t *buf = (uint8_t *)ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct mpeg_pat_section)) +		return NULL; + +	while (pos < len) { +		if ((pos + 4) > len) +			return NULL; + +		bswap16(buf + pos); +		bswap16(buf + pos + 2); +		pos += 4; +	} + +	if (pos != len) +		return NULL; + +	return (struct mpeg_pat_section *)ext; +} diff --git a/lib/libucsi/mpeg/pat_section.h b/lib/libucsi/mpeg/pat_section.h new file mode 100644 index 0000000..eadfe28 --- /dev/null +++ b/lib/libucsi/mpeg/pat_section.h @@ -0,0 +1,118 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_PAT_SECTION_H +#define _UCSI_MPEG_PAT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_pat_section structure. + */ +struct mpeg_pat_section { +	struct section_ext head; /* table_id_ext == transport_stream_id */ + +	/* struct mpeg_pat_program programs[] */ +} __ucsi_packed; + +/** + * A program within an mpeg_pat_section. + */ +struct mpeg_pat_program { +	uint16_t program_number; +  EBIT2(uint16_t reserved	: 3; , +	uint16_t pid		:13; ); +} __ucsi_packed; + +/** + * Process an mpeg_pat_section. + * + * @param section Pointer to the generic section_ext structure. + * @return Pointer to the mpeg_pat_section structure, or NULL on error. + */ +extern struct mpeg_pat_section *mpeg_pat_section_codec(struct section_ext *section); + +/** + * Accessor for the transport_stream_id field of a PAT. + * + * @param pat PAT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t mpeg_pat_section_transport_stream_id(struct mpeg_pat_section *pat) +{ +	return pat->head.table_id_ext; +} + +/** + * Conveience iterator for the programs field of an mpeg_pat_section. + * + * @param pat Pointer to the mpeg_pat_section structure. + * @param pos Variable holding a pointer to the current mpeg_pat_program structure. + */ +#define mpeg_pat_section_programs_for_each(pat, pos) \ +	for ((pos) = mpeg_pat_section_programs_first(pat); \ +	     (pos); \ +	     (pos) = mpeg_pat_section_programs_next(pat, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct mpeg_pat_program * +	mpeg_pat_section_programs_first(struct mpeg_pat_section * pat) +{ +	size_t pos = sizeof(struct mpeg_pat_section); + +	if (pos >= section_ext_length(&pat->head)) +		return NULL; + +	return (struct mpeg_pat_program*)((uint8_t *) pat + pos); +} + +static inline +	struct mpeg_pat_program *mpeg_pat_section_programs_next(struct mpeg_pat_section * pat, +								struct mpeg_pat_program * pos) +{ +	uint8_t *end = (uint8_t*) pat + section_ext_length(&pat->head); +	uint8_t *next= (uint8_t *) pos + sizeof(struct mpeg_pat_program); + +	if (next >= end) +		return NULL; + +	return (struct mpeg_pat_program *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/pmt_section.c b/lib/libucsi/mpeg/pmt_section.c new file mode 100644 index 0000000..e5aec6a --- /dev/null +++ b/lib/libucsi/mpeg/pmt_section.c @@ -0,0 +1,71 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/pmt_section.h> + +struct mpeg_pmt_section * mpeg_pmt_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *) ext; +	struct mpeg_pmt_section * pmt = (struct mpeg_pmt_section *) ext; +	size_t pos = sizeof(struct section_ext); +	size_t len = section_ext_length(ext); + +	if (len < sizeof(struct mpeg_pmt_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; +	bswap16(buf + pos); +	pos += 2; + +	if ((pos + pmt->program_info_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, pmt->program_info_length)) +		return NULL; + +	pos += pmt->program_info_length; + +	while (pos < len) { +		struct mpeg_pmt_stream * stream = +			(struct mpeg_pmt_stream *) (buf + pos); + +		if ((pos + sizeof(struct mpeg_pmt_stream)) > len) +			return NULL; + +		bswap16(buf + pos + 1); +		bswap16(buf + pos + 3); +		pos += sizeof(struct mpeg_pmt_stream); + +		if ((pos + stream->es_info_length) > len) +			return NULL; + +		if (verify_descriptors(buf + pos, stream->es_info_length)) +			return NULL; + +		pos += stream->es_info_length; +	} + +	if (pos != len) +		return NULL; + +	return (struct mpeg_pmt_section *) ext; +} diff --git a/lib/libucsi/mpeg/pmt_section.h b/lib/libucsi/mpeg/pmt_section.h new file mode 100644 index 0000000..03dea1b --- /dev/null +++ b/lib/libucsi/mpeg/pmt_section.h @@ -0,0 +1,188 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_PMT_SECTION_H +#define _UCSI_MPEG_PMT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_pmt_section structure. + */ +struct mpeg_pmt_section { +	struct section_ext head; + +  EBIT2(uint16_t reserved_1		: 3; , +	uint16_t pcr_pid		:13; ); +  EBIT2(uint16_t reserved_2		: 4; , +	uint16_t program_info_length	:12; ); +	/* struct descriptor descriptors[] */ +	/* struct mpeg_pmt_stream streams[] */ +} __ucsi_packed; + +/** + * A stream within an mpeg_pmt_section. + */ +struct mpeg_pmt_stream { +	uint8_t stream_type; +  EBIT2(uint16_t reserved_1		: 3; , +	uint16_t pid			:13; ); +  EBIT2(uint16_t reserved_2		: 4; , +	uint16_t es_info_length		:12; ); + +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process an mpeg_pmt_section section. + * + * @param section Pointer to the generic section header. + * @return Pointer to the mpeg_pmt_section structure, or NULL on error. + */ +extern struct mpeg_pmt_section *mpeg_pmt_section_codec(struct section_ext *section); + +/** + * Accessor for program_number field of a PMT. + * + * @param pmt PMT pointer. + * @return The program_number. + */ +static inline uint16_t mpeg_pmt_section_program_number(struct mpeg_pmt_section *pmt) +{ +	return pmt->head.table_id_ext; +} + +/** + * Convenience iterator for the descriptors field of the mpeg_pmt_section structure. + * + * @param pmt Pointer to the mpeg_pmt_section structure. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define mpeg_pmt_section_descriptors_for_each(pmt, pos) \ +	for ((pos) = mpeg_pmt_section_descriptors_first(pmt); \ +	     (pos); \ +	     (pos) = mpeg_pmt_section_descriptors_next(pmt, pos)) + +/** + * Convenience iterator for the streams field of the mpeg_pmt_section structure. + * + * @param pmt Pointer to the mpeg_pmt_section structure. + * @param pos Variable holding a pointer to the current mpeg_pmt_stream. + */ +#define mpeg_pmt_section_streams_for_each(pmt, pos) \ +	for ((pos) = mpeg_pmt_section_streams_first(pmt); \ +	     (pos); \ +	     (pos) = mpeg_pmt_section_streams_next(pmt, pos)) + +/** + * Convenience iterator for the descriptors field of an mpeg_pmt_stream structure. + * + * @param stream Pointer to the mpeg_pmt_stream structure. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define mpeg_pmt_stream_descriptors_for_each(stream, pos) \ +	for ((pos) = mpeg_pmt_stream_descriptors_first(stream); \ +	     (pos); \ +	     (pos) = mpeg_pmt_stream_descriptors_next(stream, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	mpeg_pmt_section_descriptors_first(struct mpeg_pmt_section * pmt) +{ +	if (pmt->program_info_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t *) pmt + sizeof(struct mpeg_pmt_section)); +} + +static inline struct descriptor * +	mpeg_pmt_section_descriptors_next(struct mpeg_pmt_section *pmt, +					  struct descriptor* pos) +{ +	return next_descriptor((uint8_t *) pmt + sizeof(struct mpeg_pmt_section), +			       pmt->program_info_length, +			       pos); +} + +static inline struct mpeg_pmt_stream * +	mpeg_pmt_section_streams_first(struct mpeg_pmt_section * pmt) +{ +	size_t pos = sizeof(struct mpeg_pmt_section) + pmt->program_info_length; + +	if (pos >= section_ext_length(&pmt->head)) +		return NULL; + +	return (struct mpeg_pmt_stream *)((uint8_t *)pmt + pos); +} + +static inline struct mpeg_pmt_stream * +	mpeg_pmt_section_streams_next(struct mpeg_pmt_section * pmt, +				      struct mpeg_pmt_stream * pos) +{ +	uint8_t *end = (uint8_t*) pmt + section_ext_length(&pmt->head); +	uint8_t *next =	(uint8_t *) pos + sizeof(struct mpeg_pmt_stream) + +			pos->es_info_length; + +	if (next >= end) +		return NULL; + +	return (struct mpeg_pmt_stream *) next; +} + +static inline struct descriptor * +	mpeg_pmt_stream_descriptors_first(struct mpeg_pmt_stream *stream) +{ +	if (stream->es_info_length == 0) +		return NULL; + +	return (struct descriptor *) +		((uint8_t*) stream + sizeof(struct mpeg_pmt_stream)); +} + +static inline struct descriptor * +	mpeg_pmt_stream_descriptors_next(struct mpeg_pmt_stream *stream, +					 struct descriptor* pos) +{ +	return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_pmt_stream), +			       stream->es_info_length, +			       pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/private_data_indicator_descriptor.h b/lib/libucsi/mpeg/private_data_indicator_descriptor.h new file mode 100644 index 0000000..80e8ef3 --- /dev/null +++ b/lib/libucsi/mpeg/private_data_indicator_descriptor.h @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_PRIVATE_DATA_INDICATOR_DESCRIPTOR +#define _UCSI_MPEG_PRIVATE_DATA_INDICATOR_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_private_data_indicator_descriptor structure + */ +struct mpeg_private_data_indicator_descriptor { +	struct descriptor d; + +	uint32_t private_data_indicator; +} __ucsi_packed; + +/** + * Process an mpeg_private_data_indicator_descriptor structure. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_private_data_indicator_descriptor, or NULL on error. + */ +static inline struct mpeg_private_data_indicator_descriptor* +	mpeg_private_data_indicator_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_private_data_indicator_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct mpeg_private_data_indicator_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/registration_descriptor.h b/lib/libucsi/mpeg/registration_descriptor.h new file mode 100644 index 0000000..df5c186 --- /dev/null +++ b/lib/libucsi/mpeg/registration_descriptor.h @@ -0,0 +1,91 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_REGISTRATION_DESCRIPTOR +#define _UCSI_MPEG_REGISTRATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_registration_descriptor structure. + */ +struct mpeg_registration_descriptor { +	struct descriptor d; + +	uint32_t format_identifier; +	/* uint8_t additional_id_info[] */ +} __ucsi_packed; + +/** + * Process an mpeg_registration_descriptor. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_registration_descriptor structure, or NULL on error. + */ +static inline struct mpeg_registration_descriptor* +	mpeg_registration_descriptor_codec(struct descriptor* d) +{ +	if (d->len < (sizeof(struct mpeg_registration_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct mpeg_registration_descriptor*) d; +} + +/** + * Retrieve a pointer to the additional_id_info field of the + * mpeg_registration_descriptor structure. + * + * @param d Pointer to the mpeg_registration_descriptor structure. + * @return Pointer to the field. + */ +static inline uint8_t * +	mpeg_registration_descriptor_additional_id_info(struct mpeg_registration_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct mpeg_registration_descriptor); +} + +/** + * Determine number of bytes in the additional_id_info field of the + * mpeg_registration_descriptor structure. + * + * @param d Pointer to the mpeg_registration_descriptor structure. + * @return Number of bytes. + */ + +static inline int +	mpeg_registration_descriptor_additional_id_info_length(struct mpeg_registration_descriptor *d) +{ +	return d->d.len - 4; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/section.h b/lib/libucsi/mpeg/section.h new file mode 100644 index 0000000..7dbff93 --- /dev/null +++ b/lib/libucsi/mpeg/section.h @@ -0,0 +1,58 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_SECTION_H +#define _UCSI_MPEG_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/mpeg/cat_section.h> +#include <libucsi/mpeg/odsmt_section.h> +#include <libucsi/mpeg/pat_section.h> +#include <libucsi/mpeg/pmt_section.h> +#include <libucsi/mpeg/tsdt_section.h> +#include <libucsi/mpeg/metadata_section.h> + +#define TRANSPORT_PAT_PID 0x00 +#define TRANSPORT_CAT_PID 0x01 +#define TRANSPORT_TSDT_PID 0x02 + +/** + * Enumeration of MPEG section tags. + */ +enum mpeg_section_tag { +	stag_mpeg_program_association			= 0x00, +	stag_mpeg_conditional_access			= 0x01, +	stag_mpeg_program_map				= 0x02, +	stag_mpeg_transport_stream_description		= 0x03, +	stag_mpeg_iso14496_scene_description		= 0x04, +	stag_mpeg_iso14496_object_description		= 0x05, +	stag_mpeg_metadata				= 0x06, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/sl_descriptor.h b/lib/libucsi/mpeg/sl_descriptor.h new file mode 100644 index 0000000..ab086e3 --- /dev/null +++ b/lib/libucsi/mpeg/sl_descriptor.h @@ -0,0 +1,63 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_SL_DESCRIPTOR +#define _UCSI_MPEG_SL_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_sl_descriptor structure. + */ +struct mpeg_sl_descriptor { +	struct descriptor d; + +	uint16_t es_id; +} __ucsi_packed; + +/** + * Process an mpeg_sl_descriptor. + * + * @param d The generic descriptor structure. + * @return Pointer to an mpeg_sl_descriptor structure, or NULL on error. + */ +static inline struct mpeg_sl_descriptor* +	mpeg_sl_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_sl_descriptor) - 2)) +		return NULL; + +	bswap16((uint8_t*) d + 2); + +	return (struct mpeg_sl_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/smoothing_buffer_descriptor.h b/lib/libucsi/mpeg/smoothing_buffer_descriptor.h new file mode 100644 index 0000000..5e6ad33 --- /dev/null +++ b/lib/libucsi/mpeg/smoothing_buffer_descriptor.h @@ -0,0 +1,66 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_SMOOTHING_BUFFER_DESCRIPTOR +#define _UCSI_MPEG_SMOOTHING_BUFFER_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_smoothing_buffer_descriptor structure. + */ +struct mpeg_smoothing_buffer_descriptor { +	struct descriptor d; + +  EBIT4(uint64_t reserved_1  		: 2; , +	uint64_t sb_leak_rate		:22; , +	uint64_t reserved_2		: 2; , +	uint64_t sb_size		:22; ); +} __ucsi_packed; + +/** + * Process an mpeg_smoothing_buffer_descriptor. + * + * @param d The generic descriptor structure. + * @return Pointer to mpeg_smoothing_buffer_descriptor, or NULL on error. + */ +static inline struct mpeg_smoothing_buffer_descriptor* +	mpeg_smoothing_buffer_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_smoothing_buffer_descriptor) - 2)) +		return NULL; + +	bswap48((uint8_t*) d + 2); + +	return (struct mpeg_smoothing_buffer_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/std_descriptor.h b/lib/libucsi/mpeg/std_descriptor.h new file mode 100644 index 0000000..2625a41 --- /dev/null +++ b/lib/libucsi/mpeg/std_descriptor.h @@ -0,0 +1,62 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_STD_DESCRIPTOR +#define _UCSI_MPEG_STD_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_std_descriptor structure. + */ +struct mpeg_std_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved	: 7; , +	uint8_t leak_valid_flag	: 1; ); +} __ucsi_packed; + +/** + * Process an mpeg_std_descriptor. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_std_descriptor, or NULL on error. + */ +static inline struct mpeg_std_descriptor* +	mpeg_std_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_std_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_std_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/system_clock_descriptor.h b/lib/libucsi/mpeg/system_clock_descriptor.h new file mode 100644 index 0000000..681641f --- /dev/null +++ b/lib/libucsi/mpeg/system_clock_descriptor.h @@ -0,0 +1,65 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_SYSTEM_CLOCK_DESCRIPTOR +#define _UCSI_MPEG_SYSTEM_CLOCK_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_system_clock_descriptor structure. + */ +struct mpeg_system_clock_descriptor { +	struct descriptor d; + +  EBIT3(uint8_t external_clock_reference_indicator	: 1; , +	uint8_t reserved_1				: 1; , +	uint8_t clock_accuracy_integer			: 6; ); +  EBIT2(uint8_t clock_accuracy_exponent			: 3; , +	uint8_t reserved_2				: 5; ); +} __ucsi_packed; + +/** + * Process an mpeg_system_clock_descriptor. + * + * @param d The generic descriptor structure. + * @return Pointer to a mpeg_system_clock_descriptor structure, or NULL on error. + */ +static inline struct mpeg_system_clock_descriptor* +	mpeg_system_clock_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_system_clock_descriptor) - 2)) +		return NULL; + +	return (struct mpeg_system_clock_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/target_background_grid_descriptor.h b/lib/libucsi/mpeg/target_background_grid_descriptor.h new file mode 100644 index 0000000..7394e82 --- /dev/null +++ b/lib/libucsi/mpeg/target_background_grid_descriptor.h @@ -0,0 +1,66 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_TARGET_BACKGROUND_GRID_DESCRIPTOR +#define _UCSI_MPEG_TARGET_BACKGROUND_GRID_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * mpeg_target_background_grid_descriptor structure. + */ +struct mpeg_target_background_grid_descriptor { +	struct descriptor d; + +  EBIT3(uint32_t horizontal_size		: 14; , +	uint32_t vertical_size			: 14; , +	uint32_t aspect_ratio_information	: 4;  ); +} __ucsi_packed; + +/** + * Process an mpeg_target_background_grid_descriptor structure. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_target_background_grid_descriptor structure, or + * NULL on error. + */ +static inline struct mpeg_target_background_grid_descriptor* +	mpeg_target_background_grid_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_target_background_grid_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct mpeg_target_background_grid_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/tsdt_section.c b/lib/libucsi/mpeg/tsdt_section.c new file mode 100644 index 0000000..fec9dd7 --- /dev/null +++ b/lib/libucsi/mpeg/tsdt_section.c @@ -0,0 +1,34 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 <libucsi/mpeg/tsdt_section.h> + +struct mpeg_tsdt_section * mpeg_tsdt_section_codec(struct section_ext * ext) +{ +	uint8_t * buf = (uint8_t *)ext; +	size_t pos = sizeof(struct section_ext); + +	if (verify_descriptors(buf + pos, +	    section_ext_length(ext) - sizeof(struct mpeg_tsdt_section))) +		return NULL; + +	return (struct mpeg_tsdt_section *)ext; +} diff --git a/lib/libucsi/mpeg/tsdt_section.h b/lib/libucsi/mpeg/tsdt_section.h new file mode 100644 index 0000000..2bbae02 --- /dev/null +++ b/lib/libucsi/mpeg/tsdt_section.h @@ -0,0 +1,94 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_TSDT_SECTION_H +#define _UCSI_MPEG_TSDT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/section.h> + +/** + * mpeg_tsdt_section structure. + */ +struct mpeg_tsdt_section { +	struct section_ext head; + +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process an mpeg_tsdt_section structure. + * + * @param section Pointer to the section_ext structure. + * @return Pointer to the mpeg_tsdt_section structure, or NULL on error. + */ +extern struct mpeg_tsdt_section *mpeg_tsdt_section_codec(struct section_ext *section); + +/** + * Convenience iterator for descriptors field. + * + * @param tsdt Pointer to the mpeg_tsdt_section structure. + * @param pos Variable holding a pointer to the current descriptor. + */ +#define mpeg_tsdt_section_descriptors_for_each(tsdt, pos) \ +	for ((pos) = mpeg_tsdt_section_descriptors_first(tsdt); \ +	     (pos); \ +	     (pos) = mpeg_tsdt_section_descriptors_next(tsdt, pos)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	mpeg_tsdt_section_descriptors_first(struct mpeg_tsdt_section * tsdt) +{ +	size_t pos = sizeof(struct mpeg_tsdt_section); + +	if (pos >= section_ext_length(&tsdt->head)) +		return NULL; + +	return (struct descriptor*)((uint8_t *) tsdt + pos); +} + +static inline struct descriptor * +	mpeg_tsdt_section_descriptors_next(struct mpeg_tsdt_section *tsdt, +					   struct descriptor* pos) +{ +	return next_descriptor((uint8_t *) tsdt + sizeof(struct mpeg_tsdt_section), +			      section_ext_length(&tsdt->head) - sizeof(struct mpeg_tsdt_section), +			      pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/types.h b/lib/libucsi/mpeg/types.h new file mode 100644 index 0000000..300cb23 --- /dev/null +++ b/lib/libucsi/mpeg/types.h @@ -0,0 +1,127 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_MPEG_TYPES_H +#define _UCSI_MPEG_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Known stream types. + */ +enum { +	MPEG_STREAM_TYPE_ISO11172_VIDEO    = 0x01, +	MPEG_STREAM_TYPE_ISO13818_2_VIDEO    = 0x02, +	MPEG_STREAM_TYPE_ISO11172_AUDIO    = 0x03, +	MPEG_STREAM_TYPE_ISO13818_3_AUDIO    = 0x04, +	MPEG_STREAM_TYPE_ISO13818_1_PRIVATE_SECTIONS = 0x05, +	MPEG_STREAM_TYPE_ISO13818_1_PRIVATE_PES  = 0x06, +	MPEG_STREAM_TYPE_ISO13522_MHEG     = 0x07, +	MPEG_STREAM_TYPE_ISO13818_DSMCC    = 0x08, +	MPEG_STREAM_TYPE_ITUH222_1     = 0x09, +	MPEG_STREAM_TYPE_ISO13818_6_A    = 0x0a, +	MPEG_STREAM_TYPE_ISO13818_6_B    = 0x0b, +	MPEG_STREAM_TYPE_ISO13818_6_C    = 0x0c, +	MPEG_STREAM_TYPE_ISO13818_6_D    = 0x0d, +	MPEG_STREAM_TYPE_ISO13818_1_AUX    = 0x0e, +	MPEG_STREAM_TYPE_ISO13818_7_AUDIO_ADTS = 0x0f, +	MPEG_STREAM_TYPE_ISO14496_2_VISUAL   = 0x10, +	MPEG_STREAM_TYPE_ISO14496_3_AUDIO_LATM = 0x11, +	MPEG_STREAM_TYPE_ISO14496_1_PES    = 0x12, +	MPEG_STREAM_TYPE_ISO14496_1_SECTIONS   = 0x13, +	MPEG_STREAM_TYPE_ISO14496_6_SYNCDOWNLOAD = 0x14, +	MPEG_STREAM_TYPE_METADATA_PES    = 0x15, +	MPEG_STREAM_TYPE_METADATA_SECTIONS   = 0x16, +	MPEG_STREAM_TYPE_METADATA_DSMCC_DATA   = 0x17, +	MPEG_STREAM_TYPE_METADATA_DSMCC_OBJECT = 0x18, +	MPEG_STREAM_TYPE_METADATA_SYNCDOWNLOAD = 0x19, +}; + +/** + * Metadata formats + */ +enum { +	MPEG_METADATA_FORMAT_ISO15938_1_TEM				= 0x01, +	MPEG_METADATA_FORMAT_ISO15938_1_BIM				= 0x02, +	MPEG_METADATA_FORMAT_METADATA_APPLICATION_FORMAT		= 0x3F, +	MPEG_METADATA_FORMAT_METADATA_APPLICATION_FORMAT_ID		= 0xFF, +}; + +/** + * MPEG 4 audio profile and levels. + */ +enum { +	MPEG4_AUDIO_PROFILE_MAIN_LEVEL_1		= 0x10, +	MPEG4_AUDIO_PROFILE_MAIN_LEVEL_2		= 0x11, +	MPEG4_AUDIO_PROFILE_MAIN_LEVEL_3		= 0x12, +	MPEG4_AUDIO_PROFILE_MAIN_LEVEL_4		= 0x13, + +	MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_1		= 0x18, +	MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_2		= 0x19, +	MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_3		= 0x1a, +	MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_4		= 0x1b, + +	MPEG4_AUDIO_PROFILE_SPEECH_LEVEL_1		= 0x20, +	MPEG4_AUDIO_PROFILE_SPEECH_LEVEL_2		= 0x21, + +	MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_1		= 0x28, +	MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_2		= 0x29, +	MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_3		= 0x2a, + +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_1			= 0x30, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_2			= 0x31, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_3			= 0x32, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_4			= 0x33, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_5			= 0x34, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_6			= 0x35, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_7			= 0x36, +	MPEG4_AUDIO_PROFILE_HQ_LEVEL_8			= 0x37, + +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_1		= 0x38, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_2		= 0x39, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_3		= 0x3a, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_4		= 0x3b, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_5		= 0x3c, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_6		= 0x3d, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_7		= 0x3e, +	MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_8		= 0x3f, + +	MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_1		= 0x40, +	MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_2		= 0x41, +	MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_3		= 0x42, +	MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_4		= 0x43, + +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_1		= 0x48, +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_2		= 0x49, +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_3		= 0x4a, +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_4		= 0x4b, +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_5		= 0x4c, +	MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_6		= 0x4d, +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/video_stream_descriptor.h b/lib/libucsi/mpeg/video_stream_descriptor.h new file mode 100644 index 0000000..14e9196 --- /dev/null +++ b/lib/libucsi/mpeg/video_stream_descriptor.h @@ -0,0 +1,101 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_VIDEO_STREAM_DESCRIPTOR +#define _UCSI_MPEG_VIDEO_STREAM_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * The mpeg_video_stream_descriptor structure + */ +struct mpeg_video_stream_descriptor { +	struct descriptor d; + +  EBIT5(uint8_t multiple_frame_rate_flag	: 1; , +	uint8_t frame_rate_code			: 4; , +	uint8_t mpeg_1_only_flag		: 1; , +	uint8_t constrained_parameter_flag	: 1; , +	uint8_t still_picture_flag		: 1; ); +	/* if (mpeg_1_only_flag == 0) struct mpeg_video_stream_extra extra */ +} __ucsi_packed; + +/** + * The mpeg_video_stream_extra - only present in non-MPEG1-only streams. + */ +struct mpeg_video_stream_extra { +	uint8_t profile_and_level_indication; +  EBIT3(uint8_t chroma_format			: 2; , +	uint8_t frame_rate_extension		: 1; , +	uint8_t reserved			: 5; ); +} __ucsi_packed; + +/** + * Process an mpeg_video_stream_descriptor structure. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_video_stream_descriptor, or NULL on error. + */ +static inline struct mpeg_video_stream_descriptor* +	mpeg_video_stream_descriptor_codec(struct descriptor* d) +{ +	struct mpeg_video_stream_descriptor* vsd = +			(struct mpeg_video_stream_descriptor*) d; + +	if (d->len < (sizeof(struct mpeg_video_stream_descriptor) - 2)) +		return NULL; + +	if (!vsd->mpeg_1_only_flag) { +		if (d->len != (sizeof(struct mpeg_video_stream_descriptor) + +				  sizeof(struct mpeg_video_stream_extra) - 2)) +			return NULL; +	} + +	return (struct mpeg_video_stream_descriptor*) d; +} + +/** + * Get a pointer to the mpeg_video_stream_extra structure. + * + * @param d Pointer to the mpeg_video_stream_descriptor structure. + * @return Pointer to the mpeg_video_stream_extra structure, or NULL on error. + */ +static inline struct mpeg_video_stream_extra* +	mpeg_video_stream_descriptor_extra(struct mpeg_video_stream_descriptor* d) +{ +	if (d->mpeg_1_only_flag != 0) +		return NULL; + +	return (struct mpeg_video_stream_extra*) +		((uint8_t*) d + sizeof(struct mpeg_video_stream_descriptor)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/mpeg/video_window_descriptor.h b/lib/libucsi/mpeg/video_window_descriptor.h new file mode 100644 index 0000000..a9a63c7 --- /dev/null +++ b/lib/libucsi/mpeg/video_window_descriptor.h @@ -0,0 +1,64 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * 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 _UCSI_MPEG_VIDEO_WINDOW_DESCRIPTOR +#define _UCSI_MPEG_VIDEO_WINDOW_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> + +/** + * mpeg_video_window_descriptor structure. + */ +struct mpeg_video_window_descriptor { +	struct descriptor d; + +  EBIT3(uint32_t horizontal_offset		: 14; , +	uint32_t vertical_offset		: 14; , +	uint32_t window_priority		: 4;  ); +} __ucsi_packed; + +/** + * Process an mpeg_video_window_descriptor. + * + * @param d Pointer to the generic descriptor structure. + * @return Pointer to the mpeg_video_window_descriptor structure, or NULL on error. + */ +static inline struct mpeg_video_window_descriptor* +	mpeg_video_window_descriptor_codec(struct descriptor* d) +{ +	if (d->len != (sizeof(struct mpeg_video_window_descriptor) - 2)) +		return NULL; + +	bswap32((uint8_t*) d + 2); + +	return (struct mpeg_video_window_descriptor*) d; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/section.h b/lib/libucsi/section.h new file mode 100644 index 0000000..53ad07f --- /dev/null +++ b/lib/libucsi/section.h @@ -0,0 +1,253 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_SECTION_H +#define _UCSI_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/endianops.h> +#include <libucsi/descriptor.h> +#include <libucsi/crc32.h> +#include <stdint.h> +#include <string.h> + +#define CRC_SIZE 4 + + +/** + * Generic section header. + */ +struct section { +	uint8_t	table_id; +  EBIT4(uint16_t syntax_indicator	: 1; , +	uint16_t private_indicator	: 1; , /* 2.4.4.10 */ +	uint16_t reserved 		: 2; , +	uint16_t length			:12; ); +} __ucsi_packed; + +/** + * Generic extended section header structure. + */ +struct section_ext { +	uint8_t	table_id; +  EBIT4(uint16_t syntax_indicator	: 1; , +	uint16_t private_indicator	: 1; , /* 2.4.4.10 */ +	uint16_t reserved		: 2; , +	uint16_t length			:12; ); + +	uint16_t table_id_ext; +  EBIT3(uint8_t reserved1		: 2; , +	uint8_t version_number		: 5; , +	uint8_t current_next_indicator	: 1; ); +	uint8_t section_number; +	uint8_t last_section_number; +} __ucsi_packed; + +/** + * Structure for keeping track of sections of a PSI table. + */ +struct psi_table_state { +	uint8_t version_number; +	uint16_t next_section_number; +	uint8_t complete:1; +	uint8_t new_table:1; +} __ucsi_packed; + + +/** + * Determine the total length of a section, including the header. + * + * @param section The parsed section structure. + * @return The length. + */ +static inline size_t section_length(struct section *section) +{ +	return section->length + sizeof(struct section); +} + +/** + * Determine the total length of an extended section, including the header, + * but omitting the CRC. + * + * @param section The parsed section_ext structure. + * @return The length. + */ +static inline size_t section_ext_length(struct section_ext * section) +{ +	return section->length + sizeof(struct section) - CRC_SIZE; +} + +/** + * Process a section structure in-place. + * + * @param buf Pointer to the data. + * @param len Length of data. + * @return Pointer to the section structure, or NULL if invalid. + */ +static inline struct section * section_codec(uint8_t * buf, size_t len) +{ +	struct section * ret = (struct section *)buf; + +	if (len < 3) +		return NULL; + +	bswap16(buf+1); + +	if (len != ret->length + 3U) +		return NULL; + +	return ret; +} + +/** + * Some sections have a CRC even though they are not section_exts. + * This function is to allow checking of them. + * + * @param section Pointer to the processed section structure. + * @return Nonzero on error, or 0 if the CRC was correct. + */ +static inline int section_check_crc(struct section *section) +{ +	uint8_t * buf = (uint8_t *) section; +	size_t len = section_length(section); +	uint32_t crc; + +	/* the crc check has to be performed on the unswapped data */ +	bswap16(buf+1); +	crc = crc32(CRC32_INIT, buf, len); +	bswap16(buf+1); + +	/* the crc check includes the crc value, +	 * the result should therefore be zero. +	 */ +	if (crc) +		return -1; +	return 0; +} + + +/** + * Decode an extended section structure. + * + * @param section Pointer to the processed section structure. + * @param check_crc If 1, the CRC of the section will also be checked. + * @return Pointer to the parsed section_ext structure, or NULL if invalid. + */ +static inline struct section_ext * section_ext_decode(struct section * section, +						      int check_crc) +{ +	if (section->syntax_indicator == 0) +		return NULL; + +	if (check_crc) { +		if (section_check_crc(section)) +			return NULL; +	} + +	bswap16((uint8_t *)section + sizeof(struct section)); + +	return (struct section_ext *)section; +} + +/** + * Encode an extended section structure for transmission. + * + * @param section Pointer to the section_ext structure. + * @param update_crc If 1, the CRC of the section will also be updated. + * @return Pointer to the encoded section_ext structure, or NULL if invalid. + */ +static inline struct section_ext * section_ext_encode(struct section_ext* section, +						      int update_crc) +{ +	if (section->syntax_indicator == 0) +		return NULL; + +	bswap16((uint8_t *)section + sizeof(struct section)); + +	if (update_crc) { +		uint8_t * buf = (uint8_t *) section; +		int len = sizeof(struct section) + section->length; +		uint32_t crc; + +		/* the crc has to be performed on the swapped data */ +		bswap16(buf+1); +		crc = crc32(CRC32_INIT, buf, len-4); +		bswap16(buf+1); + +		/* update the CRC */ +		*((uint32_t*) (buf+len-4)) = crc; +		bswap32(buf+len-4); +	} + +	return (struct section_ext *)section; +} + +/** + * Reset a psi_table_state structure. + * + * @param tstate The structure to reset. + */ +static inline void psi_table_state_reset(struct psi_table_state *tstate) +{ +	tstate->version_number = 0xff; +} + +/** + * Check if a supplied section_ext is something we want to process. + * + * @param section The parsed section_ext structure. + * @param tstate The state structure for this PSI table. + * @return 0=> not useful. nonzero => useful. + */ +static inline int section_ext_useful(struct section_ext *section, struct psi_table_state *tstate) +{ +	if ((section->version_number == tstate->version_number) && tstate->complete) +		return 0; +	if (section->version_number != tstate->version_number) { +	        if (section->section_number != 0) +	                return 0; + +		tstate->next_section_number = 0; +		tstate->complete = 0; +		tstate->version_number = section->version_number; +		tstate->new_table = 1; +	} else if (section->section_number == tstate->next_section_number) { +		tstate->new_table = 0; +	} else { +		return 0; +	} + +	tstate->next_section_number++; +	if (section->last_section_number < tstate->next_section_number) { +		tstate->complete = 1; +	} + +	return 1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/section_buf.c b/lib/libucsi/section_buf.c new file mode 100644 index 0000000..35d465e --- /dev/null +++ b/lib/libucsi/section_buf.c @@ -0,0 +1,173 @@ +/* + * section and descriptor parser + * + * 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 <errno.h> +#include <string.h> +#include "section_buf.h" + +#define SECTION_HDR_SIZE 3 +#define SECTION_PAD 0xff + +int section_buf_init(struct section_buf *section, int max) +{ +	if (max < SECTION_HDR_SIZE) +		return -EINVAL; + +	memset(section, 0, sizeof(struct section_buf)); +	section->max = max; /* max size of data */ +	section->len = SECTION_HDR_SIZE; +	section->wait_pdu = 1; + +	return 0; +} + +int section_buf_add(struct section_buf *section, uint8_t* frag, int len, int *section_status) +{ +	int copy; +	int used = 0; +	uint8_t *data; +	uint8_t *pos = (uint8_t*) section + sizeof(struct section_buf) + section->count; + +	/* have we finished? */ +	if (section->header && (section->len == section->count)) { +		*section_status = 1; +		return 0; +	} + +	/* skip over section padding bytes */ +	*section_status = 0; +	if (section->count == 0) { +		while(len && (*frag == SECTION_PAD)) { +			frag++; +			len--; +			used++; +		} + +		if (len == 0) +			return used; +	} + +	/* grab the header to get the section length */ +	if (!section->header) { +		/* copy the header frag */ +		copy = SECTION_HDR_SIZE - section->count; +		if (copy > len) +			copy = len; +		memcpy(pos, frag, copy); +		section->count += copy; +		pos += copy; +		frag += copy; +		used += copy; +		len -= copy; + +		/* we need 3 bytes for the section header */ +		if (section->count != SECTION_HDR_SIZE) +			return used; + +		/* work out the length & check it isn't too big */ +		data = (uint8_t*) section + sizeof(struct section_buf); +		section->len = SECTION_HDR_SIZE + (((data[1] & 0x0f) << 8) | data[2]); +		if (section->len > section->max) { +			*section_status = -ERANGE; +			return len + used; +		} + +		/* update fields */ +		section->header = 1; +	} + +	/* accumulate frag */ +	copy = section->len - section->count; +	if (copy > len) +		copy = len; +	memcpy(pos, frag, copy); +	section->count += copy; +	used += copy; + +	/* have we finished? */ +	if (section->header && (section->len == section->count)) +		*section_status = 1; + +	/* return number of bytes used */ +	return used; +} + +int section_buf_add_transport_payload(struct section_buf *section, +				      uint8_t* payload, int len, +				      int pdu_start, int *section_status) +{ +	int used = 0; +	int tmp; + +	/* have we finished? */ +	if (section->header && (section->len == section->count)) { +		*section_status = 1; +		return 0; +	} + +	/* don't bother if we're waiting for a PDU */ +	*section_status = 0; +	if (section->wait_pdu && (!pdu_start)) +		return len; + +	/* if we're at a PDU start, we need extra handling for the extra first +	 * byte giving the offset to the start of the next section. */ +	if (pdu_start) { +		/* we have received a pdu */ +		section->wait_pdu = 0; + +		/* work out the offset to the _next_ payload */ +		int offset = payload[0]; +		if ((offset+1) > len) { +			section->wait_pdu = 1; +			*section_status = -EINVAL; +			return len; +		} + +		/* accumulate the end if we need to */ +		if (section->count != 0) { +			/* add the final fragment. */ +			tmp = section_buf_add(section, payload + 1, offset, section_status); + +			/* the stream said this was the final fragment +			 * (PDU START bit) - check that it really was! */ +			if ((tmp != offset) || section_buf_remaining(section) || (*section_status != 1)) { +				*section_status = -ERANGE; +				section->wait_pdu = 1; +				return 1 + tmp; +			} + +			/* it is complete - return the number of bytes we used */ +			return 1 + tmp; +		} + +		/* otherwise, we skip the end of the previous section, and +		 * start accumulating the new data. */ +		used = 1 + offset; +	} + +	/* ok, just accumulate the data as normal */ +	tmp = section_buf_add(section, payload+used, len - used, section_status); +	if (*section_status < 0) { +		section->wait_pdu = 1; +	} + +	return used + tmp; +} diff --git a/lib/libucsi/section_buf.h b/lib/libucsi/section_buf.h new file mode 100644 index 0000000..52d2f84 --- /dev/null +++ b/lib/libucsi/section_buf.h @@ -0,0 +1,124 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_SECTION_BUF_H +#define _UCSI_SECTION_BUF_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> + +#define DVB_MAX_SECTION_BYTES 4096 + +/** + * Buffer used to keep track of  section fragments. You should allocate an + * area of memory of size (sizeof(section_buf) + <maxsectionsize>), and pass that area + * to section_buf_init() to set it up. + */ +struct section_buf { +	uint32_t max;      /* maximum size of section - setup by section_buf_init() */ +	uint32_t count;    /* number of bytes currently accumulated */ +	uint32_t len;      /* total number of bytes expected in the complete section */ +	uint8_t header:1;  /* flag indicating the section header has been commpletely received */ +	uint8_t wait_pdu:1;/* flag indicating to wait till the next PDU start */ +	/* uint8_t data[] */ +}; + +/** + * Initialise a section_buf structure. + * + * @param section The section_buf to initialise. + * @param max Maximum number of bytes in section (must be > 3) + * @return 0 on success, nonzero on error. + */ +extern int section_buf_init(struct section_buf *section, int max); + +/** + * Reset a section_buf structure (e.g. if a discontinuity occurred). The + * section_buf will wait for the first PDU start indicator. + * + * @param section The section_buf to reset. + */ +static inline void section_buf_reset(struct section_buf *section) +{ +	int tmp = section->wait_pdu; +	section_buf_init(section, section->max); +	section->wait_pdu = tmp; +} + +/** + * Add a data fragment to a section_buf. + * + * @param section section_buf to add to. + * @param frag Pointer to data fragment. + * @param len Number of bytes of data. + * @param section_status 0: nothing special. 1: section complete. -ERANGE indicates that the + * section is larger than section->max. + * @return Number of bytes which were consumed. + */ +extern int section_buf_add(struct section_buf *section, uint8_t* frag, int len, int *section_status); + +/** + * Add a transport packet PSI payload to a section_buf. This takes into account + * the extra byte present in PDU_START flagged packets. + * + * @param section section_buf to add to. + * @param payload Pointer to packet payload data. + * @param len Number of bytes of data. + * @param pdu_start True if the payload_unit_start_indicator flag was set in the + * TS packet. + * @param section_status 0: nothing special. 1: section complete. -ERANGE indicates that the + * section is larger than section->max. -EINVAL indicates the pointer_field was completely + * invalid (too large). + */ +extern int section_buf_add_transport_payload(struct section_buf *section, +					     uint8_t* payload, int len, +					     int pdu_start, int *section_status); + +/** + * Get the number of bytes left to be received in a section_buf. + * + * @param section The section_buf concerned. + * @return The number of bytes. + */ +static inline int section_buf_remaining(struct section_buf *section) +{ +	return section->len - section->count; +} + +/** + * Return a pointer to the start of the data in the section_buf. + * + * @param section The section_buf concerned. + * @return The data. + */ +static inline uint8_t* section_buf_data(struct section_buf *section) +{ +	return (uint8_t*) section + sizeof(struct section_buf); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/testrecord.txt b/lib/libucsi/testrecord.txt new file mode 100644 index 0000000..84d56aa --- /dev/null +++ b/lib/libucsi/testrecord.txt @@ -0,0 +1,146 @@ +libucsi test record. Anything without PASS is either not tested, or is +currently broken. + +Testing means (a) ensure there are no segfaults etc. (b) dump the raw hex, +decode it by hand, and check it matches the output. + +Sections: +PASS mpeg/cat_section.h +     mpeg/odsmt_section.h +PASS mpeg/pat_section.h +PASS mpeg/pmt_section.h +     mpeg/tsdt_section.h +     mpeg/metadata_section.h + +PASS dvb/bat_section.h +     dvb/dit_section.h +PASS dvb/eit_section.h +     dvb/int_section.h +PASS dvb/nit_section.h +     dvb/rst_section.h +PASS dvb/sdt_section.h +     dvb/sit_section.h +PASS dvb/st_section.h +PASS dvb/tdt_section.h +PASS dvb/tot_section.h +     dvb/tva_container_section.h + +PASS atsc/cvct_section.h +     atsc/dccsct_section.h +     atsc/dcct_section.h +PASS atsc/eit_section.h +PASS atsc/ett_section.h +PASS atsc/mgt_section.h +     atsc/rrt_section.h +PASS atsc/stt_section.h +PASS atsc/tvct_section.h + +Descriptors: +PASS mpeg/audio_stream_descriptor.h +PASS mpeg/ca_descriptor.h +     mpeg/content_labelling_descriptor.h +PASS mpeg/copyright_descriptor.h +PASS mpeg/data_stream_alignment_descriptor.h +PASS mpeg/external_es_id_descriptor.h +     mpeg/fmc_descriptor.h +PASS mpeg/fmxbuffer_size_descriptor.h +     mpeg/hierarchy_descriptor.h +     mpeg/ibp_descriptor.h +     mpeg/iod_descriptor.h +PASS mpeg/iso_639_language_descriptor.h +PASS mpeg/maximum_bitrate_descriptor.h +     mpeg/metadata_descriptor.h +     mpeg/metadata_pointer_descriptor.h +     mpeg/metadata_std_descriptor.h +     mpeg/mpeg4_audio_descriptor.h +     mpeg/mpeg4_video_descriptor.h +     mpeg/multiplex_buffer_descriptor.h +PASS mpeg/multiplex_buffer_utilization_descriptor.h +     mpeg/muxcode_descriptor.h +PASS mpeg/private_data_indicator_descriptor.h +PASS mpeg/registration_descriptor.h +     mpeg/sl_descriptor.h +PASS mpeg/smoothing_buffer_descriptor.h +PASS mpeg/std_descriptor.h +PASS mpeg/system_clock_descriptor.h +     mpeg/target_background_grid_descriptor.h +PASS mpeg/video_stream_descriptor.h +     mpeg/video_window_descriptor.h + +     dvb/ac3_descriptor.h +     dvb/adaptation_field_data_descriptor.h +     dvb/ait_application_descriptor.h +     dvb/ait_application_icons_descriptor.h +     dvb/ait_application_name_descriptor.h +     dvb/ait_external_application_authorisation_descriptor.h +     dvb/ancillary_data_descriptor.h +     dvb/announcement_support_descriptor.h +     dvb/application_signalling_descriptor.h +PASS dvb/bouquet_name_descriptor.h +PASS dvb/ca_identifier_descriptor.h +     dvb/cable_delivery_descriptor.h +     dvb/cell_frequency_link_descriptor.h +     dvb/cell_list_descriptor.h +PASS dvb/component_descriptor.h +PASS dvb/content_descriptor.h +     dvb/content_identifier_descriptor.h +     dvb/country_availability_descriptor.h +     dvb/data_broadcast_descriptor.h +PASS dvb/data_broadcast_id_descriptor.h +     dvb/default_authority_descriptor.h +     dvb/dsng_descriptor.h +     dvb/extended_event_descriptor.h +PASS dvb/frequency_list_descriptor.h +PASS dvb/linkage_descriptor.h +PASS dvb/local_time_offset_descriptor.h +     dvb/mhp_data_broadcast_id_descriptor.h +     dvb/mosaic_descriptor.h +     dvb/multilingual_bouquet_name_descriptor.h +PASS dvb/multilingual_component_descriptor.h +     dvb/multilingual_network_name_descriptor.h +     dvb/multilingual_service_name_descriptor.h +PASS dvb/network_name_descriptor.h +     dvb/nvod_reference_descriptor.h +PASS dvb/parental_rating_descriptor.h +     dvb/partial_transport_stream_descriptor.h +     dvb/pdc_descriptor.h +PASS dvb/private_data_specifier_descriptor.h +     dvb/related_content_descriptor.h +     dvb/rnt_rar_over_dvb_stream_descriptor.h +     dvb/rnt_rar_over_ip_descriptor.h +     dvb/rnt_rnt_scan_descriptor.h +     dvb/s2_satellite_delivery_descriptor.h +PASS dvb/satellite_delivery_descriptor.h +     dvb/scrambling_descriptor.h +     dvb/service_availablility_descriptor.h +PASS dvb/service_descriptor.h +     dvb/service_identifier_descriptor.h +PASS dvb/service_list_descriptor.h +     dvb/service_move_descriptor.h +PASS dvb/short_event_descriptor.h +     dvb/short_smoothing_buffer_descriptor.h +PASS dvb/stream_identifier_descriptor.h +PASS dvb/stuffing_descriptor.h +PASS dvb/subtitling_descriptor.h +     dvb/telephone_descriptor.h +     dvb/teletext_descriptor.h +PASS dvb/terrestrial_delivery_descriptor.h +     dvb/time_shifted_event_descriptor.h +     dvb/time_shifted_service_descriptor.h +     dvb/transport_stream_descriptor.h +     dvb/tva_id_descriptor.h +     dvb/vbi_data_descriptor.h +     dvb/vbi_teletext_descriptor.h + +PASS atsc/ac3_descriptor.h +PASS atsc/caption_service_descriptor.h +     atsc/component_name_descriptor.h +PASS atsc/content_advisory_descriptor.h +     atsc/dcc_arriving_request_descriptor.h +     atsc/dcc_departing_request_descriptor.h +PASS atsc/extended_channel_name_descriptor.h +     atsc/genre_descriptor.h +     atsc/rc_descriptor.h +PASS atsc/service_location_descriptor.h +PASS atsc/stuffing_descriptor.h +     atsc/time_shifted_service_descriptor.h diff --git a/lib/libucsi/transport_packet.c b/lib/libucsi/transport_packet.c new file mode 100644 index 0000000..ca6c2e1 --- /dev/null +++ b/lib/libucsi/transport_packet.c @@ -0,0 +1,256 @@ +/* + * section and descriptor parser + * + * 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 "transport_packet.h" + +#define CONTINUITY_VALID 0x80 +#define CONTINUITY_DUPESEEN 0x40 + +int transport_packet_values_extract(struct transport_packet *pkt, +				    struct transport_values *out, + 				    enum transport_value extract) +{ +	uint8_t *end = (uint8_t*) pkt + TRANSPORT_PACKET_LENGTH; +	uint8_t *adapend; +	uint8_t *pos = (uint8_t*) pkt + sizeof(struct transport_packet); +	enum transport_value extracted = 0; +	enum transport_adaptation_flags adapflags = 0; +	enum transport_adaptation_extension_flags adapextflags = 0; +	int adaplength = 0; +	int adapextlength = 0; + +	/* does the packet contain an adaptation field ? */ +	if ((pkt->adaptation_field_control & 2) == 0) +		goto extract_payload; + +	/* get the adaptation field length and skip the byte */ +	adaplength = *pos++; + +	/* do we actually have any adaptation data? */ +	if (adaplength == 0) +		goto extract_payload; + +	/* sanity check */ +	adapend = pos + adaplength; +	if (adapend > end) +		return -1; + +	/* extract the adaptation flags (we must have at least 1 byte to be here) */ +	adapflags = *pos++; + +	/* do we actually want anything else? */ +	if ((extract & 0xffff) == 0) +		goto extract_payload; + +	/* PCR? */ +	if (adapflags & transport_adaptation_flag_pcr) { +		if ((pos+6) > adapend) +			return -1; + +		if (extract & transport_value_pcr) { +			uint64_t base = ((uint64_t) pos[0] << 25) | +					((uint64_t) pos[1] << 17) | +					((uint64_t) pos[2] << 9) | +					((uint64_t) pos[3] << 1) | +					((uint64_t) pos[4] >> 7); +			uint64_t ext = (((uint64_t) pos[4] & 1) << 8) | +					(uint64_t) pos[5]; +			out->pcr= base * 300ULL + ext; +			extracted |= transport_value_pcr; +		} +		pos += 6; +	} + +	/* OPCR? */ +	if (adapflags & transport_adaptation_flag_opcr) { +		if ((pos+6) > adapend) +			return -1; + +		if (extract & transport_value_opcr) { +			uint64_t base = ((uint64_t) pos[0] << 25) | +					((uint64_t) pos[1] << 17) | +					((uint64_t) pos[2] << 9) | +					((uint64_t) pos[3] << 1) | +					((uint64_t) pos[4] >> 7); +			uint64_t ext = (((uint64_t) pos[4] & 1) << 8) | +					(uint64_t) pos[5]; +			out->opcr= base * 300ULL + ext; +			extracted |= transport_value_opcr; +		} +		pos += 6; +	} + +	/* splice countdown? */ +	if (adapflags & transport_adaptation_flag_splicing_point) { +		if ((pos+1) > adapend) +			return -1; + +		if (extract & transport_value_splice_countdown) { +			out->splice_countdown = *pos; +			extracted |= transport_value_splice_countdown; +		} +		pos++; +	} + +	/* private data? */ +	if (adapflags & transport_adaptation_flag_private_data) { +		if ((pos+1) > adapend) +			return -1; +		if ((pos+1+*pos) > adapend) +			return -1; + +		if (extract & transport_value_private_data) { +			out->private_data_length = *pos; +			out->private_data = pos + 1; +			extracted |= transport_value_private_data; +		} +		pos += 1 + *pos; +	} + +	/* is there an adaptation extension? */ +	if (!(adapflags & transport_adaptation_flag_extension)) +		goto extract_payload; + +	/* get/check the length */ +	if (pos >= adapend) +		return -1; +	adapextlength = *pos++; +	if ((pos + adapextlength) > adapend) +		return -1; + +	/* do we want/have anything in the adaptation extension? */ +	if (((extract & 0xff00) == 0) || (adapextlength == 0)) +		goto extract_payload; + +	/* extract the adaptation extension flags (we must have at least 1 byte +	 * to be here) */ +	adapextflags = *pos++; + +	/* LTW? */ +	if (adapextflags & transport_adaptation_extension_flag_ltw) { +		if ((pos+2) > adapend) +			return -1; + +		if (extract & transport_value_ltw) { +			if (*pos & 0x80) { +				out->ltw_offset = ((pos[0] & 0x7f) << 8) | +						  (pos[1]); +				extracted |= transport_value_ltw; +			} +		} +		pos += 2; +	} + +	/* piecewise_rate? */ +	if (adapextflags & transport_adaptation_extension_flag_piecewise_rate) { +		if ((pos+3) > adapend) +			return -1; + +		if (extract & transport_value_piecewise_rate) { +			out->piecewise_rate = ((pos[0] & 0x3f) << 16) | +					      (pos[1] << 8) | +					      pos[2]; +			extracted |= transport_value_piecewise_rate; +		} +		pos += 3; +	} + +	/* seamless_splice? */ +	if (adapextflags & transport_adaptation_extension_flag_seamless_splice) { +		if ((pos+5) > adapend) +			return -1; + +		if (extract & transport_value_piecewise_rate) { +			out->splice_type = pos[0] >> 4; +			out->dts_next_au = ((pos[0] & 0x0e) << 29) | +					   (pos[1] << 22) | +					   ((pos[2] & 0xfe) << 14) | +					   (pos[3] << 7) | +					   ((pos[4] & 0xfe) >> 1); +			extracted |= transport_value_seamless_splice; +		} +		pos += 5; +	} + + + +extract_payload: +	/* does the packet contain a payload? */ +	if (pkt->adaptation_field_control & 1) { +		int off = sizeof(struct transport_packet); +		if (pkt->adaptation_field_control & 2) +			off++; +		off += adaplength; + +		out->payload = (uint8_t*) pkt + off; +		out->payload_length = TRANSPORT_PACKET_LENGTH - off; +	} else { +		out->payload = NULL; +		out->payload_length = 0; +	} + +	out->flags = adapflags; +	return extracted; +} + +int transport_packet_continuity_check(struct transport_packet *pkt, +				      int discontinuity_indicator, unsigned char *cstate) +{ +	unsigned char pktcontinuity = pkt->continuity_counter; +	unsigned char prevcontinuity = *cstate & 0x0f; +	unsigned char nextcontinuity; + +	/* NULL packets have undefined continuity */ +	if (transport_packet_pid(pkt) == TRANSPORT_NULL_PID) +		return 0; + +	/* is the state valid? */ +	if (!(*cstate & CONTINUITY_VALID)) { +		*cstate = pktcontinuity | CONTINUITY_VALID; +		return 0; +	} + +	/* check for discontinuity_indicator */ +	if (discontinuity_indicator) { +		*cstate = pktcontinuity | CONTINUITY_VALID; +		return 0; +	} + +	/* only packets with a payload should increment the counter */ +	if (pkt->adaptation_field_control & 1) +		nextcontinuity = (prevcontinuity + 1) & 0xf; +	else +		nextcontinuity = prevcontinuity; + +	/* check for a normal continuity progression */ +	if (nextcontinuity == pktcontinuity) { +		*cstate = pktcontinuity | CONTINUITY_VALID; +		return 0; +	} + +	/* one dupe is allowed */ +	if ((prevcontinuity == pktcontinuity) && (!(*cstate & CONTINUITY_DUPESEEN))) { +		*cstate = pktcontinuity | (CONTINUITY_VALID|CONTINUITY_DUPESEEN); +		return 0; +	} + +	/* continuity error */ +	return -1; +} diff --git a/lib/libucsi/transport_packet.h b/lib/libucsi/transport_packet.h new file mode 100644 index 0000000..6314eca --- /dev/null +++ b/lib/libucsi/transport_packet.h @@ -0,0 +1,195 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_TRANSPORT_PACKET_H +#define _UCSI_TRANSPORT_PACKET_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include "descriptor.h" + +#define TRANSPORT_PACKET_LENGTH 188 +#define TRANSPORT_PACKET_SYNC   0x47 +#define TRANSPORT_MAX_PIDS      0x2000 +#define TRANSPORT_NULL_PID      0x1fff + + +/** + * Enumeration of adaptation field control values. + */ +enum transport_adaptation_field_control { +	transport_adaptation_field_control_reserved		= 0x00, +	transport_adaptation_field_control_payload_only		= 0x01, +	transport_adaptation_field_control_adaptation_only	= 0x02, +	transport_adaptation_field_control_adaptation_payload	= 0x03, +}; + +/** + * Enumeration of scrambling control values. + */ +enum transport_scrambling_control { +	transport_scrambling_control_unscrambled   		= 0x00, +	transport_scrambling_control_user_1			= 0x01, +	transport_scrambling_control_user_2			= 0x02, +	transport_scrambling_control_user_3			= 0x03, +}; + +/** + * Enumeration of adaptation flags. + */ +enum transport_adaptation_flags { +	transport_adaptation_flag_discontinuity			= 0x80, +	transport_adaptation_flag_random_access			= 0x40, +	transport_adaptation_flag_es_priority			= 0x20, +	transport_adaptation_flag_pcr				= 0x10, +	transport_adaptation_flag_opcr				= 0x08, +	transport_adaptation_flag_splicing_point		= 0x04, +	transport_adaptation_flag_private_data			= 0x02, +	transport_adaptation_flag_extension			= 0x01, +}; + +/** + * Enumeration of adaptation extension flags. + */ +enum transport_adaptation_extension_flags { +	transport_adaptation_extension_flag_ltw			= 0x80, +	transport_adaptation_extension_flag_piecewise_rate	= 0x40, +	transport_adaptation_extension_flag_seamless_splice	= 0x20, +}; + +/** + * Enumeration of flags controlling which values to extract using the + * transport_packet_values_extract() function. + */ +enum transport_value { +	/* normal adaptation */ +	transport_value_pcr					= 0x0001, +	transport_value_opcr					= 0x0002, +	transport_value_splice_countdown			= 0x0004, +	transport_value_private_data				= 0x0008, + +	/* extension adaptation */ +	transport_value_ltw					= 0x0100, +	transport_value_piecewise_rate				= 0x0200, +	transport_value_seamless_splice				= 0x0400, +}; + +/** + * Structure describing a transport packet header. + */ +struct transport_packet { +	uint8_t sync_byte; +  EBIT4(uint8_t transport_error_indicator 	: 1; , +	uint8_t payload_unit_start_indicator	: 1; , +	uint8_t transport_priority		: 1; , +	uint8_t pid_hi				: 5; ); +	uint8_t pid_lo; +  EBIT3(uint8_t transport_scrambling_control	: 2; , +	uint8_t adaptation_field_control	: 2; , +	uint8_t continuity_counter		: 4; ); +	/* values */ +} __ucsi_packed; + +/** + * Structure to extract values into using the transport_packet_values_extract() + * function. + */ +struct transport_values { +	enum transport_adaptation_flags flags; 	/* always extracted */ +	uint8_t *payload;     			/* always extracted */ +	uint16_t payload_length;    		/* always extracted */ + +	uint64_t pcr; +	uint64_t opcr; +	uint8_t  splice_countdown; +	uint8_t private_data_length; +	uint8_t *private_data; +	uint16_t ltw_offset; +	uint32_t piecewise_rate; +	uint8_t splice_type; +	uint64_t dts_next_au; +}; + +/** + * Extract the PID from a transport packet. + * + * @param pkt The packet. + * @return The PID. + */ +static inline int transport_packet_pid(struct transport_packet *pkt) +{ +	return (pkt->pid_hi << 8) | (pkt->pid_lo); +} + +/** + * Process a buffer into a transport packet. + * + * @param buf Raw buffer. Note, this function assumes there are 188 bytes available. + * @return transport_packet pointer, or NULL on error. + */ +static inline struct transport_packet *transport_packet_init(unsigned char *buf) +{ +	struct transport_packet *pkt = (struct transport_packet*) buf; + +	if (pkt->sync_byte != TRANSPORT_PACKET_SYNC) +		return NULL; + +	if (transport_packet_pid(pkt) >= TRANSPORT_MAX_PIDS) +		return NULL; + +	return pkt; +} + +/** + * Check the continuity counter for a packet in a PID stream. + * + * @param pkt transport_packet to check. + * @param discontinuity_indicator Set to 1 if the packet's discontinuity_indicator flag is set. + * @param cstate Pointer to a single 8 bit character, used to store state for validating + * continuity. To initialise the state, simply set it to 0 before the first call. + * @return 0 if the continuity was correct, or nonzero on error. cstate will not be updated on error, + * it is up to the caller to clear it to accept the next packet. + */ +extern int transport_packet_continuity_check(struct transport_packet *pkt, +					     int discontinuity_indicator, unsigned char *cstate); + +/** + * Extract selected fields from a transport packet. + * + * @param pkt The packet. + * @param out Destination structure for values. + * @param extract Orred bitmask of enum transport_value - tells it what fields + * to extract if they are available. + * @return < 0 => error. Otherwise, an orred bitmask of enum transport_value + * telling you what fields were successfully extracted. + */ +extern int transport_packet_values_extract(struct transport_packet *pkt, +					   struct transport_values *out, +					   enum transport_value extract); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/types.h b/lib/libucsi/types.h new file mode 100644 index 0000000..b01d79a --- /dev/null +++ b/lib/libucsi/types.h @@ -0,0 +1,36 @@ +/* + * section and descriptor parser + * + * 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 _UCSI_TYPES_H +#define _UCSI_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef uint8_t iso639lang_t[3]; +typedef uint8_t iso639country_t[3]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libdvb2/README b/libdvb2/README deleted file mode 100644 index 049acd6..0000000 --- a/libdvb2/README +++ /dev/null @@ -1,23 +0,0 @@ -Late in 2003 the idea to create a simple DVB library from the code snippets -in the test/utility programs was discussed on the linux-dvb mailing list. -Hopefully someone will invest some time in this project to turn the idea into -reality... - -Here is an outline of what libdvb2 should be, according to my recollection: -(For first hand information search the linux-dvb list archives for "libdvb2".) - -- C -- small: The goal is to make the library usable in *any* DVB project, which -  is easier if the library sticks to the basics. Advanced stuff can be -  done in a second library. What exacty "basic" and "advanced" means -  is subject of discussion, but I want avoid to impose a certain programming -  model (e.g. multi-threaded vw. event-loop) on users of the library. -- a prime target is to establish a standard DVB config and service list -  format, to make this sharable between different applications -- LGPL - -About the name: There already is a libdvb written by the Metzler Bros., -but the main drawback is that it is written in C++ and thus rejected -by many projects. - -Johannes Stezenbach <js@convergence.de>  | 
