aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libdvbsec
diff options
context:
space:
mode:
authoretobi <git@e-tobi.net>2013-09-03 09:48:41 +0200
committeretobi <git@e-tobi.net>2013-09-03 09:48:41 +0200
commitab959d7b4194715870128e616b8e29d4a101e488 (patch)
tree61a746231d30817be73416a7d67763fd677a1042 /lib/libdvbsec
parent6b350466c4902c5b137e0efaf1d189128a7f18f5 (diff)
downloadlinux-dvb-apps-upstream/1.1.1+rev1207.tar.gz
Imported Upstream version 1.1.1+rev1207upstream/1.1.1+rev1207
Diffstat (limited to 'lib/libdvbsec')
-rw-r--r--lib/libdvbsec/Makefile17
-rw-r--r--lib/libdvbsec/dvbsec_api.c951
-rw-r--r--lib/libdvbsec/dvbsec_api.h436
-rw-r--r--lib/libdvbsec/dvbsec_cfg.c366
-rw-r--r--lib/libdvbsec/dvbsec_cfg.h203
5 files changed, 1973 insertions, 0 deletions
diff --git a/lib/libdvbsec/Makefile b/lib/libdvbsec/Makefile
new file mode 100644
index 0000000..3d405f4
--- /dev/null
+++ b/lib/libdvbsec/Makefile
@@ -0,0 +1,17 @@
+# Makefile for linuxtv.org dvb-apps/lib/libdvbsec
+
+includes = dvbsec_api.h \
+ dvbsec_cfg.h
+
+objects = dvbsec_api.o \
+ dvbsec_cfg.o
+
+lib_name = libdvbsec
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include ../../Make.rules
diff --git a/lib/libdvbsec/dvbsec_api.c b/lib/libdvbsec/dvbsec_api.c
new file mode 100644
index 0000000..5f2ae22
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_api.c
@@ -0,0 +1,951 @@
+/*
+ libdvbsec - an SEC library
+
+ Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <linux/types.h>
+#include <libdvbapi/dvbfe.h>
+#include "dvbsec_api.h"
+
+// uncomment this to make dvbsec_command print out debug instead of talking to a frontend
+// #define TEST_SEC_COMMAND 1
+
+int dvbsec_set(struct dvbfe_handle *fe,
+ struct dvbsec_config *sec_config,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option,
+ struct dvbfe_parameters *params,
+ int timeout)
+{
+ int tmp;
+ struct dvbfe_parameters localparams;
+ struct dvbfe_parameters *topass = params;
+
+ // perform SEC
+ if (sec_config != NULL) {
+ switch(sec_config->config_type) {
+ case DVBSEC_CONFIG_NONE:
+ break;
+
+ case DVBSEC_CONFIG_POWER:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+
+ case DVBSEC_CONFIG_STANDARD:
+ {
+ // calculate the correct oscillator value
+ enum dvbsec_diseqc_oscillator osc = DISEQC_OSCILLATOR_LOW;
+ if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
+ osc = DISEQC_OSCILLATOR_HIGH;
+
+ if ((tmp = dvbsec_std_sequence(fe,
+ osc,
+ polarization,
+ sat_pos,
+ switch_option)) < 0)
+ return tmp;
+ break;
+ }
+
+ case DVBSEC_CONFIG_ADVANCED:
+ {
+ // are we high or not?
+ int high = 0;
+ if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
+ high = 1;
+
+ // determine correct string
+ char *cmd = NULL;
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_h;
+ else
+ cmd = sec_config->adv_cmd_hi_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_v;
+ else
+ cmd = sec_config->adv_cmd_hi_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_l;
+ else
+ cmd = sec_config->adv_cmd_hi_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_r;
+ else
+ cmd = sec_config->adv_cmd_hi_r;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ // do it
+ if (cmd)
+ if ((tmp = dvbsec_command(fe, cmd)) < 0)
+ return tmp;
+ break;
+ }
+ }
+
+ // work out the correct LOF value
+ uint32_t lof = 0;
+ if ((sec_config->switch_frequency == 0) || (params->frequency < sec_config->switch_frequency)) {
+ // LOW band
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ lof = sec_config->lof_lo_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ lof = sec_config->lof_lo_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ lof = sec_config->lof_lo_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ lof = sec_config->lof_lo_r;
+ break;
+ case DISEQC_POLARIZATION_UNCHANGED:
+ break;
+ }
+ } else {
+ // HIGH band
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ lof = sec_config->lof_hi_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ lof = sec_config->lof_hi_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ lof = sec_config->lof_hi_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ lof = sec_config->lof_hi_r;
+ break;
+ case DISEQC_POLARIZATION_UNCHANGED:
+ break;
+ }
+ }
+
+ // do frequency adjustment
+ if (lof) {
+ memcpy(&localparams, params, sizeof(struct dvbfe_parameters));
+ int tmpfreq = localparams.frequency - lof;
+
+ if (tmpfreq < 0)
+ tmpfreq *= -1;
+ localparams.frequency = (uint32_t) tmpfreq;
+ topass = &localparams;
+ }
+ }
+
+ // set the frontend!
+ return dvbfe_set(fe, topass, timeout);
+}
+
+int dvbsec_std_sequence(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option)
+{
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+
+ switch(polarization) {
+ case DISEQC_POLARIZATION_V:
+ case DISEQC_POLARIZATION_R:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+ case DISEQC_POLARIZATION_H:
+ case DISEQC_POLARIZATION_L:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dvbsec_diseqc_set_committed_switches(fe,
+ DISEQC_ADDRESS_ANY_DEVICE,
+ oscillator,
+ polarization,
+ sat_pos,
+ switch_option);
+
+ usleep(15000);
+
+ switch(sat_pos) {
+ case DISEQC_SWITCH_A:
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
+ break;
+ case DISEQC_SWITCH_B:
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
+ break;
+ default:
+ break;
+ }
+
+ if (sat_pos != DISEQC_SWITCH_UNCHANGED)
+ usleep(15000);
+
+ switch(oscillator) {
+ case DISEQC_OSCILLATOR_LOW:
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+ break;
+ case DISEQC_OSCILLATOR_HIGH:
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_reset state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x00 };
+
+ if (state == DISEQC_RESET_CLEAR)
+ data[2] = 0x01;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_power(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_power state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x02 };
+
+ if (state == DISEQC_POWER_ON)
+ data[2] = 0x03;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_listen state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x30 };
+
+ if (state == DISEQC_LISTEN_AWAKE)
+ data[2] = 0x31;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x38, 0x00 };
+
+ switch(oscillator) {
+ case DISEQC_OSCILLATOR_LOW:
+ data[3] |= 0x10;
+ break;
+ case DISEQC_OSCILLATOR_HIGH:
+ data[3] |= 0x11;
+ break;
+ case DISEQC_OSCILLATOR_UNCHANGED:
+ break;
+ }
+ switch(polarization) {
+ case DISEQC_POLARIZATION_V:
+ case DISEQC_POLARIZATION_R:
+ data[3] |= 0x20;
+ break;
+ case DISEQC_POLARIZATION_H:
+ case DISEQC_POLARIZATION_L:
+ data[3] |= 0x22;
+ break;
+ default:
+ break;
+ }
+ switch(sat_pos) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x40;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x44;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(switch_option) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x80;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x88;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+
+ if (data[3] == 0)
+ return 0;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_switch s1,
+ enum dvbsec_diseqc_switch s2,
+ enum dvbsec_diseqc_switch s3,
+ enum dvbsec_diseqc_switch s4)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x39, 0x00 };
+
+ switch(s1) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x10;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x11;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s2) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x20;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x22;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s3) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x40;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x44;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s4) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x80;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x88;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+
+ if (data[3] == 0)
+ return 0;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_analog_id id,
+ uint8_t value)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x48, value };
+
+ if (id == DISEQC_ANALOG_ID_A1)
+ data[2] = 0x49;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint32_t frequency)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x58, 0x00, 0x00, 0x00 };
+ int len = 5;
+
+ uint32_t bcdval = 0;
+ int i;
+ for(i=0; i<=24;i+=4) {
+ bcdval |= ((frequency % 10) << i);
+ frequency /= 10;
+ }
+
+ data[3] = bcdval >> 16;
+ data[4] = bcdval >> 8;
+ if (bcdval & 0xff) {
+ data[5] = bcdval;
+ len++;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, len);
+}
+
+int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint16_t channel)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x59, 0x00, 0x00};
+
+ data[3] = channel >> 8;
+ data[4] = channel;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x60};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x63};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x66};
+
+ if (direction == DISEQC_DIRECTION_WEST)
+ data[2] = 0x67;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction,
+ enum dvbsec_diseqc_drive_mode mode,
+ uint8_t value)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x68, 0x00};
+
+ if (direction == DISEQC_DIRECTION_WEST)
+ data[2] = 0x69;
+
+ switch(mode) {
+ case DISEQC_DRIVE_MODE_STEPS:
+ data[3] = (value & 0x7f) | 0x80;
+ break;
+ case DISEQC_DRIVE_MODE_TIMEOUT:
+ data[3] = value & 0x7f;
+ break;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6A, id};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6B, id};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ int val1,
+ int val2)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6F, 0x00, 0x00};
+ int len = 3;
+
+ if (val1 != -1) {
+ data[3] = val1;
+ len++;
+ }
+ if (val2 != -1) {
+ data[4] = val2;
+ len = 5;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, len);
+}
+
+int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ float angle)
+{
+ int integer = (int) angle;
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6e, 0x00, 0x00};
+
+ // transform the fraction into the correct representation
+ int fraction = (int) (((angle - integer) * 16.0) + 0.9) & 0x0f;
+ switch(fraction) {
+ case 1:
+ case 4:
+ case 7:
+ case 9:
+ case 12:
+ case 15:
+ fraction--;
+ break;
+ }
+
+ // generate the command
+ if (integer < -256) {
+ return -EINVAL;
+ } else if (integer < 0) {
+ integer = -integer;
+ data[3] = 0xf0;
+ } else if (integer < 256) {
+ data[3] = 0x00;
+ } else if (integer < 512) {
+ integer -= 256;
+ data[3] = 0x10;
+ } else {
+ return -EINVAL;
+ }
+ data[3] |= ((integer / 16) & 0x0f);
+ integer = integer % 16;
+ data[4] |= ((integer & 0x0f) << 4) | fraction;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+static int skipwhite(char **line, char *end)
+{
+ while(**line) {
+ if (end && (*line >= end))
+ return -1;
+ if (!isspace(**line))
+ return 0;
+ (*line)++;
+ }
+
+ return -1;
+}
+
+static int getstringupto(char **line, char *end, char *matches, char **ptrdest, int *ptrlen)
+{
+ char *start = *line;
+
+ while(**line) {
+ if (end && (*line >= end))
+ break;
+ if (strchr(matches, **line)) {
+ *ptrdest = start;
+ *ptrlen = *line - start;
+ return 0;
+ }
+ (*line)++;
+ }
+
+ *ptrdest = start;
+ *ptrlen = *line - start;
+ return 0;
+}
+
+static int parsefunction(char **line,
+ char **nameptr, int *namelen,
+ char **argsptr, int *argslen)
+{
+ if (skipwhite(line, NULL))
+ return -1;
+
+ if (getstringupto(line, NULL, "(", nameptr, namelen))
+ return -1;
+ if ((*line) == 0)
+ return -1;
+ (*line)++; // skip the '('
+ if (getstringupto(line, NULL, ")", argsptr, argslen))
+ return -1;
+ if ((*line) == 0)
+ return -1;
+ (*line)++; // skip the ')'
+
+ return 0;
+}
+
+static int parseintarg(char **args, char *argsend, int *result)
+{
+ char tmp[32];
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 31)
+ arglen = 31;
+ strncpy(tmp, arg, arglen);
+ tmp[arglen] = 0;
+
+ if (sscanf(tmp, "%i", result) != 1)
+ return -1;
+
+ return 0;
+}
+
+static int parsechararg(char **args, char *argsend, int *result)
+{
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 0)
+ *result = arg[0];
+
+ return 0;
+}
+
+static int parsefloatarg(char **args, char *argsend, float *result)
+{
+ char tmp[32];
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 31)
+ arglen = 31;
+ strncpy(tmp, arg, arglen);
+ arg[arglen] = 0;
+
+ if (sscanf(tmp, "%f", result) != 1)
+ return -1;
+
+ return 0;
+}
+
+static enum dvbsec_diseqc_switch parse_switch(int c)
+{
+ switch(toupper(c)) {
+ case 'A':
+ return DISEQC_SWITCH_A;
+ case 'B':
+ return DISEQC_SWITCH_B;
+ default:
+ return DISEQC_SWITCH_UNCHANGED;
+ }
+}
+
+int dvbsec_command(struct dvbfe_handle *fe, char *command)
+{
+ char *name;
+ char *args;
+ int namelen;
+ int argslen;
+ int address;
+ int iarg;
+ int iarg2;
+ int iarg3;
+ int iarg4;
+ float farg;
+
+ while(!parsefunction(&command, &name, &namelen, &args, &argslen)) {
+ char *argsend = args+argslen;
+
+ if (!strncasecmp(name, "tone", namelen)) {
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("tone: %c\n", iarg);
+#else
+ if (toupper(iarg) == 'B') {
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
+ } else {
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+ }
+#endif
+ } else if (!strncasecmp(name, "voltage", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("voltage: %i\n", iarg);
+#else
+ switch(iarg) {
+ case 0:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_OFF);
+ break;
+ case 13:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+ case 18:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
+ break;
+ default:
+ return -1;
+ }
+#endif
+ } else if (!strncasecmp(name, "toneburst", namelen)) {
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("toneburst: %c\n", iarg);
+#else
+ if (toupper(iarg) == 'B') {
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
+ } else {
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
+ }
+#endif
+ } else if (!strncasecmp(name, "highvoltage", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("highvoltage: %i\n", iarg);
+#else
+ dvbfe_set_high_lnb_voltage(fe, iarg ? 1 : 0);
+#endif
+ } else if (!strncasecmp(name, "dishnetworks", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("dishnetworks: %i\n", iarg);
+#else
+ dvbfe_do_dishnetworks_legacy_command(fe, iarg);
+#endif
+ } else if (!strncasecmp(name, "wait", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("wait: %i\n", iarg);
+#else
+ if (iarg)
+ usleep(iarg * 1000);
+#endif
+ } else if (!strncasecmp(name, "Dreset", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dreset: %i %i\n", address, iarg);
+#else
+ if (iarg) {
+ dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET);
+ } else {
+ dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET_CLEAR);
+ }
+#endif
+ } else if (!strncasecmp(name, "Dpower", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dpower: %i %i\n", address, iarg);
+#else
+ if (iarg) {
+ dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_ON);
+ } else {
+ dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_OFF);
+ }
+#endif
+ } else if (!strncasecmp(name, "Dcommitted", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg2))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg3))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg4))
+ return -1;
+
+ enum dvbsec_diseqc_oscillator oscillator;
+ switch(toupper(iarg)) {
+ case 'H':
+ oscillator = DISEQC_OSCILLATOR_HIGH;
+ break;
+ case 'L':
+ oscillator = DISEQC_OSCILLATOR_LOW;
+ break;
+ default:
+ oscillator = DISEQC_OSCILLATOR_UNCHANGED;
+ break;
+ }
+
+ int polarization = -1;
+ switch(toupper(iarg2)) {
+ case 'H':
+ polarization = DISEQC_POLARIZATION_H;
+ break;
+ case 'V':
+ polarization = DISEQC_POLARIZATION_V;
+ break;
+ case 'L':
+ polarization = DISEQC_POLARIZATION_L;
+ break;
+ case 'R':
+ polarization = DISEQC_POLARIZATION_R;
+ break;
+ default:
+ polarization = -1;
+ break;
+ }
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dcommitted: %i %i %i %i %i\n", address,
+ oscillator,
+ polarization,
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#else
+ dvbsec_diseqc_set_committed_switches(fe, address,
+ oscillator,
+ polarization,
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#endif
+ } else if (!strncasecmp(name, "Duncommitted", namelen)) {
+ if (parsechararg(&args, argsend, &address))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg2))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg3))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg4))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Duncommitted: %i %i %i %i %i\n", address,
+ parse_switch(iarg),
+ parse_switch(iarg2),
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#else
+ dvbsec_diseqc_set_uncommitted_switches(fe, address,
+ parse_switch(iarg),
+ parse_switch(iarg2),
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#endif
+ } else if (!strncasecmp(name, "Dfrequency", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dfrequency: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_set_frequency(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dchannel", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dchannel: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_set_channel(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dgotopreset", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dgotopreset: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_goto_satpos_preset(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dgotobearing", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parsefloatarg(&args, argsend, &farg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dgotobearing: %i %f\n", address, farg);
+#else
+ dvbsec_diseqc_goto_rotator_bearing(fe, address, farg);
+#endif
+ } else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/libdvbsec/dvbsec_api.h b/lib/libdvbsec/dvbsec_api.h
new file mode 100644
index 0000000..7e454d7
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_api.h
@@ -0,0 +1,436 @@
+/*
+ libdvbsec - an SEC library
+
+ Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#ifndef DVBSEC_API_H
+#define DVBSEC_API_H 1
+
+#include <stdint.h>
+
+struct dvbfe_handle;
+struct dvbfe_parameters;
+
+enum dvbsec_diseqc_framing {
+ DISEQC_FRAMING_MASTER_NOREPLY = 0xE0,
+ DISEQC_FRAMING_MASTER_NOREPLY_REPEAT = 0xE1,
+ DISEQC_FRAMING_MASTER_REPLY = 0xE2,
+ DISEQC_FRAMING_MASTER_REPLY_REPEAT = 0xE3,
+ DISEQC_FRAMING_SLAVE_OK = 0xE4,
+ DISEQC_FRAMING_SLAVE_UNSUPPORTED = 0xE5,
+ DISEQC_FRAMING_SLAVE_PARITY_ERROR = 0xE6,
+ DISEQC_FRAMING_SLAVE_UNRECOGNISED = 0xE7,
+};
+
+enum dvbsec_diseqc_address {
+ DISEQC_ADDRESS_ANY_DEVICE = 0x00,
+
+ DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV = 0x10,
+ DISEQC_ADDRESS_LNB = 0x11,
+ DISEQC_ADDRESS_LNB_WITH_LOOP = 0x12,
+ DISEQC_ADDRESS_SWITCHER = 0x14,
+ DISEQC_ADDRESS_SWITCHER_WITH_LOOP = 0x15,
+ DISEQC_ADDRESS_SMATV = 0x18,
+
+ DISEQC_ADDRESS_ANY_POLARISER = 0x20,
+ DISEQC_ADDRESS_LINEAR_POLARISER = 0x21,
+
+ DISEQC_ADDRESS_ANY_POSITIONER = 0x30,
+ DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER = 0x31,
+ DISEQC_ADDRESS_ELEVATION_POSITIONER = 0x32,
+
+ DISEQC_ADDRESS_ANY_INSTALLER_AID = 0x40,
+ DISEQC_ADDRESS_SIGNAL_STRENGTH = 0x41,
+
+ DISEQC_ADDRESS_ANY_INTERFACE = 0x70,
+ DISEQC_ADDRESS_HEADEND_INTERFACE = 0x71,
+
+ DISEQC_ADDRESS_REALLOC_BASE = 0x60,
+ DISEQC_ADDRESS_OEM_BASE = 0xf0,
+};
+
+enum dvbsec_diseqc_reset {
+ DISEQC_RESET,
+ DISEQC_RESET_CLEAR,
+};
+
+enum dvbsec_diseqc_power {
+ DISEQC_POWER_OFF,
+ DISEQC_POWER_ON,
+};
+
+enum dvbsec_diseqc_listen {
+ DISEQC_LISTEN_SLEEP,
+ DISEQC_LISTEN_AWAKE,
+};
+
+enum dvbsec_diseqc_polarization {
+ DISEQC_POLARIZATION_UNCHANGED = 0,
+ DISEQC_POLARIZATION_H = 'h',
+ DISEQC_POLARIZATION_V = 'v',
+ DISEQC_POLARIZATION_L = 'l',
+ DISEQC_POLARIZATION_R = 'r',
+};
+
+enum dvbsec_diseqc_oscillator {
+ DISEQC_OSCILLATOR_UNCHANGED = 0,
+ DISEQC_OSCILLATOR_LOW,
+ DISEQC_OSCILLATOR_HIGH,
+};
+
+enum dvbsec_diseqc_switch {
+ DISEQC_SWITCH_UNCHANGED = 0,
+ DISEQC_SWITCH_A,
+ DISEQC_SWITCH_B,
+};
+
+enum dvbsec_diseqc_analog_id {
+ DISEQC_ANALOG_ID_A0,
+ DISEQC_ANALOG_ID_A1,
+};
+
+enum dvbsec_diseqc_drive_mode {
+ DISEQC_DRIVE_MODE_STEPS,
+ DISEQC_DRIVE_MODE_TIMEOUT,
+};
+
+enum dvbsec_diseqc_direction {
+ DISEQC_DIRECTION_EAST,
+ DISEQC_DIRECTION_WEST,
+};
+
+enum dvbsec_config_type {
+ DVBSEC_CONFIG_NONE = 0,
+ DVBSEC_CONFIG_POWER,
+ DVBSEC_CONFIG_STANDARD,
+ DVBSEC_CONFIG_ADVANCED,
+};
+
+
+#define MAX_SEC_CMD_LEN 100
+
+struct dvbsec_config
+{
+ char id[32]; /* ID of this SEC config structure */
+ uint32_t switch_frequency; /* switching frequency - supply 0 for none. */
+ uint32_t lof_lo_v; /* frequency to subtract for V + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_h; /* frequency to subtract for H + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_l; /* frequency to subtract for L + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_r; /* frequency to subtract for R + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_hi_v; /* frequency to subtract for V + HIGH band channels */
+ uint32_t lof_hi_h; /* frequency to subtract for H + HIGH band channels */
+ uint32_t lof_hi_l; /* frequency to subtract for L + HIGH band channels */
+ uint32_t lof_hi_r; /* frequency to subtract for R + HIGH band channels */
+
+ /**
+ * The SEC control to be used depends on the type:
+ *
+ * NONE - no SEC commands will be issued. (Frequency adjustment will still be performed).
+ *
+ * POWER - only the SEC power will be turned on.
+ *
+ * STANDARD - the standard DISEQC back compatable sequence is used.
+ *
+ * ADVANCED - SEC strings are supplied by the user describing the exact sequence
+ * of operations to use.
+ */
+ enum dvbsec_config_type config_type;
+
+ /* stuff for type == dvbsec_config_ADVANCED */
+ char adv_cmd_lo_h[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/H. */
+ char adv_cmd_lo_v[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/V. */
+ char adv_cmd_lo_l[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/L. */
+ char adv_cmd_lo_r[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/R. */
+ char adv_cmd_hi_h[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/H. */
+ char adv_cmd_hi_v[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/V. */
+ char adv_cmd_hi_l[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/L. */
+ char adv_cmd_hi_r[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/R. */
+};
+
+/**
+ * Helper function for tuning adapters with SEC support. This function will do
+ * everything required, including frequency adjustment based on the parameters
+ * in sec_config.
+ *
+ * Note: Since the SEC configuration structure can be set to disable any SEC
+ * operations, this function can be reused for ALL DVB style devices (just
+ * set all LOF=0,type=dvbsec_config_NONE for devices which do not require
+ * SEC control).
+ *
+ * The sec configuration structures can be looked up using the dvbcfg_sec library.
+ *
+ * @param fe Frontend concerned.
+ * @param sec_config SEC configuration structure. May be NULL to disable SEC/frequency adjustment.
+ * @param polarization Polarization of signal.
+ * @param sat_pos Satellite position - only used if type == DISEQC_SEC_CONFIG_STANDARD.
+ * @param switch_option Switch option - only used if type == DISEQC_SEC_CONFIG_STANDARD.
+ * @param params Tuning parameters.
+ * @param timeout <0 => wait forever for lock. 0=>return immediately, >0=>
+ * number of milliseconds to wait for a lock.
+ * @return 0 on locked (or if timeout==0 and everything else worked), or
+ * nonzero on failure (including no lock).
+ */
+extern int dvbsec_set(struct dvbfe_handle *fe,
+ struct dvbsec_config *sec_config,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option,
+ struct dvbfe_parameters *params,
+ int timeout);
+
+/**
+ * This will issue the standardised back-compatable DISEQC/SEC command
+ * sequence as defined in the DISEQC spec:
+ *
+ * i.e. tone off, set voltage, wait15, DISEQC, wait15, toneburst, wait15, set tone.
+ *
+ * @param fe Frontend concerned.
+ * @param oscillator Value to set the lo/hi switch to.
+ * @param polarization Value to set the polarisation switch to.
+ * @param sat_pos Value to set the satellite position switch to.
+ * @param switch_option Value to set the "swtch option" switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_std_sequence(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option);
+
+/**
+ * Execute an SEC command string on the provided frontend. Please see the documentation
+ * in dvbsec_cfg.h on the command format,
+ *
+ * @param fe Frontend concerned.
+ * @param command The command to execute.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_command(struct dvbfe_handle *fe, char *command);
+
+/**
+ * Control the reset status of an attached DISEQC device.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_reset state);
+
+/**
+ * Control the power status of an attached DISEQC peripheral.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_power(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_power state);
+
+/**
+ * Control the listening status of an attached DISEQC peripheral.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_listen state);
+
+/**
+ * Set the state of the committed switches of a DISEQC device.
+ * These are switches which are defined to have a standard name.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param oscillator Value to set the lo/hi switch to.
+ * @param polarization Value to set the polarization switch to.
+ * @param sat_pos Value to set the satellite position switch to.
+ * @param switch_option Value to set the switch option switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option);
+
+/**
+ * Set the state of the uncommitted switches of a DISEQC device.
+ * These provide another four switching possibilities.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param s1 Value to set the S1 switch to.
+ * @param s2 Value to set the S2 switch to.
+ * @param s3 Value to set the S3 switch to.
+ * @param s3 Value to set the S4 switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_switch s1,
+ enum dvbsec_diseqc_switch s2,
+ enum dvbsec_diseqc_switch s3,
+ enum dvbsec_diseqc_switch s4);
+
+/**
+ * Set an analogue value.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id The id of the analogue value to set.
+ * @param value The value to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_analog_id id,
+ uint8_t value);
+
+/**
+ * Set the desired frequency.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param frequency The frequency to set in GHz.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint32_t frequency);
+
+/**
+ * Set the desired channel.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param channel ID of the channel to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint16_t channel);
+
+/**
+ * Halt the satellite positioner.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address);
+
+/**
+ * Disable satellite positioner limits.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address);
+
+/**
+ * Set satellite positioner limits.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction);
+
+/**
+ * Drive satellite positioner motor.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param direction Direction to drive in.
+ * @param mode Drive mode to use
+ * (TIMEOUT=>value is a timeout in seconds, or STEPS=>value is a count of steps to use)
+ * @param value Value associated with the drive mode (range 0->127)
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction,
+ enum dvbsec_diseqc_drive_mode mode,
+ uint8_t value);
+
+/**
+ * Store satellite positioner preset id at current position.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id ID of the preset.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id);
+
+/**
+ * Send a satellite positioner to a pre-set position.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id ID of the preset.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id);
+
+/**
+ * Recalculate satellite positions based on the current position, using
+ * magic positioner specific values.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param val1 value1 (range 0->255, pass -1 to ignore).
+ * @param val2 value2 (range 0->255, pass -1 to ignore).
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ int val1,
+ int val2);
+
+/**
+ * Send a terrestrial aerial rotator to a particular bearing
+ * (0 degrees = north, fractional angles allowed).
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param angle Angle to rotate to (-256.0 -> 512.0)
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ float angle);
+
+#endif
diff --git a/lib/libdvbsec/dvbsec_cfg.c b/lib/libdvbsec/dvbsec_cfg.c
new file mode 100644
index 0000000..4b05a32
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_cfg.c
@@ -0,0 +1,366 @@
+/**
+ * dvbsec_cfg (i.e. linuxtv sec format) configuration file support.
+ *
+ * Copyright (c) 2005 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/types.h>
+#include "dvbsec_cfg.h"
+
+int dvbcfg_issection(char* line, char* sectionname)
+{
+ int len;
+
+ len = strlen(line);
+ if (len < 2)
+ return 0;
+
+ if ((line[0] != '[') || (line[len-1] != ']'))
+ return 0;
+
+ line++;
+ while(isspace(*line))
+ line++;
+
+ if (strncmp(line, sectionname, strlen(sectionname)))
+ return 0;
+
+ return 1;
+}
+
+char* dvbcfg_iskey(char* line, char* keyname)
+{
+ int len = strlen(keyname);
+
+ /* does the key match? */
+ if (strncmp(line, keyname, len))
+ return NULL;
+
+ /* skip keyname & any whitespace */
+ line += len;
+ while(isspace(*line))
+ line++;
+
+ /* should be the '=' sign */
+ if (*line != '=')
+ return 0;
+
+ /* more whitespace skipping */
+ line++;
+ while(isspace(*line))
+ line++;
+
+ /* finally, return the value */
+ return line;
+}
+
+int dvbsec_cfg_load(FILE *f,
+ void *arg,
+ dvbsec_cfg_callback cb)
+{
+ struct dvbsec_config tmpsec;
+ char *linebuf = NULL;
+ size_t line_size = 0;
+ int len;
+ int insection = 0;
+ char *value;
+
+ /* process each line */
+ while((len = getline(&linebuf, &line_size, f)) > 0) {
+ char *line = linebuf;
+
+ /* chop any comments */
+ char *hashpos = strchr(line, '#');
+ if (hashpos)
+ *hashpos = 0;
+ char *lineend = line + strlen(line);
+
+ /* trim the line */
+ while(*line && isspace(*line))
+ line++;
+ while((lineend != line) && isspace(*(lineend-1)))
+ lineend--;
+ *lineend = 0;
+
+ /* skip blank lines */
+ if (*line == 0)
+ continue;
+
+ if (dvbcfg_issection(line, "sec")) {
+ if (insection) {
+ if (cb(arg, &tmpsec))
+ return 0;
+ }
+ insection = 1;
+ memset(&tmpsec, 0, sizeof(tmpsec));
+
+ } else if ((value = dvbcfg_iskey(line, "name")) != NULL) {
+ strncpy(tmpsec.id, value, sizeof(tmpsec.id));
+ } else if ((value = dvbcfg_iskey(line, "switch-frequency")) != NULL) {
+ tmpsec.switch_frequency = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-v")) != NULL) {
+ tmpsec.lof_lo_v = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-h")) != NULL) {
+ tmpsec.lof_lo_h = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-l")) != NULL) {
+ tmpsec.lof_lo_l = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-r")) != NULL) {
+ tmpsec.lof_lo_r = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-v")) != NULL) {
+ tmpsec.lof_hi_v = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-h")) != NULL) {
+ tmpsec.lof_hi_h = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-l")) != NULL) {
+ tmpsec.lof_hi_l = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-r")) != NULL) {
+ tmpsec.lof_hi_r = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "config-type")) != NULL) {
+ if (!strcasecmp(value, "none")) {
+ tmpsec.config_type = DVBSEC_CONFIG_NONE;
+ } else if (!strcasecmp(value, "power")) {
+ tmpsec.config_type = DVBSEC_CONFIG_POWER;
+ } else if (!strcasecmp(value, "standard")) {
+ tmpsec.config_type = DVBSEC_CONFIG_STANDARD;
+ } else if (!strcasecmp(value, "advanced")) {
+ tmpsec.config_type = DVBSEC_CONFIG_ADVANCED;
+ } else {
+ insection = 0;
+ }
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-v")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_v, value, sizeof(tmpsec.adv_cmd_lo_v));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-h")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_h, value, sizeof(tmpsec.adv_cmd_lo_h));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-r")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_r, value, sizeof(tmpsec.adv_cmd_lo_r));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-l")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_l, value, sizeof(tmpsec.adv_cmd_lo_l));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-v")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_v, value, sizeof(tmpsec.adv_cmd_hi_v));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-h")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_h, value, sizeof(tmpsec.adv_cmd_hi_h));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-r")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_r, value, sizeof(tmpsec.adv_cmd_hi_r));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-l")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_l, value, sizeof(tmpsec.adv_cmd_hi_l));
+ } else {
+ insection = 0;
+ }
+ }
+
+ // output the final section if there is one
+ if (insection) {
+ if (cb(arg, &tmpsec))
+ return 0;
+ }
+
+ if (linebuf)
+ free(linebuf);
+ return 0;
+}
+
+static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec);
+static int dvbsec_cfg_find_default(const char *sec_id, struct dvbsec_config *sec);
+
+struct findparams {
+ const char *sec_id;
+ struct dvbsec_config *sec_dest;
+};
+
+int dvbsec_cfg_find(const char *config_file,
+ const char *sec_id,
+ struct dvbsec_config *sec)
+{
+ struct findparams findp;
+
+ // clear the structure
+ memset(sec, 0, sizeof(struct dvbsec_config));
+
+ // open the file
+ if (config_file != NULL) {
+ FILE *f = fopen(config_file, "r");
+ if (f == NULL)
+ return -EIO;
+
+ // parse each entry
+ findp.sec_id = sec_id;
+ findp.sec_dest = sec;
+ dvbsec_cfg_load(f, &findp, dvbsec_cfg_find_callback);
+
+ // done
+ fclose(f);
+
+ // find it?
+ if (sec->id[0])
+ return 0;
+ }
+
+ return dvbsec_cfg_find_default(sec_id, sec);
+}
+
+static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec)
+{
+ struct findparams *findp = arg;
+
+ if (strcmp(findp->sec_id, sec->id))
+ return 0;
+
+ memcpy(findp->sec_dest, sec, sizeof(struct dvbsec_config));
+ return 1;
+}
+
+int dvbsec_cfg_save(FILE *f,
+ struct dvbsec_config *secs,
+ int count)
+{
+ int i;
+
+ for(i=0; i<count; i++) {
+ char *config_type = "";
+ switch(secs[i].config_type) {
+ case DVBSEC_CONFIG_NONE:
+ config_type = "none";
+ break;
+ case DVBSEC_CONFIG_POWER:
+ config_type = "power";
+ break;
+ case DVBSEC_CONFIG_STANDARD:
+ config_type = "standard";
+ break;
+ case DVBSEC_CONFIG_ADVANCED:
+ config_type = "advanced";
+ break;
+ }
+
+ fprintf(f, "[lnb]\n");
+ fprintf(f, "switch-frequency=%i\n", secs[i].switch_frequency);
+ if (secs[i].lof_lo_v)
+ fprintf(f, "lof-lo-v=%i\n", secs[i].lof_lo_v);
+ if (secs[i].lof_lo_h)
+ fprintf(f, "lof-lo-h=%i\n", secs[i].lof_lo_h);
+ if (secs[i].lof_lo_l)
+ fprintf(f, "lof-lo-l=%i\n", secs[i].lof_lo_l);
+ if (secs[i].lof_lo_r)
+ fprintf(f, "lof-lo-r=%i\n", secs[i].lof_lo_r);
+ if (secs[i].lof_hi_v)
+ fprintf(f, "lof-hi-v=%i\n", secs[i].lof_hi_v);
+ if (secs[i].lof_hi_h)
+ fprintf(f, "lof-hi-h=%i\n", secs[i].lof_hi_h);
+ if (secs[i].lof_hi_l)
+ fprintf(f, "lof-hi-l=%i\n", secs[i].lof_hi_l);
+ if (secs[i].lof_hi_r)
+ fprintf(f, "lof-hi-r=%i\n", secs[i].lof_hi_r);
+ fprintf(f, "config-type=%s\n", config_type);
+
+ if (secs[i].config_type == DVBSEC_CONFIG_ADVANCED) {
+ if (secs[i].adv_cmd_lo_h[0])
+ fprintf(f, "cmd-lo-h=%s\n", secs[i].adv_cmd_lo_h);
+ if (secs[i].adv_cmd_lo_v[0])
+ fprintf(f, "cmd-lo-v=%s\n", secs[i].adv_cmd_lo_v);
+ if (secs[i].adv_cmd_lo_r[0])
+ fprintf(f, "cmd-lo-r=%s\n", secs[i].adv_cmd_lo_r);
+ if (secs[i].adv_cmd_lo_l[0])
+ fprintf(f, "cmd-lo-l=%s\n", secs[i].adv_cmd_lo_l);
+ if (secs[i].adv_cmd_hi_h[0])
+ fprintf(f, "cmd-hi-h=%s\n", secs[i].adv_cmd_hi_h);
+ if (secs[i].adv_cmd_hi_v[0])
+ fprintf(f, "cmd-hi-v=%s\n", secs[i].adv_cmd_hi_v);
+ if (secs[i].adv_cmd_hi_r[0])
+ fprintf(f, "cmd-hi-r=%s\n", secs[i].adv_cmd_hi_r);
+ if (secs[i].adv_cmd_hi_l[0])
+ fprintf(f, "cmd-hi-l=%s\n", secs[i].adv_cmd_hi_l);
+ }
+
+ fprintf(f, "\n");
+ }
+
+ return 0;
+}
+
+static struct dvbsec_config defaults[] = {
+
+ {
+ .id = "NULL",
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "UNIVERSAL",
+ .switch_frequency = 11700000,
+ .lof_lo_v = 9750000,
+ .lof_lo_h = 9750000,
+ .lof_hi_v = 10600000,
+ .lof_hi_h = 10600000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "DBS",
+ .switch_frequency = 0,
+ .lof_lo_v = 11250000,
+ .lof_lo_h = 11250000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "STANDARD",
+ .switch_frequency = 0,
+ .lof_lo_v = 10000000,
+ .lof_lo_h = 10000000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "ENHANCED",
+ .switch_frequency = 0,
+ .lof_lo_v = 9750000,
+ .lof_lo_h = 9750000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "C-BAND",
+ .switch_frequency = 0,
+ .lof_lo_v = 5150000,
+ .lof_lo_h = 5150000,
+ .config_type = DVBSEC_CONFIG_POWER,
+ },
+ {
+ .id = "C-MULTI",
+ .switch_frequency = 0,
+ .lof_lo_v = 5150000,
+ .lof_lo_h = 5750000,
+ .config_type = DVBSEC_CONFIG_POWER,
+ },
+};
+#define defaults_count (sizeof(defaults) / sizeof(struct dvbsec_config))
+
+static int dvbsec_cfg_find_default(const char *sec_id,
+ struct dvbsec_config *sec)
+{
+ unsigned int i;
+
+ for(i=0; i< defaults_count; i++) {
+ if (!strncmp(sec_id, defaults[i].id, sizeof(defaults[i].id))) {
+ memcpy(sec, &defaults[i], sizeof(struct dvbsec_config));
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/lib/libdvbsec/dvbsec_cfg.h b/lib/libdvbsec/dvbsec_cfg.h
new file mode 100644
index 0000000..d4546de
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_cfg.h
@@ -0,0 +1,203 @@
+/**
+ * dvbsec_cfg (i.e. linuxtv SEC format) configuration file support.
+ *
+ * Copyright (c) 2006 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * This library allows SEC (Satellite Equipment Control) configurations
+ * to be retrieved. Each configuration is identified by a unique satellite_id.
+ *
+ * In order to make things as easy as possible for users, there are a set of
+ * defaults hardcoded into the library covering the majority of LNB types. When
+ * these are used, the standard back-compatable sequence defined in the DISEQC
+ * standard will be used - this will suffice for _most_ situations.
+ *
+ * UNIVERSAL - Europe, 10800 to 11800 MHz and 11600 to 12700 Mhz, Dual LO, loband 9750, hiband 10600 MHz.
+ * DBS - Expressvu, North America, 12200 to 12700 MHz, Single LO, 11250 MHz.
+ * STANDARD - 10945 to 11450 Mhz, Single LO, 10000Mhz.
+ * ENHANCED - Astra, 10700 to 11700 MHz, Single LO, 9750MHz.
+ * C-BAND - Big Dish, 3700 to 4200 MHz, Single LO, 5150Mhz.
+ * C-MULTI - Big Dish - Multipoint LNBf, 3700 to 4200 MHz, Dual LO, H:5150MHz, V:5750MHz.
+ *
+ * However, for the power user with a more complex setup, these simple defaults
+ * are not enough. Therefore, it is also possible to define additional SEC
+ * configurations in an external configuration file. This file consists of multiple
+ * entries in the following format:
+ *
+ * [sec]
+ * name=<sec_id>
+ * switch-frequency=<switching frequency (SLOF)>
+ * lof-lo-v=<low band + V + frequency>
+ * lof-lo-h=<low band + H + frequency>
+ * lof-lo-l=<low band + L + frequency>
+ * lof-lo-r=<low band + R + frequency>
+ * lof-hi-v=<high band + V + frequency>
+ * lof-hi-h=<high band + H + frequency>
+ * lof-hi-l=<high band + L + frequency>
+ * lof-hi-r=<high band + R + frequency>
+ * config-type=<none|power|standard|advanced>
+ * cmd-lo-v=<sec sequence>
+ * cmd-lo-h=<sec sequence>
+ * cmd-lo-r=<sec sequence>
+ * cmd-lo-l=<sec sequence>
+ * cmd-hi-v=<sec sequence>
+ * cmd-hi-h=<sec sequence>
+ * cmd-hi-r=<sec sequence>
+ * cmd-hi-l=<sec sequence>
+ *
+ * The sec_id is whatever unique value you wish. If it is the same as one of the hardcoded defaults, the configuration
+ * details from the file will be used instead of the hardcoded ones.
+ * The switch-frequency (or SLOF) indicates the point seperating low band frequencies from high band frequencies.
+ * Set this value to 0 if there is only one frequency band.
+ * The lof-lo-v is the frequency adjustment for V + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-h is the frequency adjustment for H + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-l is the frequency adjustment for L + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-r is the frequency adjustment for R + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-hi-v is the frequency adjustment for V + high band (unused if switch-frequency==0).
+ * The lof-hi-h is the frequency adjustment for H + high band (unused if switch-frequency==0).
+ * The lof-hi-l is the frequency adjustment for L + high band (unused if switch-frequency==0).
+ * The lof-hi-r is the frequency adjustment for R + high band (unused if switch-frequency==0).
+ *
+ * config-type indicates the desired type of SEC command to use, it may be:
+ * none - No SEC commands will be issued (frequency adjustment will still be performed).
+ * power - Only the SEC power is turned on.
+ * standard - The standard DISEQC back compatable sequence will be issued.
+ * advanced - The DISEQC sequence described in the appropriate sec cmd string will be used.
+ *
+ * The cmd-<lo|hi>-<v|h|l|r> describes the SEC cmd string to use in advanced mode for each of the possible combinations of
+ * frequency band and polarisation. If a certain combination is not required, it may be omitted. It consists of a
+ * space seperated combination of commands - those available are as follows:
+ *
+ * tone(<0|1>) - control the 22kHz tone 0:off, 1:on
+ * voltage(<0|13|18>) - control the LNB voltage 0v, 13v, or 18v
+ * toneburst(<a|b>) - issue a toneburst (mini command) for position A or B.
+ * highvoltage(<0|1>) - control high lnb voltage for long cable runs 0: normal, 1:add 1v to LNB voltage.
+ * dishnetworks(<integer>) - issue a dishnetworks legacy command.
+ * wait(<integer>) - wait for the given number of milliseconds.
+ * Dreset(<address>, <0|1>) - control the reset state of a DISEC device, 0:disable reset, 1:enable reset.
+ * Dpower(<address>, <0|1>) - control the power of a DISEC device, 0:off, 1:on.
+ * Dcommitted(<address>, <h|l|x>, <v|h|l|r|x>, <a|b|x>, <a|b|x>) - Write to the committed switches of a DISEC device.
+ * The parameters are for band, polarisation, satelliteposition, switchoption:
+ * band - h:high band, l:low band
+ * polarisation - v: vertical, h:horizontal,r:right,l:left
+ * satelliteposition - a:position A, b: position B
+ * switchoption - a:position A, b: position B
+ * The special value 'x' means "no change to this switch".
+ *
+ * Duncommitted(<address>, <a|b|x>, <a|b|x>, <a|b|x>, <a|b|x>) - Write to the uncommitted switches of the a DISEC device.
+ * The parameters are for switch1, switch2, switch3, switch4, and may be set to position a or b.
+ * The special value 'x' means "no change to this switch".
+ *
+ * Dfrequency(<address>, <frequency in GHz>) - set the frequency of a DISEC device.
+ * Dchannel(<address>, <channel id>) - set the desired channel id of a DISEC device.
+ * Dgotopreset(<address>, <preset id>) - tell a DISEC satellite positioner to move to the given preset id.
+ * Dgotobearing(<address>, <bearing in degrees>) - tell a DISEQC terrestrial rotator to go to the
+ * given bearing (range -256.0 -> 512.0 degrees, fractions allowed).
+ *
+ * In the above DISEQC commands, <address> is the integer (normally in hex format) address of the
+ * diseqc device to communicate with. A list of possiblities is as follows:
+ *
+ * DISEQC_ADDRESS_ANY_DEVICE = 0x00
+ *
+ * DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV = 0x10
+ * DISEQC_ADDRESS_LNB = 0x11
+ * DISEQC_ADDRESS_LNB_WITH_LOOP = 0x12
+ * DISEQC_ADDRESS_SWITCHER = 0x14
+ * DISEQC_ADDRESS_SWITCHER_WITH_LOOP = 0x15
+ * DISEQC_ADDRESS_SMATV = 0x18
+ *
+ * DISEQC_ADDRESS_ANY_POLARISER = 0x20
+ * DISEQC_ADDRESS_LINEAR_POLARISER = 0x21
+ *
+ * DISEQC_ADDRESS_ANY_POSITIONER = 0x30
+ * DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER = 0x31
+ * DISEQC_ADDRESS_ELEVATION_POSITIONER = 0x32
+ *
+ * DISEQC_ADDRESS_ANY_INSTALLER_AID = 0x40
+ * DISEQC_ADDRESS_SIGNAL_STRENGTH = 0x41
+ *
+ * DISEQC_ADDRESS_ANY_INTERFACE = 0x70
+ * DISEQC_ADDRESS_HEADEND_INTERFACE = 0x71
+ *
+ * DISEQC_ADDRESS_REALLOC_BASE = 0x60
+ * DISEQC_ADDRESS_OEM_BASE = 0xf0
+ */
+
+#ifndef DVBSEC_CFG_H
+#define DVBSEC_CFG_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <libdvbsec/dvbsec_api.h>
+
+/**
+ * Callback function used in dvbsec_cfg_load().
+ *
+ * @param arg Private information to caller.
+ * @param channel The current channel details.
+ * @return 0 to continue, 1 to stop loading.
+ */
+typedef int (*dvbsec_cfg_callback)(void *arg, struct dvbsec_config *sec);
+
+/**
+ * Load an SEC file.
+ *
+ * @param f File to load from.
+ * @param arg Value to pass to 'arg' in callback above.
+ * @param cb Callback function called for each sec loaded from the file.
+ * @return 0 on success, or nonzero error code on failure.
+ */
+extern int dvbsec_cfg_load(FILE *f, void *arg,
+ dvbsec_cfg_callback cb);
+
+/**
+ * Convenience function to parse an SEC config file. This will also consult the set
+ * of hardcoded defaults if no config file was supplied, or a match was not found in
+ * the config file.
+ *
+ * @param config_file Config filename to load, or NULL to just check defaults.
+ * @param sec_id ID of SEC configuration.
+ * @param sec Where to put the details if found.
+ * @return 0 on success, nonzero on error.
+ */
+extern int dvbsec_cfg_find(const char *config_file,
+ const char *sec_id,
+ struct dvbsec_config *sec);
+
+/**
+ * Save SEC format config file.
+ *
+ * @param f File to save to.
+ * @param secs Pointer to array of SECs to save.
+ * @param count Number of entries in the above array.
+ * @return 0 on success, or nonzero error code on failure.
+ */
+extern int dvbsec_cfg_save(FILE *f,
+ struct dvbsec_config *secs,
+ int count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif