diff options
Diffstat (limited to 'kaffeine/src/input/dvb/lib')
199 files changed, 29169 insertions, 0 deletions
diff --git a/kaffeine/src/input/dvb/lib/Makefile.am b/kaffeine/src/input/dvb/lib/Makefile.am new file mode 100644 index 0000000..aa4701c --- /dev/null +++ b/kaffeine/src/input/dvb/lib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libdvbapi libdvben50221 libucsi diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am b/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am new file mode 100644 index 0000000..59f288b --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am @@ -0,0 +1,11 @@ +noinst_LTLIBRARIES = libdvbapi.la + +INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib + +libdvbapi_la_SOURCES = diseqc.c \ + dvbca.c \ + dvbdemux.c \ + dvbfe.c \ + dvbnet.c + +CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.c b/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.c new file mode 100644 index 0000000..8c8771d --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.c @@ -0,0 +1,141 @@ +/* + libdvbfe - a DVB frontend library + + Copyright (C) 2005 Manu Abraham <manu@kromtek.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 +*/ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <linux/dvb/frontend.h> +#include "diseqc.h" +#include <libdvbmisc/dvbmisc.h> + + +int verbose = 1; + +int set_22k_tone(int fd, dvbfe_sec_tone_mode_t tone) +{ + int ret = 0; + + if (fd > 0) { + switch (tone) { + case DVBFE_SEC_TONE_OFF: + ret = ioctl(fd, FE_SET_TONE, DVBFE_SEC_TONE_OFF); + break; + case DVBFE_SEC_TONE_ON: + ret = ioctl(fd, FE_SET_TONE, DVBFE_SEC_TONE_ON); + break; + default: + print(verbose, ERROR, 1, "Invalid command !"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed !"); + } else + print(verbose, ERROR, 1, "Device open error !"); + + return ret; +} + +int set_tone_data_burst(int fd, dvbfe_sec_mini_cmd_t minicmd) +{ + int ret = 0; + + if (fd > 0) { + switch (minicmd) { + case DVBFE_SEC_MINI_A: + ret = ioctl(fd, FE_DISEQC_SEND_BURST, DVBFE_SEC_MINI_A); + break; + case DVBFE_SEC_MINI_B: + ret = ioctl(fd, FE_DISEQC_SEND_BURST, DVBFE_SEC_MINI_B); + break; + default: + print(verbose, ERROR, 1, "Invalid command"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + } else + print(verbose, ERROR, 1, "Device open error !"); + + return ret; +} + +int set_polarization(int fd, dvbfe_sec_voltage_t polarization) +{ + int ret = 0; + + if (fd > 0) { + switch (polarization) { + case DVBFE_SEC_VOLTAGE_13: + ret = ioctl(fd, FE_SET_VOLTAGE, DVBFE_SEC_VOLTAGE_13); + break; + case DVBFE_SEC_VOLTAGE_18: + ret = ioctl(fd, FE_SET_VOLTAGE, DVBFE_SEC_VOLTAGE_18); + break; + default: + print(verbose, ERROR, 1, "Invalid command"); + break; + } + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + } else + print(verbose, ERROR, 1, "Device open error !"); + + return ret; +} + +int do_diseqc_cmd(int fd, uint8_t cmd, uint8_t address, uint8_t *data) +{ + int ret = 0; + uint8_t length; + struct diseqc_cmd diseqc_message; + + memcpy(&diseqc_message.message[0], &msgtbl->command[1], 6); + length = msgtbl->command[0]; + diseqc_message.length = length; + + /* Set Address */ + diseqc_message.message[2] = address; + switch (length) { + case 6: + /* Set Data */ + diseqc_message.message[5] = data[2]; + case 5: + /* Set Data */ + diseqc_message.message[4] = data[1]; + case 4: + /* Set Data */ + diseqc_message.message[3] = data[0]; + case 3: + /* Only cmd */ + break; + default: + return -EINVAL; + } + + if (fd > 0) { + ret = ioctl(fd, cmd, &diseqc_message); + if (ret == -1) + print(verbose, ERROR, 1, "IOCTL failed"); + + } else + print(verbose, ERROR, 1, "Device open error !"); + + return ret; +} diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.h b/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.h new file mode 100644 index 0000000..fc8ffd4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/diseqc.h @@ -0,0 +1,171 @@ +/* + libdvbfe - a DVB frontend library + + Copyright (C) 2005 Manu Abraham <manu@kromtek.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 DISEQC_H +#define DISEQC_H + +#include <stdlib.h> +#include <stdint.h> + +/* Addresses */ +#define DISEQCxx_MASTER 0x00 +#define SMATV_MASTER 0x10 +#define LNB_MASTER 0x10 +#define SWITCHER_MASTER 0x10 +#define LNB 0x11 +#define LNB_LOOP 0x12 +#define SWITCHER_DC 0x14 +#define SWITCHER_DC_LOOP 0x15 +#define POL_CONTROLLER 0x21 +#define POSITIONER_MASTER 0x30 +#define POSITIONER_POLAR 0x31 +#define POSITIONER_ELEVATION 0x32 + +/* Commands */ +#define DISEQC_SET_LOW_LO 0 +#define DISEQC10_SET_VERT_POL 1 +#define DISEQC10_SET_SAT_POS_A 2 +#define DISEQC10_SET_SWITCH_OPT_A 3 +#define DISEQC10_SET_HIGH_LO 4 +#define DISEQC10_SET_HORIZ_POL 5 +#define DISEQC10_SET_SAT_POS_B 6 + +#define DISEQC10_SET_SWITCH_OPT_B 7 +#define DISEQC11_SET_SWITCH1_INP_A 8 +#define DISEQC11_SET_SWITCH2_INP_A 9 +#define DISEQC11_SET_SWITCH3_INP_A 10 +#define DISEQC11_SET_SWITCH4_INP_A 11 +#define DISEQC11_SET_SWITCH1_INP_B 12 +#define DISEQC11_SET_SWITCH2_INP_B 13 +#define DISEQC11_SET_SWITCH3_INP_B 14 +#define DISEQC11_SET_SWITCH4_INP_B 15 + +#define DISEQCxx_SET_BUS_SLEEP 16 +#define DISEQCxx_SET_BUS_AWAKE 17 +#define DISEQC11_SET_CHAN_FREQ 18 +#define DISEQC11_SET_RCVR_CHAN 19 +#define DISEQC12_SET_MOTOR_HALT 20 +#define DISEQC12_SET_LIMITS_OFF 21 +#define DISEQC12_SET_LIMITS_ON 22 +#define DISEQC22_GET_MOTOR_STATE 23 +#define DISEQC12_SET_MOTOR_WEST 24 +#define DISEQC12_SET_MOTOR_EAST 25 +#define DISEQC12_SET_WEST_LIMIT 26 +#define DISEQC12_SET_EAST_LIMIT 27 +#define DISEQC12_STEP_MOTOR_UP 28 //??????? +#define DISEQC12_STEP_MOTOR_DOWN 29 + +struct diseqc_cmd { + uint8_t message[6]; + uint8_t length; +}; + +struct cmd_types { + uint8_t command[7]; + char *cmd_descr; +}; + +typedef enum dvbfe_sec_voltage { + DVBFE_SEC_VOLTAGE_13, + DVBFE_SEC_VOLTAGE_18, + DVBFE_SEC_VOLTAGE_OFF +} dvbfe_sec_voltage_t; + +typedef enum dvbfe_sec_tone_mode { + DVBFE_SEC_TONE_ON, + DVBFE_SEC_TONE_OFF +} dvbfe_sec_tone_mode_t; + +typedef enum dvbfe_sec_mini_cmd { + DVBFE_SEC_MINI_A, + DVBFE_SEC_MINI_B +} dvbfe_sec_mini_cmd_t; + + +struct cmd_types msgtbl[] = { + + { { 0x03, 0xe0, 0x00, 0x20, 0x00, 0x00, 0x00 }, "DISEQC_SET_LOW_LO" }, + { { 0x03, 0xe0, 0x00, 0x21, 0x00, 0x00, 0x00 }, "DISEQC10_SET_VERT_POL" }, + { { 0x03, 0xe0, 0x00, 0x22, 0x00, 0x00, 0x00 }, "DISEQC10_SET_SAT_POS_A" }, + { { 0x03, 0xe0, 0x00, 0x23, 0x00, 0x00, 0x00 }, "DISEQC10_SET_SWITCH_OPT_A" }, + { { 0x03, 0xe0, 0x00, 0x24, 0x00, 0x00, 0x00 }, "DISEQC10_SET_HIGH_LO" }, + { { 0x03, 0xe0, 0x00, 0x25, 0x00, 0x00, 0x00 }, "DISEQC10_SET_HORIZ_POL" }, + { { 0x03, 0xe0, 0x00, 0x26, 0x00, 0x00, 0x00 }, "DISEQC10_SET_SAT_POS_B" }, + + { { 0x03, 0xe0, 0x00, 0x27, 0x00, 0x00, 0x00 }, "DISEQC10_SET_SWITCH_OPT_B" }, + { { 0x03, 0xe0, 0x00, 0x28, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH1_INP_A" }, + { { 0x03, 0xe0, 0x00, 0x29, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH2_INP_A" }, + { { 0x03, 0xe0, 0x00, 0x2a, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH3_INP_A" }, + { { 0x03, 0xe0, 0x00, 0x2b, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH4_INP_A" }, + { { 0x03, 0xe0, 0x00, 0x2c, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH1_INP_B" }, + { { 0x03, 0xe0, 0x00, 0x2d, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH2_INP_B" }, + { { 0x03, 0xe0, 0x00, 0x2e, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH3_INP_B" }, + { { 0x03, 0xe0, 0x00, 0x2f, 0x00, 0x00, 0x00 }, "DISEQC11_SET_SWITCH4_INP_B" }, + + { { 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00 }, "DISEQCxx_SET_BUS_SLEEP" }, + { { 0x03, 0xe0, 0x00, 0x31, 0x00, 0x00, 0x00 }, "DISEQCxx_SET_BUS_AWAKE" }, + { { 0x06, 0x0e, 0x00, 0x05, 0x80, 0x00, 0x00 }, "DISEQC11_SET_CHAN_FREQ" }, + { { 0x05, 0xe0, 0x00, 0x59, 0x00, 0x00, 0x00 }, "DISEQC11_SET_RCVR_CHAN" }, + + { { 0x03, 0xe0, 0x00, 0x60, 0x00, 0x00, 0x00 }, "DISEQC12_SET_MOTOR_HALT" }, + { { 0x03, 0xe0, 0x00, 0x63, 0x00, 0x00, 0x00 }, "DISEQC12_SET_LIMITS_OFF" }, + { { 0x04, 0xe0, 0x00, 0x6a, 0x00, 0x00, 0x00 }, "DISEQC12_SET_LIMITS_ON" }, + { { 0x03, 0xe0, 0x00, 0x64, 0x00, 0x00, 0x00 }, "DISEQC22_GET_MOTOR_STATE" } , + { { 0x04, 0xe1, 0x00, 0x69, 0x00, 0x00, 0x00 }, "DISEQC12_SET_MOTOR_WEST" }, + { { 0x04, 0xe1, 0x00, 0x68, 0x00, 0x00, 0x00 }, "DISEQC12_SET_MOTOR_EAST" }, + { { 0x03, 0xe1, 0x00, 0x67, 0x00, 0x00, 0x00 }, "DISEQC12_SET_WEST_LIMIT" }, + { { 0x03, 0xe1, 0x00, 0x66, 0x00, 0x00, 0x00 }, "DISEQC12_SET_EAST_LIMIT" }, + { { 0x04, 0xe2, 0x00, 0x68, 0x00, 0x00, 0x00 }, "DISEQC12_STEP_MOTOR_UP" }, + { { 0x04, 0xe2, 0x00, 0x69, 0x00, 0x00, 0x00 }, "DISEQC12_STEP_MOTOR_DOWN"}, + + { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } +}; + + +/* + * Tone/Data Burst control + * @param fd, FD opened with libdvbfe_open(). + * @param tone, SEC_TONE_ON/SEC_TONE_OFF + */ +extern int set_22k_tone(int fd, dvbfe_sec_tone_mode_t tone); + +/* + * 22khz Tone control + * @param fd, FD opened with libdvbfe_open(). + * @param adapter, minicmd, SEC_MINI_A/SEC_MINI_B + */ +extern int set_tone_data_burst(int fd, dvbfe_sec_mini_cmd_t minicmd); + +/* + * H/V polarization control + * @param fd, FD opened with libdvbfe_open(). + * @param polarization, SEC_VOLTAGE_13/SEC_VOLTAGE_18/SEC_VOLTAGE_OFF + */ +extern int set_polarization(int fd, dvbfe_sec_voltage_t polarization); + +/* + * Send a DiSEqC Command + * @param fd, FD opened with libdvbfe_open(). + * @param cmd, the defined diseqc commands + * @param address, the address of the DiSEqC device to be controlled + * @param data, a pointer to am array containing the data to be sent + * max. length of data, that can be sent is 3 bytes + */ +extern int do_diseqc_command(int fd, uint8_t cmd, uint8_t address, uint8_t *data); + +#endif diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbca.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbca.c new file mode 100644 index 0000000..8261cd2 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvbapi/dvbca.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbca.h new file mode 100644 index 0000000..c65423b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c new file mode 100644 index 0000000..aebad34 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c @@ -0,0 +1,243 @@ +/* + * 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; + + 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; + + 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/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h new file mode 100644 index 0000000..3fe4a4b --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h @@ -0,0 +1,202 @@ +/* + * 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 + +/** + * 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 once, or multiple times in readonly + * mode. 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/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c new file mode 100644 index 0000000..fc6ecf4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c @@ -0,0 +1,760 @@ +/* + * libdvbfe - a DVB frontend library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * 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 <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <linux/dvb/frontend.h> +#include "dvbfe.h" + +#define GET_INFO_MIN_DELAY_US 100000 + +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_prv { + int fd; + dvbfe_type_t type; + char *name; + struct timeval nextinfotime; + struct dvbfe_info cachedinfo; + int cachedreturnval; +}; + +dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly) +{ + char filename[PATH_MAX+1]; + struct dvbfe_handle_prv *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_prv*) malloc(sizeof(struct dvbfe_handle_prv)); + memset(fehandle, 0, sizeof(struct dvbfe_handle_prv)); + 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(dvbfe_handle_t _fehandle) +{ + struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle; + + close(fehandle->fd); + free(fehandle->name); + free(fehandle); +} + +int dvbfe_get_info(dvbfe_handle_t _fehandle, dvbfe_info_mask_t querymask, struct dvbfe_info *result) +{ + int returnval = 0; + fe_status_t status; + struct dvb_frontend_parameters kparams; + struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle; + struct timeval curtime; + + // limit how often this is called to reduce bus traffic + gettimeofday(&curtime, NULL); + if ((curtime.tv_sec < fehandle->nextinfotime.tv_sec) || + ((curtime.tv_sec == fehandle->nextinfotime.tv_sec) && (curtime.tv_usec < fehandle->nextinfotime.tv_usec))) { + memcpy(result, &fehandle->cachedinfo, sizeof(struct dvbfe_info)); + return fehandle->cachedreturnval; + } + + // retrieve the requested values + memset(result, 0, sizeof(result)); + result->type = fehandle->type; + result->name = fehandle->name; + if (querymask & DVBFE_INFO_LOCKSTATUS) { + if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) { + returnval |= DVBFE_INFO_LOCKSTATUS; + if (status & FE_HAS_SIGNAL) + result->signal = 1; + + if (status & FE_HAS_CARRIER) + result->carrier = 1; + + if (status & FE_HAS_VITERBI) + result->viterbi = 1; + + if (status & FE_HAS_SYNC) + result->sync = 1; + + if (status & FE_HAS_LOCK) + result->lock = 1; + } + } + if (querymask & DVBFE_INFO_FEPARAMS) { + if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kparams)) { + returnval |= DVBFE_INFO_FEPARAMS; + result->feparams.frequency = kparams.frequency; + result->feparams.inversion = lookupval(kparams.inversion, 1, dvbfe_spectral_inversion_to_kapi); + switch(fehandle->type) { + case FE_QPSK: + result->feparams.u.dvbs.symbol_rate = kparams.u.qpsk.symbol_rate; + result->feparams.u.dvbs.fec_inner = + lookupval(kparams.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi); + break; + + case FE_QAM: + result->feparams.u.dvbc.symbol_rate = kparams.u.qam.symbol_rate; + result->feparams.u.dvbc.fec_inner = + lookupval(kparams.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbc.modulation = + lookupval(kparams.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi); + break; + + case FE_OFDM: + result->feparams.u.dvbt.bandwidth = + lookupval(kparams.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi); + result->feparams.u.dvbt.code_rate_HP = + lookupval(kparams.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbt.code_rate_LP = + lookupval(kparams.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi); + result->feparams.u.dvbt.constellation = + lookupval(kparams.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi); + result->feparams.u.dvbt.transmission_mode = + lookupval(kparams.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi); + result->feparams.u.dvbt.guard_interval = + lookupval(kparams.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi); + result->feparams.u.dvbt.hierarchy_information = + lookupval(kparams.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi); + break; + + case FE_ATSC: + result->feparams.u.atsc.modulation = + lookupval(kparams.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; + } + + // setup for next poll + gettimeofday(&fehandle->nextinfotime, NULL); + fehandle->nextinfotime.tv_usec += GET_INFO_MIN_DELAY_US; + if (fehandle->nextinfotime.tv_usec >= 1000000) { + fehandle->nextinfotime.tv_usec -= 1000000; + fehandle->nextinfotime.tv_sec++; + } + memcpy(&fehandle->cachedinfo, result, sizeof(struct dvbfe_info)); + fehandle->cachedreturnval = returnval; + + // done + return returnval; +} + +int dvbfe_set(dvbfe_handle_t _fehandle, struct dvbfe_parameters *params, int timeout) +{ + struct dvb_frontend_parameters kparams; + struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle; + 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; +} + +void dvbfe_poll(dvbfe_handle_t fehandle) +{ + // no implementation required yet +} + + + + + + + +int dvbfe_diseqc_command(dvbfe_handle_t _fehandle, char *command) +{ + int i = 0; + int waittime; + int status; + struct dvb_diseqc_master_cmd master_cmd; + unsigned int tmpcmd[6]; + struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle; + char value_s[20]; + int value_i; + int addr; + + while(command[i]) { + /* kill whitespace */ + if (isspace(command[i])) { + i++; + continue; + } + + switch(command[i]) { + case 't': + if ((status = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF)) != 0) + return status; + break; + + case 'T': + if ((status = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON)) != 0) + return status; + break; + + case '_': + if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF)) != 0) + return status; + break; + + case 'v': + if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13)) != 0) + return status; + break; + + case 'V': + if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18)) != 0) + return status; + break; + + case 'A': + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A)) != 0) + return status; + break; + + case 'B': + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B)) != 0) + return status; + break; + + case '+': + ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1); + /* don't care if this one is not supported */ + break; + + case '-': + ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0); + /* don't care if this one is not supported */ + break; + + case 'W': + waittime = atoi(command + i + 1); + if (waittime == 0) { + return -EINVAL; + } + usleep(waittime * 1000); + while(command[i] && !isspace(command[i])) + i++; + break; + + case '.': // extended command + { + i++; + + if (!strncmp(command+i, "D(", 2)) { + i += 2; + + master_cmd.msg_len = + sscanf(command+i, "%x %x %x %x %x %x", + tmpcmd, tmpcmd+1, tmpcmd+2, tmpcmd+3, tmpcmd+4, tmpcmd+5); + if (master_cmd.msg_len == 0) + return -EINVAL; + master_cmd.msg[0] = tmpcmd[0]; + master_cmd.msg[1] = tmpcmd[1]; + master_cmd.msg[2] = tmpcmd[2]; + master_cmd.msg[3] = tmpcmd[3]; + master_cmd.msg[4] = tmpcmd[4]; + master_cmd.msg[5] = tmpcmd[5]; + + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + } else if (!strncmp(command+i, "Dband(", 6)) { + if (sscanf(command+i+6, "%i %2s", &addr, value_s) != 2) + return -EINVAL; + if (!strncmp(value_s, "lo", 2)) { + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x20; + master_cmd.msg_len = 3; + } else if (!strncmp(value_s, "hi", 2)) { + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x24; + master_cmd.msg_len = 3; + } else { + return -EINVAL; + } + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if ((!strncmp(command+i, "Dpolarisation(", 14) || + (!strncmp(command+i, "Dpolarization(", 14)))) { + if (sscanf(command+i+14, "%i %1s", &addr, value_s) != 2) + return -EINVAL; + switch(*value_s) { + case 'H': + case 'L': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x25; + master_cmd.msg_len = 3; + break; + + case 'V': + case 'R': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x21; + master_cmd.msg_len = 3; + break; + + default: + return -EINVAL; + } + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if (!strncmp(command+i, "Dsatellite_position(", 20)) { + if (sscanf(command+i+20, "%i %1s", &addr, value_s) != 2) + return -EINVAL; + switch(*value_s) { + case 'A': + case 'C': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x22; + master_cmd.msg_len = 3; + break; + + case 'B': + case 'D': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x26; + master_cmd.msg_len = 3; + break; + + default: + return -EINVAL; + } + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if (!strncmp(command+i, "Dswitch_option(", 15)) { + if (sscanf(command+i+15, "%i %1s", &addr, value_s) != 2) + return -EINVAL; + switch(*value_s) { + case 'A': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x23; + master_cmd.msg_len = 3; + break; + + case 'B': + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x27; + master_cmd.msg_len = 3; + break; + + default: + return -EINVAL; + } + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if (!strncmp(command+i, "Dport_pins(", 11)) { + int mask; + if (sscanf(command+i+11, "%i %i %i", &addr, &mask, &value_i) != 3) + return -EINVAL; + + if (mask & 0x0f) { + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x38; + master_cmd.msg[3] = ((mask & 0x0f) << 4) | (value_i & 0x0f); + master_cmd.msg_len = 4; + + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + } + if (mask & 0xf0) { + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x39; + master_cmd.msg[3] = (mask & 0xf0) | ((value_i & 0xf0) >> 4); + master_cmd.msg_len = 4; + + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + } + + } else if (!strncmp(command+i, "Dgoto_preset(", 13)) { + if (sscanf(command+i+13, "%i %i", &addr, &value_i) != 2) + return -EINVAL; + + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x3b; + master_cmd.msg[3] = value_i; + master_cmd.msg_len = 4; + + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if (!strncmp(command+i, "Dgoto_angle(", 12)) { + int integer = 0; + int fraction = 0; + char *tmp; + + if (sscanf(command+i+12, "%i %s", &addr, value_s) != 2) + return -EINVAL; + + // parse the integer and fractional parts using fixed point + integer = atoi(value_s); + tmp = strchr(value_s, '.'); + if (tmp != NULL) { + tmp++; + tmp[3] = 0; + fraction = ((atoi(tmp) * 16000) / 1000000) & 0xf; + } + + // generate the command + master_cmd.msg[0] = 0xe0; + master_cmd.msg[1] = addr; + master_cmd.msg[2] = 0x6e; + if (integer < -256) { + return -EINVAL; + } else if (integer < 0) { + integer = -integer; + master_cmd.msg[3] = 0xf0; + } else if (integer < 256) { + master_cmd.msg[3] = 0x00; + } else if (integer < 512) { + integer -= 256; + master_cmd.msg[3] = 0x10; + } else { + return -EINVAL; + } + master_cmd.msg[3] |= ((integer / 16) & 0x0f); + integer = integer % 16; + master_cmd.msg[4] |= ((integer & 0x0f) << 4) | fraction; + master_cmd.msg_len = 5; + + if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0) + return status; + + } else if (!strncmp(command+i, "dishnetworks(", 13)) { + if (sscanf(command+i+13, "%i", tmpcmd) != 1) + return -EINVAL; + + if ((status = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, tmpcmd)) != 0) + return status; + } + + /* skip to the end... */ + while(command[i] && (command[i] != ')')) + i++; + break; + } + + + default: + return -EINVAL; + } + + i++; + } + + return 0; +} + +int dvbfe_diseqc_read(dvbfe_handle_t _fehandle, int timeout, unsigned char *buf, unsigned int len) +{ + struct dvb_diseqc_slave_reply reply; + int result; + struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle; + + 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/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h new file mode 100644 index 0000000..9eb03b7 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h @@ -0,0 +1,308 @@ +/* + * libdvbfe - a DVB frontend library + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * 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. + */ +typedef enum dvbfe_type { + DVBFE_TYPE_DVBS, + DVBFE_TYPE_DVBC, + DVBFE_TYPE_DVBT, + DVBFE_TYPE_ATSC, +} dvbfe_type_t; + +typedef enum dvbfe_polarization { + DVBFE_POLARIZATION_H, + DVBFE_POLARIZATION_V, + DVBFE_POLARIZATION_L, + DVBFE_POLARIZATION_R, +} dvbfe_polarization_t; + +typedef enum dvbfe_spectral_inversion { + DVBFE_INVERSION_OFF, + DVBFE_INVERSION_ON, + DVBFE_INVERSION_AUTO +} dvbfe_spectral_inversion_t; + +typedef 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 +} dvbfe_code_rate_t; + +typedef 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 +} dvbfe_dvbt_const_t; + +typedef 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, +} dvbfe_dvbc_mod_t; + +typedef 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 +} dvbfe_atsc_mod_t; + +typedef enum dvbfe_dvbt_transmit_mode { + DVBFE_DVBT_TRANSMISSION_MODE_2K, + DVBFE_DVBT_TRANSMISSION_MODE_8K, + DVBFE_DVBT_TRANSMISSION_MODE_AUTO +} dvbfe_dvbt_transmit_mode_t; + +typedef enum dvbfe_dvbt_bandwidth { + DVBFE_DVBT_BANDWIDTH_8_MHZ, + DVBFE_DVBT_BANDWIDTH_7_MHZ, + DVBFE_DVBT_BANDWIDTH_6_MHZ, + DVBFE_DVBT_BANDWIDTH_AUTO +} dvbfe_dvbt_bandwidth_t; + +typedef 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 +} dvbfe_dvbt_guard_interval_t; + +typedef enum dvbfe_dvbt_hierarchy { + DVBFE_DVBT_HIERARCHY_NONE, + DVBFE_DVBT_HIERARCHY_1, + DVBFE_DVBT_HIERARCHY_2, + DVBFE_DVBT_HIERARCHY_4, + DVBFE_DVBT_HIERARCHY_AUTO +} dvbfe_dvbt_hierarchy_t; + +/** + * Structure used to store and communicate frontend parameters. + */ +struct dvbfe_parameters { + uint32_t frequency; + dvbfe_spectral_inversion_t inversion; + union { + struct { + uint32_t symbol_rate; + dvbfe_code_rate_t fec_inner; + dvbfe_polarization_t polarization; + } dvbs; + + struct { + uint32_t symbol_rate; + dvbfe_code_rate_t fec_inner; + dvbfe_dvbc_mod_t modulation; + } dvbc; + + struct { + dvbfe_dvbt_bandwidth_t bandwidth; + dvbfe_code_rate_t code_rate_HP; + dvbfe_code_rate_t code_rate_LP; + dvbfe_dvbt_const_t constellation; + dvbfe_dvbt_transmit_mode_t transmission_mode; + dvbfe_dvbt_guard_interval_t guard_interval; + dvbfe_dvbt_hierarchy_t hierarchy_information; + } dvbt; + + struct { + dvbfe_atsc_mod_t modulation; + } atsc; + } u; +}; + +/** + * Mask of values used in the dvbfe_get_info() call. + */ +typedef 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, +} dvbfe_info_mask_t; + +/** + * Structure containing values used by the dvbfe_get_info() call. + */ +struct dvbfe_info { + dvbfe_type_t 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 */ +}; + +/** + * Frontend handle datatype. + */ +typedef void *dvbfe_handle_t; + +/** + * 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 dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly); + +/** + * Close a DVB frontend. + * + * @param fehandle Handle opened with dvbfe_open(). + */ +extern void dvbfe_close(dvbfe_handle_t handle); + +/** + * Set the frontend tuning parameters. + * + * @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(dvbfe_handle_t fehandle, struct dvbfe_parameters *params, int timeout); + +/** + * Call this function regularly from a loop to maintain the frontend lock. + * + * @param fehandle Handle opened with dvbfe_open(). + */ +extern void dvbfe_poll(dvbfe_handle_t fehandle); + +/** + * 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. + * @return ORed bitmask of DVBFE_INFO_* indicating which values were read successfully. + */ +extern int dvbfe_get_info(dvbfe_handle_t fehandle, dvbfe_info_mask_t querymask, struct dvbfe_info *result); + +/** + * Execute a DISEQC command string. + * + * A diseqc command consists of a sequence of the following codes, separated by + * whitespace: + * Simple commands: + * t - turn 22kHz tone off. + * T - turn 22kHz tone on. + * _ - set voltage to 0v (i.e. off). + * v - set voltage to 13v. + * V - set voltage to 18v. + * + - Enable high LNB voltage. + * - - Disable high LNB voltage. + * A - send DISEQC mini command A. + * B - send DISEQC mini command B. + * Wii - Delay for ii milliseconds. + * + * Extended commands: + * .dishnetworks(<value>) - Send a dish networks legacy command <value> + * .D(<value> ...) - Send a raw diseqc master command. The command may be up + * to 6 bytes long. + * .Dband(<addr> <lo|hi>) - Set frequency band hi or lo. + * .Dpolarisation(<addr> <V|H|L|R>) - Set polarisation. + * .Dsatellite_position(<addr> <A|B>) - Set "satellite position" input switch. + * .Dswitch_option(<addr> <A|B>) - Set "switch option" input switch. + * .Dport_pins(<addr> <mask> <value>) - Set all input switches. Mask and value + * are hex-ascii 8 bit bytes. Only bits with a corresponding '1' in mask + * will be changed. + * .Dgoto_preset(<addr> <index>) - Set a positioner to a preset index (integer) + * .Dgoto_angle(<addr> <angle>) - Set a positioner to a given angle + * (e.g. 49.6). The angle may range between -180 to 496. It may include a + * fractional part. + * + * All integer values use standard notation - no prefix=>decimal, 0x=>hex etc. + * + * Set <addr> to 0 if you just have a simple DISEQC setup (e.g. one switch). See + * the DISEQC specification at http://www.eutelsat.org/ for full information. + * + * Comments begin with '#' - any characters after this will be ignored + * to the end of the line. + * + * Examples: + * S-19.2E 11700000 V 9750000 t v W15 .D(E0 10 38 F0) W15 A W15 t + * S-19.2E 99999999 V 10600000 t v W15 .D(E0 10 38 F1) W15 A W15 T + * S-19.2E 11700000 H 9750000 t V W15 .D(E0 10 38 F2) W15 A W15 t + * S-19.2E 99999999 H 10600000 t V W15 .D(E0 10 38 F3) W15 A W15 T + * + * @param fehandle Handle opened with dvbfe_open(). + * @param command Command to execute. + * @return 0 on success, nonzero on failure. + */ +extern int dvbfe_diseqc_command(dvbfe_handle_t fehandle, char *command); + +/** + * 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(dvbfe_handle_t fehandle, int timeout, unsigned char *buf, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif // LIBDVBFE_H diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c new file mode 100644 index 0000000..d6ee632 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c @@ -0,0 +1,99 @@ +/* + * 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, int encapsulation) +{ + struct dvb_net_if params; + + 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; + } + return ioctl(fd, NET_ADD_IF, ¶ms); +} + +int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, int *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/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h new file mode 100644 index 0000000..426e540 --- /dev/null +++ b/kaffeine/src/input/dvb/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. + */ +typedef enum dvbnet_encap { + DVBNET_ENCAP_MPE, + DVBNET_ENCAP_ULE, +} dvbnet_encap_t; + +/** + * 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 0 on success, nonzero on failure. + */ +extern int dvbnet_add_interface(int fd, uint16_t pid, int 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, int *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/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am b/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am new file mode 100644 index 0000000..7c9764a --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am @@ -0,0 +1,21 @@ +noinst_LTLIBRARIES = libdvben50221.la + +INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib + +libdvben50221_la_SOURCES = asn_1.c \ + en50221_app_ai.c \ + en50221_app_auth.c \ + en50221_app_ca.c \ + en50221_app_datetime.c \ + en50221_app_dvb.c \ + en50221_app_epg.c \ + en50221_app_lowspeed.c \ + en50221_app_mmi.c \ + en50221_app_rm.c \ + en50221_app_smartcard.c \ + en50221_app_teletext.c \ + en50221_app_utils.c \ + en50221_session.c \ + en50221_transport.c + +CFLAGS = -g -O2 -DLOG_LEVEL=1 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c new file mode 100644 index 0000000..8cc528f --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c @@ -0,0 +1,81 @@ +/* + ASN.1 routines, implementation for libdvben50221 + an implementation for the High Level Common Interface + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h new file mode 100644 index 0000000..00d636b --- /dev/null +++ b/kaffeine/src/input/dvb/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 (manu@kromtek.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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c new file mode 100644 index 0000000..6facef0 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c @@ -0,0 +1,185 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + +en50221_app_ai en50221_app_ai_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_ai_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_ai_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_ai_destroy(en50221_app_ai ai) +{ + struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_ai_register_callback(en50221_app_ai ai, en50221_app_ai_callback callback, void *arg) +{ + struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai; + + pthread_mutex_lock(&private->lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_ai_enquiry(en50221_app_ai ai, uint16_t session_number) +{ + struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4); +} + +int en50221_app_ai_entermenu(en50221_app_ai ai, uint16_t session_number) +{ + struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4); +} + +int en50221_app_ai_message(en50221_app_ai ai, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai; + (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(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_ai_parse_app_info(struct en50221_app_ai_private *private, + 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(&private->lock); + en50221_app_ai_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h new file mode 100644 index 0000000..4def877 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h @@ -0,0 +1,129 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_ai; + +/** + * Create an instance of an application information resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c new file mode 100644 index 0000000..b062e3e --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c @@ -0,0 +1,179 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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 *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + +en50221_app_auth en50221_app_auth_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_auth_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_auth_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_auth_destroy(en50221_app_auth auth) +{ + struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_auth_register_request_callback(en50221_app_auth auth, + en50221_app_auth_request_callback callback, void *arg) +{ + struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth; + + pthread_mutex_lock(&private->lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_auth_send(en50221_app_auth auth, + uint16_t session_number, + uint16_t auth_protocol_id, uint8_t *auth_data, + uint32_t auth_data_length) +{ + struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2); +} + +int en50221_app_auth_message(en50221_app_auth auth, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth; + (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(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_auth_parse_request(struct en50221_app_auth_private *private, + 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(&private->lock); + en50221_app_auth_request_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h new file mode 100644 index 0000000..30d9c55 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h @@ -0,0 +1,119 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_auth; + +/** + * Create an instance of the auth resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c new file mode 100644 index 0000000..a1206fb --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c @@ -0,0 +1,615 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + + +en50221_app_ca en50221_app_ca_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_ca_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_ca_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->ca_info_callback = NULL; + private->ca_pmt_reply_callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_ca_destroy(en50221_app_ca ca) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_ca_register_info_callback(en50221_app_ca ca, + en50221_app_ca_info_callback callback, void *arg) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + + pthread_mutex_lock(&private->lock); + private->ca_info_callback = callback; + private->ca_info_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_ca_register_pmt_reply_callback(en50221_app_ca ca, + en50221_app_ca_pmt_reply_callback callback, void *arg) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + + pthread_mutex_lock(&private->lock); + private->ca_pmt_reply_callback = callback; + private->ca_pmt_reply_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_ca_info_enq(en50221_app_ca ca, + uint16_t session_number) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4); +} + +int en50221_app_ca_pmt(en50221_app_ca ca, + uint16_t session_number, + uint8_t *ca_pmt, + uint32_t ca_pmt_length) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2); +} + +int en50221_app_ca_message(en50221_app_ca ca, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_CA_PMT_REPLY: + return en50221_app_ca_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; +} + +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; + struct ca_pmt_descriptor *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; + struct ca_pmt_descriptor *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_private *private, + 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(&private->lock); + en50221_app_ca_info_callback cb = private->ca_info_callback; + void *cb_arg = private->ca_info_callback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_ca_pmt_reply_callback cb = private->ca_pmt_reply_callback; + void *cb_arg = private->ca_pmt_reply_callback_arg; + pthread_mutex_unlock(&private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h new file mode 100644 index 0000000..ab29649 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h @@ -0,0 +1,254 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_ca; + +/** + * Create an instance of the ca resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c new file mode 100644 index 0000000..5686443 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c @@ -0,0 +1,169 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + + +en50221_app_datetime en50221_app_datetime_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_datetime_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_datetime_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_datetime_destroy(en50221_app_datetime datetime) +{ + struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_datetime_register_enquiry_callback(en50221_app_datetime datetime, + en50221_app_datetime_enquiry_callback callback, void *arg) +{ + struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime; + + pthread_mutex_lock(&private->lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_datetime_send(en50221_app_datetime datetime, + uint16_t session_number, + time_t utc_time, + int time_offset) +{ + struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, data_length); +} + +int en50221_app_datetime_message(en50221_app_datetime datetime, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime; + (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(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_datetime_parse_enquiry(struct en50221_app_datetime_private *private, + 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(&private->lock); + en50221_app_datetime_enquiry_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number, response_interval); + } + return 0; +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h new file mode 100644 index 0000000..5819fb4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h @@ -0,0 +1,116 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_datetime; + +/** + * Create an instance of the datetime resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c new file mode 100644 index 0000000..82da884 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c @@ -0,0 +1,263 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + + +en50221_app_dvb en50221_app_dvb_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_dvb_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_dvb_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->tune_callback = NULL; + private->replace_callback = NULL; + private->clear_replace_callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_dvb_destroy(en50221_app_dvb dvb) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_dvb_register_tune_callback(en50221_app_dvb dvb, + en50221_app_dvb_tune_callback callback, void *arg) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + + pthread_mutex_lock(&private->lock); + private->tune_callback = callback; + private->tune_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_dvb_register_replace_callback(en50221_app_dvb dvb, + en50221_app_dvb_replace_callback callback, void *arg) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + + pthread_mutex_lock(&private->lock); + private->replace_callback = callback; + private->replace_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_dvb_register_clear_replace_callback(en50221_app_dvb dvb, + en50221_app_dvb_clear_replace_callback callback, void *arg) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + + pthread_mutex_lock(&private->lock); + private->clear_replace_callback = callback; + private->clear_replace_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_dvb_ask_release(en50221_app_dvb dvb, uint16_t session_number) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4); +} + +int en50221_app_dvb_message(en50221_app_dvb dvb, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_REPLACE: + return en50221_app_dvb_parse_replace(private, slot_id, session_number, data+3, data_length-3); + case TAG_CLEAR_REPLACE: + return en50221_app_dvb_parse_clear_replace(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_dvb_parse_tune(struct en50221_app_dvb_private *private, + 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(&private->lock); + en50221_app_dvb_tune_callback cb = private->tune_callback; + void *cb_arg = private->tune_callback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_dvb_replace_callback cb = private->replace_callback; + void *cb_arg = private->replace_callback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_dvb_clear_replace_callback cb = private->clear_replace_callback; + void *cb_arg = private->clear_replace_callback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number, replacement_ref); + } + return 0; +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h new file mode 100644 index 0000000..221f58a --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h @@ -0,0 +1,164 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_dvb; + +/** + * Create an instance of the dvb resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c new file mode 100644 index 0000000..dba09b0 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c @@ -0,0 +1,166 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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 *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + + +en50221_app_epg en50221_app_epg_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_epg_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_epg_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_epg_destroy(en50221_app_epg epg) +{ + struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_epg_register_enquiry_callback(en50221_app_epg epg, + en50221_app_epg_reply_callback callback, void *arg) +{ + struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg; + + pthread_mutex_lock(&private->lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_epg_enquire(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) +{ + struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 15); +} + +int en50221_app_epg_message(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 *private = (struct en50221_app_epg_private *) 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_private *private, + 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(&private->lock); + en50221_app_epg_reply_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number, event_status); + } + return 0; +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h new file mode 100644 index 0000000..c3c4c59 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h @@ -0,0 +1,136 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_epg; + +/** + * Create an instance of the epg resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c new file mode 100644 index 0000000..25d088f --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c @@ -0,0 +1,514 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + uint8_t slot_id, uint16_t session_number, int more_last, + uint8_t *data, uint32_t data_length); + + + +en50221_app_lowspeed en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_lowspeed_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_lowspeed_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->command_callback = NULL; + private->send_callback = NULL; + private->sessions = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_lowspeed_destroy(en50221_app_lowspeed lowspeed) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + + struct en50221_app_lowspeed_session *cur_s = private->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(&private->lock); + free(private); +} + +void en50221_app_lowspeed_clear_session(en50221_app_lowspeed lowspeed, uint16_t session_number) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + + pthread_mutex_lock(&private->lock); + struct en50221_app_lowspeed_session *cur_s = private->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 { + private->sessions = cur_s->next; + } + free(cur_s); + return; + } + + prev_s = cur_s; + cur_s=cur_s->next; + } + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_lowspeed_register_command_callback(en50221_app_lowspeed lowspeed, + en50221_app_lowspeed_command_callback callback, void *arg) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + + pthread_mutex_lock(&private->lock); + private->command_callback = callback; + private->command_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_lowspeed_register_send_callback(en50221_app_lowspeed lowspeed, + en50221_app_lowspeed_send_callback callback, void *arg) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + + pthread_mutex_lock(&private->lock); + private->send_callback = callback; + private->send_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_lowspeed_send_comms_reply(en50221_app_lowspeed lowspeed, + uint16_t session_number, + uint8_t comms_reply_id, + uint8_t return_value) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 6); +} + +int en50221_app_lowspeed_send_comms_data(en50221_app_lowspeed lowspeed, + uint16_t session_number, + uint8_t phase_id, + uint32_t tx_data_length, + uint8_t *tx_data) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2); +} + +int en50221_app_lowspeed_message(en50221_app_lowspeed lowspeed, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_COMMS_SEND_LAST: + return en50221_app_lowspeed_parse_send(private, slot_id, session_number, 1, data+3, data_length-3); + case TAG_COMMS_SEND_MORE: + return en50221_app_lowspeed_parse_send(private, 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_private *private, + 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(&private->lock); + en50221_app_lowspeed_command_callback cb = private->command_callback; + void *cb_arg = private->command_callback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + struct en50221_app_lowspeed_session *cur_s = private->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(&private->lock); + return -1; + } + cur_s->session_number = session_number; + cur_s->block_chain = NULL; + cur_s->block_length = 0; + cur_s->next = private->sessions; + private->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(&private->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(&private->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(&private->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(&private->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 = private->send_callback; + void *cb_arg = private->send_callback_arg; + pthread_mutex_unlock(&private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h new file mode 100644 index 0000000..9f58ad9 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h @@ -0,0 +1,210 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_lowspeed; + +/** + * Create an instance of the lowspeed resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c new file mode 100644 index 0000000..ab5c6e4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c @@ -0,0 +1,1316 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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_private *private, + 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); + + + +en50221_app_mmi en50221_app_mmi_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_mmi_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_mmi_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->closecallback = NULL; + private->displaycontrolcallback = NULL; + private->keypadcontrolcallback = NULL; + private->subtitlesegmentcallback = NULL; + private->sceneendmarkcallback = NULL; + private->scenecontrolcallback = NULL; + private->subtitledownloadcallback = NULL; + private->flushdownloadcallback = NULL; + private->enqcallback = NULL; + private->menucallback = NULL; + private->listcallback = NULL; + private->sessions = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_mmi_destroy(en50221_app_mmi mmi) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + struct en50221_app_mmi_session *cur_s = private->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(&private->lock); + free(private); +} + +void en50221_app_mmi_clear_session(en50221_app_mmi mmi, uint16_t session_number) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + struct en50221_app_mmi_session *cur_s = private->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 { + private->sessions = cur_s->next; + } + free(cur_s); + return; + } + + prev_s = cur_s; + cur_s=cur_s->next; + } + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_close_callback(en50221_app_mmi mmi, + en50221_app_mmi_close_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->closecallback = callback; + private->closecallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_display_control_callback(en50221_app_mmi mmi, + en50221_app_mmi_display_control_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->displaycontrolcallback = callback; + private->displaycontrolcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_keypad_control_callback(en50221_app_mmi mmi, + en50221_app_mmi_keypad_control_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->keypadcontrolcallback = callback; + private->keypadcontrolcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_subtitle_segment_callback(en50221_app_mmi mmi, + en50221_app_mmi_subtitle_segment_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->subtitlesegmentcallback = callback; + private->subtitlesegmentcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_scene_end_mark_callback(en50221_app_mmi mmi, + en50221_app_mmi_scene_end_mark_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->sceneendmarkcallback = callback; + private->sceneendmarkcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_scene_control_callback(en50221_app_mmi mmi, + en50221_app_mmi_scene_control_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->scenecontrolcallback = callback; + private->scenecontrolcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_subtitle_download_callback(en50221_app_mmi mmi, + en50221_app_mmi_subtitle_download_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->subtitledownloadcallback = callback; + private->subtitledownloadcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_flush_download_callback(en50221_app_mmi mmi, + en50221_app_mmi_flush_download_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->flushdownloadcallback = callback; + private->flushdownloadcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_enq_callback(en50221_app_mmi mmi, + en50221_app_mmi_enq_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->enqcallback = callback; + private->enqcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_menu_callback(en50221_app_mmi mmi, + en50221_app_mmi_menu_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->menucallback = callback; + private->menucallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_mmi_register_list_callback(en50221_app_mmi mmi, + en50221_app_mmi_list_callback callback, void *arg) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + + pthread_mutex_lock(&private->lock); + private->listcallback = callback; + private->listcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_mmi_close(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t cmd_id, + uint8_t delay) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, data_length); +} + +int en50221_app_mmi_display_reply(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t reply_id, + struct en502221_app_mmi_display_reply_details *details) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, iov_count); +} + +int en50221_app_mmi_keypress(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t keycode) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_display_message(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t display_message_id) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_scene_done(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t decoder_continue, + uint8_t scene_reveal, + uint8_t scene_tag) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_download_reply(en50221_app_mmi mmi, + uint16_t session_number, + uint16_t object_id, + uint8_t download_reply_id) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 7); +} + +int en50221_app_mmi_answ(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t answ_id, + uint8_t *text, + uint32_t text_count) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, iov_count); +} + +int en50221_app_mmi_menu_answ(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t choice_ref) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5); +} + +int en50221_app_mmi_message(en50221_app_mmi mmi, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_DISPLAY_CONTROL: + return en50221_app_mmi_parse_display_control(private, slot_id, session_number, data+3, data_length-3); + case TAG_KEYPAD_CONTROL: + return en50221_app_mmi_parse_keypad_control(private, slot_id, session_number, data+3, data_length-3); + case TAG_ENQUIRY: + return en50221_app_mmi_parse_enq(private, slot_id, session_number, data+3, data_length-3); + case TAG_MENU_LAST: + return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 1, data+3, data_length-3); + case TAG_MENU_MORE: + return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 0, data+3, data_length-3); + case TAG_LIST_LAST: + return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 1, data+3, data_length-3); + case TAG_LIST_MORE: + return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 0, data+3, data_length-3); + case TAG_SUBTITLE_SEGMENT_LAST: + return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 1, data+3, data_length-3); + case TAG_SUBTITLE_SEGMENT_MORE: + return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 0, data+3, data_length-3); + case TAG_SCENE_END_MARK: + return en50221_app_mmi_parse_scene_end_mark(private, slot_id, session_number, data+3, data_length-3); + case TAG_SCENE_CONTROL: + return en50221_app_mmi_parse_scene_control(private, slot_id, session_number, data+3, data_length-3); + case TAG_SUBTITLE_DOWNLOAD_LAST: + return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 1, data+3, data_length-3); + case TAG_SUBTITLE_DOWNLOAD_MORE: + return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 0, data+3, data_length-3); + case TAG_FLUSH_DOWNLOAD: + return en50221_app_mmi_parse_flush_download(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_mmi_parse_close(struct en50221_app_mmi_private *private, + 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(&private->lock); + en50221_app_mmi_close_callback cb = private->closecallback; + void *cb_arg = private->closecallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_display_control_callback cb = private->displaycontrolcallback; + void *cb_arg = private->displaycontrolcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_keypad_control_callback cb = private->keypadcontrolcallback; + void *cb_arg = private->keypadcontrolcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_enq_callback cb = private->enqcallback; + void *cb_arg = private->enqcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + uint8_t *outdata; + uint32_t outdata_length; + int dfstatus = en50221_app_mmi_defragment(private, session_number, tag_id, more_last, + data, asn_data_length, + &outdata, &outdata_length); + if (dfstatus <= 0) { + pthread_mutex_unlock(&private->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(&private->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(&private->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(&private->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(&private->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 = private->menucallback; + void *cb_arg = private->menucallback_arg; + pthread_mutex_unlock(&private->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 = private->listcallback; + void *cb_arg = private->listcallback_arg; + pthread_mutex_unlock(&private->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(&private->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_private *private, + 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(&private->lock); + uint8_t *outdata; + uint32_t outdata_length; + int dfstatus = en50221_app_mmi_defragment(private, session_number, tag_id, more_last, + data, asn_data_length, + &outdata, &outdata_length); + if (dfstatus <= 0) { + pthread_mutex_unlock(&private->lock); + return dfstatus; + } + + // do callback + int cbstatus = 0; + switch(tag_id) { + case TAG_SUBTITLE_SEGMENT_LAST: + { + en50221_app_mmi_subtitle_segment_callback cb = private->subtitlesegmentcallback; + void *cb_arg = private->subtitlesegmentcallback_arg; + pthread_mutex_unlock(&private->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 = private->subtitledownloadcallback; + void *cb_arg = private->subtitledownloadcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_scene_end_mark_callback cb = private->sceneendmarkcallback; + void *cb_arg = private->sceneendmarkcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_scene_control_callback cb = private->scenecontrolcallback; + void *cb_arg = private->scenecontrolcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_mmi_flush_download_callback cb = private->flushdownloadcallback; + void *cb_arg = private->flushdownloadcallback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number); + } + return 0; +} + +static int en50221_app_mmi_defragment(struct en50221_app_mmi_private *private, + 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 = private->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 = private->sessions; + private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h new file mode 100644 index 0000000..b5e3abf --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h @@ -0,0 +1,571 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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 en502221_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. + */ +typedef void *en50221_app_mmi; + +/** + * Create an instance of the mmi resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(en50221_app_mmi mmi, + uint16_t session_number, + uint8_t reply_id, + struct en502221_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(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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c new file mode 100644 index 0000000..7c57aba --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c @@ -0,0 +1,294 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + +en50221_app_rm en50221_app_rm_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_rm_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_rm_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->enqcallback = NULL; + private->replycallback = NULL; + private->changedcallback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_rm_destroy(en50221_app_rm rm) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_rm_register_enq_callback(en50221_app_rm rm, + en50221_app_rm_enq_callback callback, void *arg) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + + pthread_mutex_lock(&private->lock); + private->enqcallback = callback; + private->enqcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_rm_register_reply_callback(en50221_app_rm rm, + en50221_app_rm_reply_callback callback, void *arg) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + + pthread_mutex_lock(&private->lock); + private->replycallback = callback; + private->replycallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_rm_register_changed_callback(en50221_app_rm rm, + en50221_app_rm_changed_callback callback, void *arg) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + + pthread_mutex_lock(&private->lock); + private->changedcallback = callback; + private->changedcallback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_rm_enq(en50221_app_rm rm, uint16_t session_number) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + 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 private->funcs->send_data(private->funcs->arg, session_number, buf, 4); +} + +int en50221_app_rm_reply(en50221_app_rm rm, uint16_t session_number, + uint32_t resource_id_count, + uint32_t *resource_ids) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2); +} + +int en50221_app_rm_changed(en50221_app_rm rm, uint16_t session_number) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + 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 private->funcs->send_data(private->funcs->arg, session_number, buf, 4); +} + +int en50221_app_rm_message(en50221_app_rm rm, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_PROFILE: + return en50221_app_rm_parse_profile_reply(private, slot_id, session_number, data+3, data_length-3); + case TAG_PROFILE_CHANGE: + return en50221_app_rm_parse_profile_change(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_rm_parse_profile_enq(struct en50221_app_rm_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length) +{ + (void)data; + (void)data_length; + + pthread_mutex_lock(&private->lock); + en50221_app_rm_enq_callback cb = private->enqcallback; + void *cb_arg = private->enqcallback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_rm_reply_callback cb = private->replycallback; + void *cb_arg = private->replycallback_arg; + pthread_mutex_unlock(&private->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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length) +{ + (void)data; + (void)data_length; + + pthread_mutex_lock(&private->lock); + en50221_app_rm_changed_callback cb = private->changedcallback; + void *cb_arg = private->changedcallback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number); + } + return 0; +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h new file mode 100644 index 0000000..696065d --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h @@ -0,0 +1,178 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_rm; + +/** + * Create an instance of the resource manager. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c new file mode 100644 index 0000000..83015ae --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c @@ -0,0 +1,293 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + +en50221_app_smartcard en50221_app_smartcard_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_smartcard_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_smartcard_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->command_callback = NULL; + private->send_callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_smartcard_destroy(en50221_app_smartcard smartcard) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_smartcard_register_command_callback(en50221_app_smartcard smartcard, + en50221_app_smartcard_command_callback callback, void *arg) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + + pthread_mutex_lock(&private->lock); + private->command_callback = callback; + private->command_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +void en50221_app_smartcard_register_send_callback(en50221_app_smartcard smartcard, + en50221_app_smartcard_send_callback callback, void *arg) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + + pthread_mutex_lock(&private->lock); + private->send_callback = callback; + private->send_callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_smartcard_command_reply(en50221_app_smartcard smartcard, + uint16_t session_number, + uint8_t reply_id, + uint8_t status, + uint8_t *data, + uint32_t data_length) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iovec, iov_count); +} + +int en50221_app_smartcard_receive(en50221_app_smartcard smartcard, + uint16_t session_number, + uint8_t *data, + uint32_t data_length, + uint8_t SW1, + uint8_t SW2) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 3); +} + +int en50221_app_smartcard_message(en50221_app_smartcard smartcard, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard; + (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(private, slot_id, session_number, data+3, data_length-3); + case TAG_SMARTCARD_SEND: + return en50221_app_smartcard_parse_send(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_smartcard_parse_command(struct en50221_app_smartcard_private *private, + 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(&private->lock); + en50221_app_smartcard_command_callback cb = private->command_callback; + void *cb_arg = private->command_callback_arg; + pthread_mutex_unlock(&private->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_private *private, + 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(&private->lock); + en50221_app_smartcard_send_callback cb = private->send_callback; + void *cb_arg = private->send_callback_arg; + pthread_mutex_unlock(&private->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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h new file mode 100644 index 0000000..56655c4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h @@ -0,0 +1,191 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_smartcard; + +/** + * Create an instance of the smartcard resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h new file mode 100644 index 0000000..2086a80 --- /dev/null +++ b/kaffeine/src/input/dvb/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 (manu@kromtek.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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c new file mode 100644 index 0000000..cc2ee41 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c @@ -0,0 +1,139 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private { + 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_private *private, + uint8_t slot_id, uint16_t session_number, + uint8_t *data, uint32_t data_length); + + + +en50221_app_teletext en50221_app_teletext_create(struct en50221_app_send_functions *funcs) +{ + struct en50221_app_teletext_private *private = NULL; + + // create structure and set it up + private = malloc(sizeof(struct en50221_app_teletext_private)); + if (private == NULL) { + return NULL; + } + private->funcs = funcs; + private->callback = NULL; + + pthread_mutex_init(&private->lock, NULL); + + // done + return private; +} + +void en50221_app_teletext_destroy(en50221_app_teletext teletext) +{ + struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext; + + pthread_mutex_destroy(&private->lock); + free(private); +} + +void en50221_app_teletext_register_callback(en50221_app_teletext teletext, + en50221_app_teletext_callback callback, void *arg) +{ + struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext; + + pthread_mutex_lock(&private->lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->lock); +} + +int en50221_app_teletext_message(en50221_app_teletext teletext, + uint8_t slot_id, + uint16_t session_number, + uint32_t resource_id, + uint8_t *data, uint32_t data_length) +{ + struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext; + (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(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_teletext_parse_ebu(struct en50221_app_teletext_private *private, + 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(&private->lock); + en50221_app_teletext_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->lock); + if (cb) { + return cb(cb_arg, slot_id, session_number, teletext_data, asn_data_length); + } + return 0; +} + diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h new file mode 100644 index 0000000..1164d94 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h @@ -0,0 +1,104 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *en50221_app_teletext; + +/** + * Create an instance of the teletext resource. + * + * @param funcs Send functions to use. + * @return Instance, or NULL on failure. + */ +extern 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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c new file mode 100644 index 0000000..af68846 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c @@ -0,0 +1,37 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h new file mode 100644 index 0000000..34ca68f --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h @@ -0,0 +1,105 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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; +}; + +/** + * 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. + */ + int (*send_data)(void *arg, uint16_t session_number, uint8_t *data, uint16_t data_length); + + /** + * Send vector data. + */ + int (*send_datav)(void *arg, uint16_t session_number, struct iovec *vector, int iov_count); +}; + +/** + * 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h new file mode 100644 index 0000000..045a6a5 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h @@ -0,0 +1,52 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 session layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c new file mode 100644 index 0000000..1cc9a2e --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c @@ -0,0 +1,954 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private +{ + uint32_t max_sessions; + 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_private *private, + uint32_t resource_id, + uint8_t slot_id, + uint8_t connection_id, + en50221_sl_resource_callback callback, void* arg); + + + + +en50221_session_layer en50221_sl_create(en50221_transport_layer tl, + uint32_t max_sessions) +{ + struct en50221_session_layer_private *private = NULL; + uint32_t i; + + // setup structure + private = (struct en50221_session_layer_private*) malloc(sizeof(struct en50221_session_layer_private)); + if (private == NULL) + goto error_exit; + private->max_sessions = max_sessions; + private->lookup = NULL; + private->session = NULL; + private->tl = tl; + private->error = 0; + + // init the mutex + pthread_mutex_init(&private->global_lock, NULL); + pthread_mutex_init(&private->setcallback_lock, NULL); + + // create the slots + private->sessions = malloc(sizeof(struct en50221_session) * max_sessions); + if (private->sessions == NULL) + goto error_exit; + + // set them up + for(i=0; i< max_sessions; i++) { + private->sessions[i].state = S_STATE_IDLE; + private->sessions[i].callback = NULL; + + pthread_mutex_init(&private->sessions[i].session_lock, NULL); + } + + // register ourselves with the transport layer + en50221_tl_register_callback(tl, en50221_sl_transport_callback, private); + + return private; + +error_exit: + en50221_sl_destroy(private); + return NULL; +} + +void en50221_sl_destroy(en50221_session_layer sl) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + uint32_t i; + + if (private) { + if (private->sessions) { + for(i=0; i< private->max_sessions; i++) { + pthread_mutex_destroy(&private->sessions[i].session_lock); + } + free(private->sessions); + } + + pthread_mutex_destroy(&private->setcallback_lock); + pthread_mutex_destroy(&private->global_lock); + + free(private); + } +} + +int en50221_sl_get_error(en50221_session_layer tl) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) tl; + return private->error; +} + +void en50221_sl_register_lookup_callback(en50221_session_layer sl, en50221_sl_lookup_callback callback, void *arg) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + pthread_mutex_lock(&private->setcallback_lock); + private->lookup = callback; + private->lookup_arg = arg; + pthread_mutex_unlock(&private->setcallback_lock); +} + +void en50221_sl_register_session_callback(en50221_session_layer sl, + en50221_sl_session_callback callback, void *arg) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + pthread_mutex_lock(&private->setcallback_lock); + private->session = callback; + private->session_arg = arg; + pthread_mutex_unlock(&private->setcallback_lock); +} + +int en50221_sl_create_session(en50221_session_layer sl, int slot_id, uint8_t connection_id, uint32_t resource_id, + en50221_sl_resource_callback callback, void* arg) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + // lookup next free session_id: + pthread_mutex_lock(&private->global_lock); + int session_number = en50221_sl_alloc_new_session(private, resource_id, slot_id, connection_id, callback, arg); + if (session_number == -1) { + pthread_mutex_unlock(&private->global_lock); + return -1; + } + pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 8)) { + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (private->sessions[session_number].state == S_STATE_IN_CREATION) { + private->sessions[session_number].state = S_STATE_IDLE; + } + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + + private->error = en50221_tl_get_error(private->tl); + return -1; + } + + // ok. + return session_number; +} + +int en50221_sl_destroy_session(en50221_session_layer sl, uint16_t session_number) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + if (session_number >= private->max_sessions) { + private->error = EN50221ERR_BADSESSIONNUMBER; + return -1; + } + + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (!(private->sessions[session_number].state & (S_STATE_ACTIVE|S_STATE_IN_DELETION))) { + private->error = EN50221ERR_BADSESSIONNUMBER; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return -1; + } + + // set the state + private->sessions[session_number].state = S_STATE_IN_DELETION; + + // get essential details + uint8_t slot_id = private->sessions[session_number].slot_id; + uint8_t connection_id = private->sessions[session_number].connection_id; + pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 4)) { + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (private->sessions[session_number].state == S_STATE_IN_DELETION) { + private->sessions[session_number].state = S_STATE_IDLE; + } + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + + private->error = en50221_tl_get_error(private->tl); + return -1; + } + + return 0; +} + +int en50221_sl_send_data(en50221_session_layer sl, uint16_t session_number, uint8_t *data, uint16_t data_length) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + if (session_number >= private->max_sessions) { + private->error = EN50221ERR_BADSESSIONNUMBER; + return -1; + } + + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (private->sessions[session_number].state != S_STATE_ACTIVE) { + private->error = EN50221ERR_BADSESSIONNUMBER; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return -1; + } + + // get essential details + uint8_t slot_id = private->sessions[session_number].slot_id; + uint8_t connection_id = private->sessions[session_number].connection_id; + pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, iov, 2)) { + private->error = en50221_tl_get_error(private->tl); + return -1; + } + + return 0; +} + +int en50221_sl_send_datav(en50221_session_layer sl, uint16_t session_number, + struct iovec *vector, int iov_count) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + + if (session_number >= private->max_sessions) { + private->error = EN50221ERR_BADSESSIONNUMBER; + return -1; + } + + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (private->sessions[session_number].state != S_STATE_ACTIVE) { + private->error = EN50221ERR_BADSESSIONNUMBER; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return -1; + } + if (iov_count > 9) { + private->error = EN50221ERR_IOVLIMIT; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return -1; + } + uint8_t slot_id = private->sessions[session_number].slot_id; + uint8_t connection_id = private->sessions[session_number].connection_id; + pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, out_iov, iov_count+1)) { + private->error = en50221_tl_get_error(private->tl); + return -1; + } + return 0; +} + +int en50221_sl_broadcast_data(en50221_session_layer sl, int slot_id, uint32_t resource_id, + uint8_t *data, uint16_t data_length) +{ + struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl; + uint32_t i; + + for(i = 0; i < private->max_sessions; i++) + { + pthread_mutex_lock(&private->sessions[i].session_lock); + + if (private->sessions[i].state != S_STATE_ACTIVE) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + if ((slot_id != -1) && (slot_id != private->sessions[i].slot_id)) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + + if (private->sessions[i].resource_id == resource_id) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + en50221_sl_send_data(sl, i, data, data_length); + } else { + pthread_mutex_unlock(&private->sessions[i].session_lock); + } + } + + return 0; +} + + + +static void en50221_sl_handle_open_session_request(struct en50221_session_layer_private *private, + 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(&private->setcallback_lock); + en50221_sl_lookup_callback lcb = private->lookup; + void *lcb_arg = private->lookup_arg; + pthread_mutex_unlock(&private->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(&private->global_lock); + session_number = en50221_sl_alloc_new_session(private, connected_resource_id, slot_id, connection_id, + resource_callback, resource_arg); + pthread_mutex_unlock(&private->global_lock); + + if (session_number == -1) { + status = S_STATUS_CLOSE_NO_RES; + } else { + // inform upper layers/ check availability + pthread_mutex_lock(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 9)) { + print(LOG_LEVEL, ERROR, 1, "Transport layer error %i occurred\n", en50221_tl_get_error(private->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(&private->sessions[session_number].session_lock); + if (status != S_STATUS_OPEN) { + private->sessions[session_number].state = S_STATE_IDLE; + } else { + private->sessions[session_number].state = S_STATE_ACTIVE; + } + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + + // tell upper layers + if (private->sessions[session_number].state == S_STATE_ACTIVE) { + pthread_mutex_lock(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->setcallback_lock); + + if (status == S_STATUS_OPEN) { + if (cb) + cb(cb_arg, S_SCALLBACK_REASON_CAMCONNECTED, slot_id, session_number, connected_resource_id); + } else { + private->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_private *private, + 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 >= private->max_sessions) { + code = 0xF0; // session close error + print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id); + } else { + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (slot_id != private->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 != private->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 (!(private->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) { + private->sessions[session_number].state = S_STATE_IDLE; + code = 0x00; // close ok + } + resource_id = private->sessions[session_number].resource_id; + pthread_mutex_unlock(&private->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(private->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(private->tl), slot_id); + } + + // callback to announce destruction to resource if it was ok + if (code == 0x00) { + pthread_mutex_lock(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->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_private *private, + 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 >= private->max_sessions) { + print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id); + return; + } + + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (slot_id != private->sessions[session_number].slot_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (connection_id != private->sessions[session_number].connection_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (private->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(&private->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]); + private->sessions[session_number].state = S_STATE_IDLE; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + + // inform upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->setcallback_lock); + if (cb) + cb(cb_arg, S_SCALLBACK_REASON_CONNECTFAIL, slot_id, session_number, + private->sessions[session_number].resource_id); + return; + } + + // set it active + private->sessions[session_number].state = S_STATE_ACTIVE; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + + // inform upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->setcallback_lock); + if (cb) + cb(cb_arg, S_SCALLBACK_REASON_CONNECTED, slot_id, session_number, + private->sessions[session_number].resource_id); +} + +static void en50221_sl_handle_close_session_response(struct en50221_session_layer_private *private, + 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 >= private->max_sessions) { + print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id); + return; + } + + pthread_mutex_lock(&private->sessions[session_number].session_lock); + if (slot_id != private->sessions[session_number].slot_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (connection_id != private->sessions[session_number].connection_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (private->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(&private->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 + private->sessions[session_number].state = S_STATE_IDLE; + pthread_mutex_unlock(&private->sessions[session_number].session_lock); +} + +static void en50221_sl_handle_session_package(struct en50221_session_layer_private *private, + 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 >= private->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(&private->sessions[session_number].session_lock); + if (slot_id != private->sessions[session_number].slot_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (connection_id != private->sessions[session_number].connection_id) { + print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id); + pthread_mutex_unlock(&private->sessions[session_number].session_lock); + return; + } + if (private->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(&private->sessions[session_number].session_lock); + return; + } + + en50221_sl_resource_callback cb = private->sessions[session_number].callback; + void *cb_arg = private->sessions[session_number].callback_arg; + uint32_t resource_id = private->sessions[session_number].resource_id; + pthread_mutex_unlock(&private->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_private *private = (struct en50221_session_layer_private *) 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(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->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(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->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(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->setcallback_lock); + + for(i=0; i< private->max_sessions; i++) { + pthread_mutex_lock(&private->sessions[i].session_lock); + + if (private->sessions[i].state == S_STATE_IDLE) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + if (private->sessions[i].connection_id != connection_id) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + + private->sessions[i].state = S_STATE_IDLE; + + uint8_t slot_id = private->sessions[i].slot_id; + uint32_t resource_id = private->sessions[i].resource_id; + pthread_mutex_unlock(&private->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(&private->setcallback_lock); + en50221_sl_session_callback cb = private->session; + void *cb_arg = private->session_arg; + pthread_mutex_unlock(&private->setcallback_lock); + + for(i=0; i< private->max_sessions; i++) { + pthread_mutex_lock(&private->sessions[i].session_lock); + + if (private->sessions[i].state == S_STATE_IDLE) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + if (private->sessions[i].slot_id != slot_id) { + pthread_mutex_unlock(&private->sessions[i].session_lock); + continue; + } + private->sessions[i].state = S_STATE_IDLE; + + uint32_t resource_id = private->sessions[i].resource_id; + pthread_mutex_unlock(&private->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(private, data+1, data_length-1, slot_id, connection_id); + break; + + case ST_CLOSE_SESSION_REQ: + en50221_sl_handle_close_session_request(private, data+1, data_length-1, slot_id, connection_id); + break; + + case ST_SESSION_NUMBER: + en50221_sl_handle_session_package(private, data+1, data_length-1, slot_id, connection_id); + break; + + case ST_CREATE_SESSION_RES: + en50221_sl_handle_create_session_response(private, data+1, data_length-1, slot_id, connection_id); + break; + + case ST_CLOSE_SESSION_RES: + en50221_sl_handle_close_session_response(private, 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_private *private, + 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 < private->max_sessions; i++) { + if (private->sessions[i].state == S_STATE_IDLE) { + session_number = i; + break; + } + } + if (session_number == -1) { + private->error = EN50221ERR_OUTOFSESSIONS; + return -1; + } + + // setup the session + private->sessions[session_number].state = S_STATE_IN_CREATION; + private->sessions[session_number].resource_id = resource_id; + private->sessions[session_number].slot_id = slot_id; + private->sessions[session_number].connection_id = connection_id; + private->sessions[session_number].callback = callback; + private->sessions[session_number].callback_arg = arg; + + // ok + return session_number; +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h new file mode 100644 index 0000000..c7cc6a8 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h @@ -0,0 +1,212 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 session layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *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 en50221_session_layer en50221_sl_create(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(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(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(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(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(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(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(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(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(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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c new file mode 100644 index 0000000..ff7c936 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c @@ -0,0 +1,1240 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 transport layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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_private +{ + 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_private *tl, uint8_t slot_id, + uint8_t *data, uint32_t data_length); +static int en50221_tl_poll_tc(struct en50221_transport_layer_private *tl, uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_alloc_new_tc(struct en50221_transport_layer_private *tl, uint8_t slot_id); +static void queue_message(struct en50221_transport_layer_private *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_private *private, + uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_handle_delete_tc(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_handle_request_tc(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id); +static int en50221_tl_handle_data_more(struct en50221_transport_layer_private *private, + 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_private *private, + 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_private *private, + uint8_t slot_id, uint8_t connection_id, + uint8_t *data, uint32_t data_length); + + +en50221_transport_layer en50221_tl_create(uint8_t max_slots, uint8_t max_connections_per_slot) +{ + struct en50221_transport_layer_private *private = NULL; + int i; + int j; + + // setup structure + private = (struct en50221_transport_layer_private*) malloc(sizeof(struct en50221_transport_layer_private)); + if (private == NULL) + goto error_exit; + private->max_slots = max_slots; + private->max_connections_per_slot = max_connections_per_slot; + private->slots = NULL; + private->slot_pollfds = NULL; + private->slots_changed = 1; + private->callback = NULL; + private->callback_arg = NULL; + private->error_slot = 0; + private->error = 0; + pthread_mutex_init(&private->global_lock, NULL); + pthread_mutex_init(&private->setcallback_lock, NULL); + + // create the slots + private->slots = malloc(sizeof(struct en50221_slot) * max_slots); + if (private->slots == NULL) + goto error_exit; + + // set them up + for(i=0; i< max_slots; i++) { + private->slots[i].ca_hndl = -1; + + // create the connections for this slot + private->slots[i].connections = malloc(sizeof(struct en50221_connection) * max_connections_per_slot); + if (private->slots[i].connections == NULL) + goto error_exit; + + // create a mutex for the slot + pthread_mutex_init(&private->slots[i].slot_lock, NULL); + + // set them up + for(j = 0; j < max_connections_per_slot; j++) { + private->slots[i].connections[j].state = T_STATE_IDLE; + private->slots[i].connections[j].tx_time.tv_sec = 0; + private->slots[i].connections[j].last_poll_time.tv_sec = 0; + private->slots[i].connections[j].last_poll_time.tv_usec = 0; + private->slots[i].connections[j].chain_buffer = NULL; + private->slots[i].connections[j].buffer_length = 0; + private->slots[i].connections[j].send_queue = NULL; + private->slots[i].connections[j].send_queue_tail = NULL; + } + } + + // create the pollfds + private->slot_pollfds = malloc(sizeof(struct pollfd) * max_slots); + if (private->slot_pollfds == NULL) { + goto error_exit; + } + memset(private->slot_pollfds, 0, sizeof(struct pollfd) * max_slots); + + return private; + +error_exit: + en50221_tl_destroy(private); + return NULL; +} + +// Destroy an instance of the transport layer +void en50221_tl_destroy(en50221_transport_layer tl) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + int i, j; + + if (private) { + if (private->slots) { + for(i=0; i< private->max_slots; i++) { + if (private->slots[i].connections) { + for(j=0; j<private->max_connections_per_slot; j++) { + if (private->slots[i].connections[j].chain_buffer) { + free(private->slots[i].connections[j].chain_buffer); + } + + struct en50221_message *cur_msg = private->slots[i].connections[j].send_queue; + while(cur_msg) { + struct en50221_message *next_msg = cur_msg->next; + free(cur_msg); + cur_msg = next_msg; + } + private->slots[i].connections[j].send_queue = NULL; + private->slots[i].connections[j].send_queue_tail = NULL; + } + free(private->slots[i].connections); + pthread_mutex_destroy(&private->slots[i].slot_lock); + } + } + free(private->slots); + } + if (private->slot_pollfds) { + free(private->slot_pollfds); + } + pthread_mutex_destroy(&private->setcallback_lock); + pthread_mutex_destroy(&private->global_lock); + free(private); + } +} + +// this can be called from the user-space app to +// register new slots that we should work with +int en50221_tl_register_slot(en50221_transport_layer tl, int ca_hndl, uint8_t slot, + uint32_t response_timeout, uint32_t poll_delay) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + + // lock + pthread_mutex_lock(&private->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 < private->max_slots; i++) { + if (private->slots[i].ca_hndl == -1) { + slot_id = i; + break; + } + } + if (slot_id == -1) { + private->error = EN50221ERR_OUTOFSLOTS; + pthread_mutex_unlock(&private->global_lock); + return -1; + } + + // set up the slot struct + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + private->slots[slot_id].ca_hndl = ca_hndl; + private->slots[slot_id].slot = slot; + private->slots[slot_id].response_timeout = response_timeout; + private->slots[slot_id].poll_delay = poll_delay; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + + private->slots_changed = 1; + pthread_mutex_unlock(&private->global_lock); + return slot_id; +} + +void en50221_tl_destroy_slot(en50221_transport_layer tl, uint8_t slot_id) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + int i; + + if (slot_id >= private->max_slots) + return; + + // lock + pthread_mutex_lock(&private->global_lock); + + // clear the slot + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + private->slots[slot_id].ca_hndl = -1; + for(i=0; i<private->max_connections_per_slot; i++) { + private->slots[slot_id].connections[i].state = T_STATE_IDLE; + private->slots[slot_id].connections[i].tx_time.tv_sec = 0; + private->slots[slot_id].connections[i].last_poll_time.tv_sec = 0; + private->slots[slot_id].connections[i].last_poll_time.tv_usec = 0; + if (private->slots[slot_id].connections[i].chain_buffer) { + free(private->slots[slot_id].connections[i].chain_buffer); + } + private->slots[slot_id].connections[i].chain_buffer = NULL; + private->slots[slot_id].connections[i].buffer_length = 0; + + struct en50221_message *cur_msg = private->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; + } + private->slots[slot_id].connections[i].send_queue = NULL; + private->slots[slot_id].connections[i].send_queue_tail = NULL; + } + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + + // tell upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->setcallback_lock); + if (cb) + cb(cb_arg, T_CALLBACK_REASON_SLOTCLOSE, NULL, 0, slot_id, 0); + + private->slots_changed = 1; + pthread_mutex_unlock(&private->global_lock); +} + +int en50221_tl_poll(en50221_transport_layer tl) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + uint8_t data[4096]; + int slot_id; + int j; + + // make up pollfds if the slots have changed + pthread_mutex_lock(&private->global_lock); + if (private->slots_changed) { + for(slot_id = 0; slot_id < private->max_slots; slot_id++) { + if (private->slots[slot_id].ca_hndl != -1) { + private->slot_pollfds[slot_id].fd = private->slots[slot_id].ca_hndl; + private->slot_pollfds[slot_id].events = POLLIN|POLLPRI|POLLERR; + private->slot_pollfds[slot_id].revents = 0; + } else { + private->slot_pollfds[slot_id].fd = 0; + private->slot_pollfds[slot_id].events = 0; + private->slot_pollfds[slot_id].revents = 0; + } + } + private->slots_changed = 0; + } + pthread_mutex_unlock(&private->global_lock); + + // anything happened? + if (poll(private->slot_pollfds, private->max_slots, 10) < 0) { + private->error_slot = -1; + private->error = EN50221ERR_CAREAD; + return -1; + } + + // go through all slots (even though poll may not have reported any events + for(slot_id = 0; slot_id < private->max_slots; slot_id++) { + + // check if this slot is still used and get its handle + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + continue; + } + int ca_hndl = private->slots[slot_id].ca_hndl; + + if (private->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) { + private->error_slot = slot_id; + private->error = EN50221ERR_CAREAD; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + + // process it if we got some + if (readcnt > 0) { + if (private->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 < private->max_slots; new_slot_id++) { + if ((private->slots[new_slot_id].ca_hndl == ca_hndl) && (private->slots[new_slot_id].slot == r_slot_id)) + break; + } + if (new_slot_id != private->max_slots) { + // we found the requested CAM + pthread_mutex_lock(&private->slots[new_slot_id].slot_lock); + if (en50221_tl_process_data(private, new_slot_id, data, readcnt)) { + pthread_mutex_unlock(&private->slots[new_slot_id].slot_lock); + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + pthread_mutex_unlock(&private->slots[new_slot_id].slot_lock); + } else { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + } + else if (en50221_tl_process_data(private, slot_id, data, readcnt)) { + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + } + } else if (private->slot_pollfds[slot_id].revents & POLLERR) { + // an error was reported + private->error_slot = slot_id; + private->error = EN50221ERR_CAREAD; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + + // poll the connections on this slot + check for timeouts + for(j=0; j < private->max_connections_per_slot; j++) { + // ignore connection if idle + if (private->slots[slot_id].connections[j].state == T_STATE_IDLE) { + continue; + } + + // send queued data + if (private->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 (private->slots[slot_id].connections[j].send_queue && + (private->slots[slot_id].connections[j].tx_time.tv_sec == 0)) { + + // get the message + struct en50221_message *msg = private->slots[slot_id].connections[j].send_queue; + if (msg->next != NULL) { + private->slots[slot_id].connections[j].send_queue = msg->next; + } else { + private->slots[slot_id].connections[j].send_queue = NULL; + private->slots[slot_id].connections[j].send_queue_tail = NULL; + } + + // send the message + if (dvbca_link_write(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, j, msg->data, msg->length) < 0) { + free(msg); + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + print(LOG_LEVEL, ERROR, 1, "CAWrite failed"); + return -1; + } + gettimeofday(&private->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)) { + private->slots[slot_id].connections[j].state = T_STATE_IN_DELETION; + if (private->slots[slot_id].connections[j].chain_buffer) { + free(private->slots[slot_id].connections[j].chain_buffer); + } + private->slots[slot_id].connections[j].chain_buffer = NULL; + private->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 (private->slots[slot_id].connections[j].state & T_STATE_ACTIVE) { + if ((private->slots[slot_id].connections[j].tx_time.tv_sec == 0) && + (time_after(private->slots[slot_id].connections[j].last_poll_time, private->slots[slot_id].poll_delay))) { + + gettimeofday(&private->slots[slot_id].connections[j].last_poll_time, 0); + if (en50221_tl_poll_tc(private, slot_id, j)) { + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + } + } + + // check for timeouts - in any state + if (private->slots[slot_id].connections[j].tx_time.tv_sec && + (time_after(private->slots[slot_id].connections[j].tx_time, private->slots[slot_id].response_timeout))) { + + if (private->slots[slot_id].connections[j].state & (T_STATE_IN_CREATION|T_STATE_IN_DELETION)) { + private->slots[slot_id].connections[j].state = T_STATE_IDLE; + } else if (private->slots[slot_id].connections[j].state & (T_STATE_ACTIVE|T_STATE_ACTIVE_DELETEQUEUED)) { + private->error_slot = slot_id; + private->error = EN50221ERR_TIMEOUT; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + } + } + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + } + + return 0; +} + +void en50221_tl_register_callback(en50221_transport_layer tl, en50221_tl_callback callback, void *arg) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + + pthread_mutex_lock(&private->setcallback_lock); + private->callback = callback; + private->callback_arg = arg; + pthread_mutex_unlock(&private->setcallback_lock); +} + +int en50221_tl_get_error_slot(en50221_transport_layer tl) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + return private->error_slot; +} + +int en50221_tl_get_error(en50221_transport_layer tl) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + return private->error; +} + +int en50221_tl_send_data(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id, + uint8_t *data, uint32_t data_size) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + +#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 >= private->max_slots) { + private->error = EN50221ERR_BADSLOTID; + return -1; + } + + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (connection_id >= private->max_connections_per_slot) { + private->error_slot = slot_id; + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (private->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->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) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + pthread_mutex_unlock(&private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_ASNENCODE; + pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg); + + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return 0; +} + +int en50221_tl_send_datav(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id, + struct iovec *vector, int iov_count) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + +#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 >= private->max_slots) { + private->error = EN50221ERR_BADSLOTID; + return -1; + } + + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (connection_id >= private->max_connections_per_slot) { + private->error_slot = slot_id; + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (private->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) { + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->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) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + pthread_mutex_unlock(&private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_ASNENCODE; + pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg); + + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return 0; +} + +int en50221_tl_new_tc(en50221_transport_layer tl, uint8_t slot_id) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + + // check + if (slot_id >= private->max_slots) { + private->error = EN50221ERR_BADSLOTID; + return -1; + } + + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + + // allocate a new connection if possible + int conid = en50221_tl_alloc_new_tc(private, slot_id); + if (conid == -1) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFCONNECTIONS; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + + // allocate msg structure + struct en50221_message *msg = malloc(sizeof(struct en50221_message)+3); + if (msg == NULL) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + pthread_mutex_unlock(&private->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(private, slot_id, conid, msg); + + // done + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return conid; +} + +int en50221_tl_del_tc(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + + // check + if (slot_id >= private->max_slots) { + private->error = EN50221ERR_BADSLOTID; + return -1; + } + + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (connection_id >= private->max_connections_per_slot) { + private->error_slot = slot_id; + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (!(private->slots[slot_id].connections[connection_id].state & + (T_STATE_ACTIVE|T_STATE_IN_DELETION))) { + private->error_slot = slot_id; + private->error = EN50221ERR_BADSTATE; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + + // allocate msg structure + struct en50221_message *msg = malloc(sizeof(struct en50221_message)+3); + if (msg == NULL) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg); + private->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE_DELETEQUEUED; + + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return 0; +} + +int en50221_tl_get_connection_state(en50221_transport_layer tl, + uint8_t slot_id, uint8_t connection_id) +{ + struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl; + + if (slot_id >= private->max_slots) { + private->error = EN50221ERR_BADSLOTID; + return -1; + } + + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + if (private->slots[slot_id].ca_hndl == -1) { + private->error = EN50221ERR_BADSLOTID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + if (connection_id >= private->max_connections_per_slot) { + private->error_slot = slot_id; + private->error = EN50221ERR_BADCONNECTIONID; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + return -1; + } + int state = private->slots[slot_id].connections[connection_id].state; + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + + return state; +} + + + + +// ask the module for new data +static int en50221_tl_poll_tc(struct en50221_transport_layer_private *private, uint8_t slot_id, uint8_t connection_id) +{ + gettimeofday(&private->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(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) { + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + return 0; +} + +// handle incoming data +static int en50221_tl_process_data(struct en50221_transport_layer_private *private, 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); + private->error_slot = slot_id; + private->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); + private->error_slot = slot_id; + private->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 >= private->max_connections_per_slot) { + print(LOG_LEVEL, ERROR, 1, "Received bad connection id %02x from module on slot %02x\n", connection_id, slot_id); + private->error_slot = slot_id; + private->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(private, slot_id, connection_id)) < 0) { + return -1; + } + break; + case T_DELETE_T_C: + if ((result = en50221_tl_handle_delete_tc(private, slot_id, connection_id)) < 0) { + return -1; + } + break; + case T_D_T_C_REPLY: + if ((result = en50221_tl_handle_delete_tc_reply(private, slot_id, connection_id)) < 0) { + return -1; + } + break; + case T_REQUEST_T_C: + if ((result = en50221_tl_handle_request_tc(private, slot_id, connection_id)) < 0) { + return -1; + } + break; + case T_DATA_MORE: + if ((result = en50221_tl_handle_data_more(private, slot_id, connection_id, data, asn_data_length)) < 0) { + return -1; + } + break; + case T_DATA_LAST: + if ((result = en50221_tl_handle_data_last(private, slot_id, connection_id, data, asn_data_length)) < 0) { + return -1; + } + break; + case T_SB: + if ((result = en50221_tl_handle_sb(private, 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); + private->error_slot = slot_id; + private->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_private *private, + uint8_t slot_id, uint8_t connection_id) +{ + // set this connection to state active + if (private->slots[slot_id].connections[connection_id].state == T_STATE_IN_CREATION) { + private->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE; + private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + + // tell upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + return 0; +} + +static int en50221_tl_handle_delete_tc(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id) +{ + // immediately delete this connection and send D_T_C_REPLY + if (private->slots[slot_id].connections[connection_id].state & (T_STATE_ACTIVE|T_STATE_IN_DELETION)) + { + // clear down the slot + private->slots[slot_id].connections[connection_id].state = T_STATE_IDLE; + if (private->slots[slot_id].connections[connection_id].chain_buffer) { + free(private->slots[slot_id].connections[connection_id].chain_buffer); + } + private->slots[slot_id].connections[connection_id].chain_buffer = NULL; + private->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(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) { + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + + // tell upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + return 0; +} + +static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id) +{ + // delete this connection, should be in T_STATE_IN_DELETION already + if (private->slots[slot_id].connections[connection_id].state == T_STATE_IN_DELETION) { + private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + return 0; +} + +static int en50221_tl_handle_request_tc(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id) +{ + // allocate a new connection if possible + int conid = en50221_tl_alloc_new_tc(private, slot_id); + int ca_hndl = private->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, private->slots[slot_id].slot, connection_id, hdr, 4) < 0) { + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + private->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, private->slots[slot_id].slot, connection_id, hdr, 4) < 0) { + private->slots[slot_id].connections[conid].state = T_STATE_IDLE; + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + private->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, private->slots[slot_id].slot, conid, hdr, 3) < 0) { + private->slots[slot_id].connections[conid].state = T_STATE_IDLE; + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + gettimeofday(&private->slots[slot_id].connections[conid].tx_time, 0); + + // tell upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->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_private *private, + uint8_t slot_id, uint8_t connection_id, + uint8_t *data, uint32_t data_length) +{ + // connection in correct state? + if (private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + // a chained data packet is coming in, save + // it to the buffer and wait for more + private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + int new_data_length = + private->slots[slot_id].connections[connection_id].buffer_length + data_length; + uint8_t *new_data_buffer = + realloc(private->slots[slot_id].connections[connection_id].chain_buffer, new_data_length); + if (new_data_buffer == NULL) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + return -1; + } + private->slots[slot_id].connections[connection_id].chain_buffer = new_data_buffer; + + memcpy(private->slots[slot_id].connections[connection_id].chain_buffer + + private->slots[slot_id].connections[connection_id].buffer_length, + data, data_length); + private->slots[slot_id].connections[connection_id].buffer_length = new_data_length; + + return 0; +} + +static int en50221_tl_handle_data_last(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id, + uint8_t *data, uint32_t data_length) +{ + // connection in correct state? + if (private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + // last package of a chain or single package comes in + private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + if (private->slots[slot_id].connections[connection_id].chain_buffer == NULL) + { + // single package => dispatch immediately + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->setcallback_lock); + + if (cb && data_length) { + pthread_mutex_unlock(&private->slots[slot_id].slot_lock); + cb(cb_arg, T_CALLBACK_REASON_DATA, data, data_length, slot_id, connection_id); + pthread_mutex_lock(&private->slots[slot_id].slot_lock); + } + } + else + { + int new_data_length = private->slots[slot_id].connections[connection_id].buffer_length + data_length; + uint8_t *new_data_buffer = + realloc(private->slots[slot_id].connections[connection_id].chain_buffer, new_data_length); + if (new_data_buffer == NULL) { + private->error_slot = slot_id; + private->error = EN50221ERR_OUTOFMEMORY; + return -1; + } + + memcpy(new_data_buffer + private->slots[slot_id].connections[connection_id].buffer_length, data, data_length); + + // clean the buffer position + private->slots[slot_id].connections[connection_id].chain_buffer = NULL; + private->slots[slot_id].connections[connection_id].buffer_length = 0; + + // tell the upper layers + pthread_mutex_lock(&private->setcallback_lock); + en50221_tl_callback cb = private->callback; + void *cb_arg = private->callback_arg; + pthread_mutex_unlock(&private->setcallback_lock); + if (cb && data_length) { + pthread_mutex_unlock(&private->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(&private->slots[slot_id].slot_lock); + } + + free(new_data_buffer); + } + + return 0; +} + +static int en50221_tl_handle_sb(struct en50221_transport_layer_private *private, + uint8_t slot_id, uint8_t connection_id, + uint8_t *data, uint32_t data_length) +{ + // is the connection id ok? + if (private->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); + private->error_slot = slot_id; + private->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); + private->error_slot = slot_id; + private->error = EN50221ERR_BADCAMDATA; + return -1; + } + + // tell it to send the data if it says there is some + if (data[0] & 0x80) { + int ca_hndl = private->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, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) { + private->error_slot = slot_id; + private->error = EN50221ERR_CAWRITE; + return -1; + } + gettimeofday(&private->slots[slot_id].connections[connection_id].tx_time, 0); + + } else { + // no data - indicate not waiting for anything now + private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0; + } + + return 0; +} + +static int en50221_tl_alloc_new_tc(struct en50221_transport_layer_private *private, 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 < private->max_connections_per_slot; i++) { + if (private->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 + private->slots[slot_id].connections[conid].state = T_STATE_IN_CREATION; + private->slots[slot_id].connections[conid].chain_buffer = NULL; + private->slots[slot_id].connections[conid].buffer_length = 0; + + return conid; +} + +static void queue_message(struct en50221_transport_layer_private *private, uint8_t slot_id, + uint8_t connection_id, struct en50221_message *msg) +{ + msg->next = NULL; + if (private->slots[slot_id].connections[connection_id].send_queue_tail) { + private->slots[slot_id].connections[connection_id].send_queue_tail->next = msg; + } else { + private->slots[slot_id].connections[connection_id].send_queue = msg; + private->slots[slot_id].connections[connection_id].send_queue_tail = msg; + } +} diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h new file mode 100644 index 0000000..59dc64c --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h @@ -0,0 +1,231 @@ +/* + en50221 encoder An implementation for libdvb + an implementation for the en50221 session layer + + Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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. + */ +typedef void *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 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(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(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(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(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(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(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(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(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(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(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(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(en50221_transport_layer tl, + uint8_t slot_id, uint8_t connection_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h b/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h new file mode 100644 index 0000000..75713f4 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h @@ -0,0 +1,72 @@ +/* + libdvbmisc - DVB miscellaneous library + + Copyright (C) 2005 Manu Abraham <manu@kromtek.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/kaffeine/src/input/dvb/lib/libucsi/Makefile.am b/kaffeine/src/input/dvb/lib/libucsi/Makefile.am new file mode 100644 index 0000000..071f310 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libucsi.la + +SUBDIRS = dvb mpeg . + +INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib + +libucsi_la_SOURCES = crc32.c \ + section_buf.c \ + transport_packet.c + +libucsi_la_LDFLAGS = ./mpeg \ + ./dvb + +libucsi_la_LIBADD = ./mpeg/libdvbmpeg.la \ + ./dvb/libdvbdvb.la + +CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h new file mode 100644 index 0000000..a18b29d --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/atsc/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_ATSC_DESCRIPTOR_H +#define _UCSI_ATSC_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/endianops.h> + +/** + * Enumeration of ATSC descriptor tags. + */ +enum atsc_descriptor_tag { + +/* A 52/A describes a + * dtag_atsc_ac3_registration = 0x05, */ + +/* A90 describes a + * dtag_atsc_association_tag = 0x14, */ + + dtag_atsc_stuffing = 0x80, + dtag_atsc_ac3_audio = 0x81, + dtag_atsc_caption_service = 0x86, + dtag_atsc_content_advisory = 0x87, + dtag_atsc_ca = 0x88, + dtag_atsc_extended_channel_name = 0xa0, + dtag_atsc_service_location = 0xa1, + dtag_atsc_time_shifted_service = 0xa2, + dtag_atsc_component_name = 0xa3, + dtag_atsc_data_service = 0xa4, + dtag_atsc_pid_count = 0xa5, + dtag_atsc_download = 0xa6, + dtag_atsc_MPE = 0xa7, + dtag_atsc_dcc_departing_request = 0xa8, + dtag_atsc_dcc_arriving_request = 0xa9, + dtag_atsc_redistribution_control = 0xaa, + dtag_atsc_dcc_location_code = 0xab, + dtag_atsc_private_information = 0xad, + dtag_atsc_module_link = 0xb4, + dtag_atsc_crc32 = 0xb5, + dtag_atsc_group_link = 0xb8, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h new file mode 100644 index 0000000..e693b9d --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h @@ -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 + */ + +#ifndef _UCSI_ATSC_SECTION_H +#define _UCSI_ATSC_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Enumeration of ATSC section tags. + */ +enum atsc_section_tag { +/* 0xC0-0xC6 [ATSC coordinated values which are defined in other standards.] */ + 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_informationen = 0xcb, + stag_atsc_extended_text = 0xcc, + stag_atsc_system_time = 0xcd, + + stag_atsc_data_event = 0xce, + stag_atsc_data_service = 0xcf, + stag_atsc_network_resources = 0xd1, + stag_atsc_long_term_serivce = 0xd2, +/* identical to DVB/ISO ? + 0x3F DSM-CC Addressable Section Table + 0x3B DSM-CC Section Table + 0x3C DSM-CC Section Table */ + + /* 0xCE-0xD2 [ATSC coordinated values which are defined in other standards.] */ + stag_atsc_directed_channel_change = 0xd3, + stag_atsc_directed_channel_change_selection_code = 0xd4, + + /* 0xD5-0xDF [ATSC coordinated values which are defined in other standards.] */ + stag_atsc_aggregate_event_information = 0xd6, + stag_atsc_aggregate_extended_text = 0xd7, + stag_atsc_satellite_virtual_channel = 0xda, + + /* 0xE0-0xE5 [Used in other systems] */ + /* 0xE6-0xFE [Reserved for future ATSC use] */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kaffeine/src/input/dvb/lib/libucsi/crc32.c b/kaffeine/src/input/dvb/lib/libucsi/crc32.c new file mode 100644 index 0000000..dc1de5c --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/crc32.h b/kaffeine/src/input/dvb/lib/libucsi/crc32.h new file mode 100644 index 0000000..5d77e84 --- /dev/null +++ b/kaffeine/src/input/dvb/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, int len) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/descriptor.h new file mode 100644 index 0000000..809936d --- /dev/null +++ b/kaffeine/src/input/dvb/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, int 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, int len) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/Makefile.am b/kaffeine/src/input/dvb/lib/libucsi/dvb/Makefile.am new file mode 100644 index 0000000..b358273 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libdvbdvb.la + +INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib + +libdvbdvb_la_SOURCES = bat_section.c \ + dit_section.c \ + eit_section.c \ + int_section.c \ + nit_section.c \ + rst_section.c \ + sdt_section.c \ + sit_section.c \ + st_section.c \ + tdt_section.c \ + tot_section.c \ + tva_container_section.c \ + types.c + +CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h new file mode 100644 index 0000000..d60e37b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h new file mode 100644 index 0000000..69a21b8 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h new file mode 100644 index 0000000..877d9c0 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h new file mode 100644 index 0000000..5ea5932 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_name_descriptor.h new file mode 100644 index 0000000..a4b719e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h new file mode 100644 index 0000000..34f584a --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h new file mode 100644 index 0000000..7a0280d --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h new file mode 100644 index 0000000..55a570b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h new file mode 100644 index 0000000..c1d50ff --- /dev/null +++ b/kaffeine/src/input/dvb/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_countries_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/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c new file mode 100644 index 0000000..afbeb0f --- /dev/null +++ b/kaffeine/src/input/dvb/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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h new file mode 100644 index 0000000..277d5ab --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/bouquet_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/bouquet_name_descriptor.h new file mode 100644 index 0000000..a298849 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ca_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ca_identifier_descriptor.h new file mode 100644 index 0000000..ac670a9 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h new file mode 100644 index 0000000..70b0c98 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h new file mode 100644 index 0000000..b6285bd --- /dev/null +++ b/kaffeine/src/input/dvb/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_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_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/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h new file mode 100644 index 0000000..6a42ce4 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h new file mode 100644 index 0000000..154e235 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h new file mode 100644 index 0000000..5cc16dc --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h new file mode 100644 index 0000000..63d24a1 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h @@ -0,0 +1,222 @@ +/* + * 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 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/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h new file mode 100644 index 0000000..29a6b9a --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_descriptor.h new file mode 100644 index 0000000..069e1db --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h new file mode 100644 index 0000000..8547d8f --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.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_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> + +/** + * 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; + +/** + * 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; +} + +#ifdef __cplusplus +} +#endif + +#endif + +#include <libucsi/dvb/mhp_data_broadcast_id_descriptor.h> diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/default_authority_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/default_authority_descriptor.h new file mode 100644 index 0000000..0b0ba73 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h new file mode 100644 index 0000000..0772601 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h @@ -0,0 +1,198 @@ +/* + * 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/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/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/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> +#include <libucsi/endianops.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, + + /* 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 +};/*__ucsi_packed;*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/dit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/dit_section.c new file mode 100644 index 0000000..4f69d4e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/dit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/dit_section.h new file mode 100644 index 0000000..69fce4f --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/dsng_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/dsng_descriptor.h new file mode 100644 index 0000000..6fd369b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c new file mode 100644 index 0000000..ce22a58 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h new file mode 100644 index 0000000..9064224 --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h new file mode 100644 index 0000000..82d580b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h new file mode 100644 index 0000000..4fca751 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c new file mode 100644 index 0000000..a6ddd6e --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_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) + * 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; + + unsigned int pos = sizeof(struct section_ext); + unsigned int len = section_ext_length(ext); + + if (len < sizeof(struct dvb_int_section)) + return NULL; + + bswap32(buf+8); + bswap16(buf+12); + pos += 9; + + 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/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h new file mode 100644 index 0000000..71ba1e8 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h new file mode 100644 index 0000000..f3370c8 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h @@ -0,0 +1,478 @@ +/* + * 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; , + uint32_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) { + 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_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/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h new file mode 100644 index 0000000..94932ff --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h new file mode 100644 index 0000000..d5cf435 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h new file mode 100644 index 0000000..28838de --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h new file mode 100644 index 0000000..0d8deb1 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_component_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_component_descriptor.h new file mode 100644 index 0000000..ab156af --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_network_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_network_name_descriptor.h new file mode 100644 index 0000000..1a7b8c4 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_service_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/multilingual_service_name_descriptor.h new file mode 100644 index 0000000..31bb9c3 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/network_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/network_name_descriptor.h new file mode 100644 index 0000000..0754597 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c new file mode 100644 index 0000000..d931926 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_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) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General 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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.h new file mode 100644 index 0000000..77ab1a0 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/nvod_reference_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/nvod_reference_descriptor.h new file mode 100644 index 0000000..6180514 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h new file mode 100644 index 0000000..9acbcb0 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h new file mode 100644 index 0000000..c8ba441 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h new file mode 100644 index 0000000..49cc187 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/private_data_specifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/private_data_specifier_descriptor.h new file mode 100644 index 0000000..f4cc03c --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/related_content_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/related_content_descriptor.h new file mode 100644 index 0000000..fd6a358 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h new file mode 100644 index 0000000..b67b0d9 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h new file mode 100644 index 0000000..cc0ed58 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h new file mode 100644 index 0000000..cb74f75 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c new file mode 100644 index 0000000..67fa0d3 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + int pos = sizeof(struct section); + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h new file mode 100644 index 0000000..b4269b8 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h @@ -0,0 +1,111 @@ +/* + * 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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h new file mode 100644 index 0000000..66c9288 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h new file mode 100644 index 0000000..23be76e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/scrambling_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/scrambling_descriptor.h new file mode 100644 index 0000000..4669bc8 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c new file mode 100644 index 0000000..bdc8ce1 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h new file mode 100644 index 0000000..0130fe7 --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h new file mode 100644 index 0000000..8488d71 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h new file mode 100644 index 0000000..f16781b --- /dev/null +++ b/kaffeine/src/input/dvb/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 uint32_t * + dvb_service_availability_descriptor_cell_ids(struct dvb_service_availability_descriptor *d) +{ + return (uint32_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/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h new file mode 100644 index 0000000..e116ffc --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h @@ -0,0 +1,156 @@ +/* + * 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_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/kaffeine/src/input/dvb/lib/libucsi/dvb/service_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_identifier_descriptor.h new file mode 100644 index 0000000..2037a05 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/service_list_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_list_descriptor.h new file mode 100644 index 0000000..0086b25 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/service_move_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_move_descriptor.h new file mode 100644 index 0000000..7685e65 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/short_event_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/short_event_descriptor.h new file mode 100644 index 0000000..449c6f0 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h new file mode 100644 index 0000000..7deab9b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c new file mode 100644 index 0000000..61134d0 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c @@ -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 + */ + +#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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h new file mode 100644 index 0000000..d05989f --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/st_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/st_section.c new file mode 100644 index 0000000..0e60aa1 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/st_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/st_section.h new file mode 100644 index 0000000..52ba888 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/stream_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/stream_identifier_descriptor.h new file mode 100644 index 0000000..262c7e2 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/stuffing_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/stuffing_descriptor.h new file mode 100644 index 0000000..48e415d --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/subtitling_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/subtitling_descriptor.h new file mode 100644 index 0000000..74fc25a --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c new file mode 100644 index 0000000..30a23cf --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int len = section->length + sizeof(struct 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/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.h new file mode 100644 index 0000000..fc2bcb8 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h new file mode 100644 index 0000000..46b39e4 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h new file mode 100644 index 0000000..280b6eb --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h new file mode 100644 index 0000000..b890178 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/time_shifted_event_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/time_shifted_event_descriptor.h new file mode 100644 index 0000000..6b4a9f6 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/time_shifted_service_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/time_shifted_service_descriptor.h new file mode 100644 index 0000000..c8dcc0e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c new file mode 100644 index 0000000..3ce2c6d --- /dev/null +++ b/kaffeine/src/input/dvb/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; + int pos = sizeof(struct section); + int len = section->length + sizeof(struct 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/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.h new file mode 100644 index 0000000..3474da1 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/transport_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/transport_stream_descriptor.h new file mode 100644 index 0000000..1797ec5 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c new file mode 100644 index 0000000..32a5795 --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h new file mode 100644 index 0000000..6519ded --- /dev/null +++ b/kaffeine/src/input/dvb/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 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_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/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h new file mode 100644 index 0000000..c830259 --- /dev/null +++ b/kaffeine/src/input/dvb/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_countries_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/kaffeine/src/input/dvb/lib/libucsi/dvb/types.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/types.c new file mode 100644 index 0000000..c1cf583 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h new file mode 100644 index 0000000..f26ea6b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h new file mode 100644 index 0000000..9d41e0c --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h new file mode 100644 index 0000000..6ae9791 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/endianops.h b/kaffeine/src/input/dvb/lib/libucsi/endianops.h new file mode 100644 index 0000000..23b418b --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/Makefile.am b/kaffeine/src/input/dvb/lib/libucsi/mpeg/Makefile.am new file mode 100644 index 0000000..a8d0c32 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/Makefile.am @@ -0,0 +1,12 @@ +noinst_LTLIBRARIES = libdvbmpeg.la + +INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib + +libdvbmpeg_la_SOURCES = cat_section.c \ + metadata_section.c \ + odsmt_section.c \ + pat_section.c \ + pmt_section.c \ + tsdt_section.c + +CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/audio_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/audio_stream_descriptor.h new file mode 100644 index 0000000..7e6ea07 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/ca_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/ca_descriptor.h new file mode 100644 index 0000000..88a65dd --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c new file mode 100644 index 0000000..c72973e --- /dev/null +++ b/kaffeine/src/input/dvb/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; + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h new file mode 100644 index 0000000..864b19e --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/content_labelling_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/content_labelling_descriptor.h new file mode 100644 index 0000000..06738ab --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/copyright_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/copyright_descriptor.h new file mode 100644 index 0000000..5991fe9 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/data_stream_alignment_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/data_stream_alignment_descriptor.h new file mode 100644 index 0000000..887495f --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/descriptor.h new file mode 100644 index 0000000..c32775f --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/external_es_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/external_es_id_descriptor.h new file mode 100644 index 0000000..3aa3237 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/fmc_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/fmc_descriptor.h new file mode 100644 index 0000000..5a5bed2 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h new file mode 100644 index 0000000..74f643c --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/hierarchy_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/hierarchy_descriptor.h new file mode 100644 index 0000000..a38539d --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/ibp_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/ibp_descriptor.h new file mode 100644 index 0000000..e82780a --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/iod_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/iod_descriptor.h new file mode 100644 index 0000000..61de153 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/iso_639_language_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/iso_639_language_descriptor.h new file mode 100644 index 0000000..5b5aac0 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/maximum_bitrate_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/maximum_bitrate_descriptor.h new file mode 100644 index 0000000..e0bcddb --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_descriptor.h new file mode 100644 index 0000000..5b91e05 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_pointer_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_pointer_descriptor.h new file mode 100644 index 0000000..e4d7503 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c new file mode 100644 index 0000000..9af1d96 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c @@ -0,0 +1,28 @@ +/* + * 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.h new file mode 100644 index 0000000..62c4e03 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_std_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_std_descriptor.h new file mode 100644 index 0000000..fc83e6e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/mpeg4_audio_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/mpeg4_audio_descriptor.h new file mode 100644 index 0000000..f876759 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/mpeg4_video_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/mpeg4_video_descriptor.h new file mode 100644 index 0000000..b956b91 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/multiplex_buffer_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/multiplex_buffer_descriptor.h new file mode 100644 index 0000000..d55ce3d --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h new file mode 100644 index 0000000..16550ed --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/muxcode_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/muxcode_descriptor.h new file mode 100644 index 0000000..6bed334 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c new file mode 100644 index 0000000..c56ccb1 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + int pos = sizeof(struct section_ext); + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h new file mode 100644 index 0000000..2e5302d --- /dev/null +++ b/kaffeine/src/input/dvb/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 __ucsi_packed; + struct mpeg_odsmt_stream_multi multi __ucsi_packed; + } u __ucsi_packed; +} __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, + uint32_t* len); + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct mpeg_odsmt_stream * + mpeg_odsmt_section_streams_first(struct mpeg_odsmt_section *odsmt) +{ + int 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, + uint32_t* len) +{ + struct mpeg_odsmt_stream* pos; + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c new file mode 100644 index 0000000..80b28d5 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + int pos = sizeof(struct section_ext); + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h new file mode 100644 index 0000000..20b3f7a --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c new file mode 100644 index 0000000..6ff4fac --- /dev/null +++ b/kaffeine/src/input/dvb/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; + unsigned int pos = sizeof(struct section_ext); + unsigned int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h new file mode 100644 index 0000000..73bba1d --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/private_data_indicator_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/private_data_indicator_descriptor.h new file mode 100644 index 0000000..80e8ef3 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/registration_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/registration_descriptor.h new file mode 100644 index 0000000..df5c186 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h new file mode 100644 index 0000000..6215e95 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/sl_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/sl_descriptor.h new file mode 100644 index 0000000..ab086e3 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/smoothing_buffer_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/smoothing_buffer_descriptor.h new file mode 100644 index 0000000..5e6ad33 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/std_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/std_descriptor.h new file mode 100644 index 0000000..2625a41 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/system_clock_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/system_clock_descriptor.h new file mode 100644 index 0000000..681641f --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/target_background_grid_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/target_background_grid_descriptor.h new file mode 100644 index 0000000..7394e82 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c new file mode 100644 index 0000000..fbbbe3c --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c @@ -0,0 +1,35 @@ +/* + * 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; + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h new file mode 100644 index 0000000..9039278 --- /dev/null +++ b/kaffeine/src/input/dvb/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) +{ + int 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/kaffeine/src/input/dvb/lib/libucsi/mpeg/types.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/types.h new file mode 100644 index 0000000..300cb23 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/video_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/video_stream_descriptor.h new file mode 100644 index 0000000..14e9196 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/mpeg/video_window_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/video_window_descriptor.h new file mode 100644 index 0000000..a9a63c7 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/section.h b/kaffeine/src/input/dvb/lib/libucsi/section.h new file mode 100644 index 0000000..e2f7551 --- /dev/null +++ b/kaffeine/src/input/dvb/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; + + +/** + * 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, int len) +{ + struct section * ret = (struct section *)buf; + + if (len < 3) + return NULL; + + bswap16(buf+1); + + if (len != ret->length + 3) + 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; + int len = sizeof(struct section) + section->length; + 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; + + /* zap the current CRC value */ + memset(buf+len-4, 0, 4); + + /* the crc has to be performed on the swapped data */ + bswap16(buf+1); + crc = crc32(CRC32_INIT, buf, len); + bswap16(buf+1); + + /* update the CRC */ + *((uint32_t*) (buf+len-4)) = crc; + bswap32(buf+len-4); + } + + return (struct section_ext *)section; +} + +/** + * Determine the total length of a section, including the header. + * + * @param section The parsed section structure. + * @return The length. + */ +static inline int 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 int section_ext_length(struct section_ext * section) +{ + return section->length + sizeof(struct section) - CRC_SIZE; +} + +/** + * 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) && (section->section_number == 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/kaffeine/src/input/dvb/lib/libucsi/section_buf.c b/kaffeine/src/input/dvb/lib/libucsi/section_buf.c new file mode 100644 index 0000000..35d465e --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/section_buf.h b/kaffeine/src/input/dvb/lib/libucsi/section_buf.h new file mode 100644 index 0000000..e15cc1d --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/section_buf.h @@ -0,0 +1,125 @@ +/* + * 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); + +/** + * 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. + */ +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/kaffeine/src/input/dvb/lib/libucsi/testrecord.txt b/kaffeine/src/input/dvb/lib/libucsi/testrecord.txt new file mode 100644 index 0000000..259ffe1 --- /dev/null +++ b/kaffeine/src/input/dvb/lib/libucsi/testrecord.txt @@ -0,0 +1,101 @@ +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 + +Descriptors: +PASS mpeg/audio_stream_descriptor.h +PASS mpeg/ca_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/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/ancillary_data_descriptor.h + dvb/announcement_support_descriptor.h + dvb/bouquet_name_descriptor.h + dvb/ca_identifier_descriptor.h + dvb/ca_system_descriptor.h + dvb/cable_delivery_descriptor.h + dvb/cell_frequency_link_descriptor.h + dvb/cell_list_descriptor.h + dvb/component_descriptor.h + dvb/content_descriptor.h + dvb/country_availability_descriptor.h + dvb/data_broadcast_descriptor.h + dvb/data_broadcast_id_descriptor.h + dvb/descriptor.h + dvb/dsng_descriptor.h + dvb/extended_event_descriptor.h + dvb/frequency_list_descriptor.h + dvb/linkage_descriptor.h + dvb/local_time_offset_descriptor.h + dvb/mosaic_descriptor.h + dvb/multilingual_bouquet_name_descriptor.h + dvb/multilingual_component_descriptor.h + dvb/multilingual_network_name_descriptor.h + dvb/multilingual_service_name_descriptor.h + dvb/network_name_descriptor.h + dvb/nvod_reference_descriptor.h + dvb/parental_rating_descriptor.h + dvb/partial_transport_stream_descriptor.h + dvb/pdc_descriptor.h + dvb/private_data_specifier_descriptor.h + dvb/satellite_delivery_descriptor.h + dvb/service_descriptor.h + dvb/service_list_descriptor.h + dvb/service_move_descriptor.h + dvb/short_event_descriptor.h + dvb/short_smoothing_buffer_descriptor.h + dvb/stream_identifier_descriptor.h + dvb/stuffing_descriptor.h + dvb/subtitling_descriptor.h + dvb/telephone_descriptor.h + dvb/teletext_descriptor.h + dvb/terrestrial_delivery_descriptor.h + dvb/time_shifted_event_descriptor.h + dvb/time_shifted_service_descriptor.h + dvb/transport_stream_descriptor.h + dvb/vbi_data_descriptor.h + dvb/vbi_teletext_descriptor.h diff --git a/kaffeine/src/input/dvb/lib/libucsi/transport_packet.c b/kaffeine/src/input/dvb/lib/libucsi/transport_packet.c new file mode 100644 index 0000000..ca6c2e1 --- /dev/null +++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h b/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h new file mode 100644 index 0000000..7dfbd78 --- /dev/null +++ b/kaffeine/src/input/dvb/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. + * @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/kaffeine/src/input/dvb/lib/libucsi/types.h b/kaffeine/src/input/dvb/lib/libucsi/types.h new file mode 100644 index 0000000..b01d79a --- /dev/null +++ b/kaffeine/src/input/dvb/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 |