/* test_sec_ne.c - Test for Not-Equal section filters.
* usage: DEMUX=/dev/dvb/adapterX/demuxX test_sec_ne pid [tid [tid_ext]]
*
* Copyright (C) 2002 convergence GmbH
* Johannes Stezenbach <js@convergence.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/dvb/dmx.h>
#include "hex_dump.h"
#define MAX_SECTION_SIZE 8192
static unsigned int version_number;
void usage(void)
{
fprintf(stderr, "usage: test_sec_ne pid [tid [tid_ext]]\n");
fprintf(stderr, " Read the version_number from the first section\n");
fprintf(stderr, " and sec a filter to wait for it to change.\n");
fprintf(stderr, " The default demux device used can be changed\n");
fprintf(stderr, " using the DEMUX environment variable;\n");
exit(1);
}
void process_section(int fd)
{
uint8_t buf[MAX_SECTION_SIZE];
int bytes;
bytes = read(fd, buf, sizeof(buf));
if (bytes < 0) {
perror("read");
if (bytes != ETIMEDOUT)
exit(1);
}
hex_dump(buf, bytes);
version_number = ((buf[5] >> 1) & 0x1f);
printf("current version_number: %u\n\n", version_number);
}
int set_filter(int fd, unsigned int pid, unsigned int tid,
unsigned int tid_ext, unsigned int _version_number)
{
struct dmx_sct_filter_params f;
unsigned long bufsz;
if (getenv("BUFFER")) {
bufsz=strtoul(getenv("BUFFER"), NULL, 0);
if (bufsz > 0 && bufsz <= MAX_SECTION_SIZE) {
fprintf(stderr, "DMX_SET_BUFFER_SIZE %lu\n", bufsz);
if (ioctl(fd, DMX_SET_BUFFER_SIZE, bufsz) == -1)pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//*
* libdvbfe - a DVB frontend library
*
* Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
* Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
* Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <linux/dvb/frontend.h>
#include <libdvbmisc/dvbmisc.h>
#include "dvbfe.h"
int verbose = 0;
static int dvbfe_spectral_inversion_to_kapi[][2] =
{
{ DVBFE_INVERSION_OFF, INVERSION_OFF },
{ DVBFE_INVERSION_ON, INVERSION_ON },
{ DVBFE_INVERSION_AUTO, INVERSION_AUTO },
{ -1, -1 }
};
static int dvbfe_code_rate_to_kapi[][2] =
{
{ DVBFE_FEC_NONE, FEC_NONE },
{ DVBFE_FEC_1_2, FEC_1_2 },
{ DVBFE_FEC_2_3, FEC_2_3 },
{ DVBFE_FEC_3_4, FEC_3_4 },
{ DVBFE_FEC_4_5, FEC_4_5 },
{ DVBFE_FEC_5_6, FEC_5_6 },
{ DVBFE_FEC_6_7, FEC_6_7 },
{ DVBFE_FEC_7_8, FEC_7_8 },
{ DVBFE_FEC_8_9, FEC_8_9 },
{ DVBFE_FEC_AUTO, FEC_AUTO },
{ -1, -1 }
};
static int dvbfe_dvbt_const_to_kapi[][2] =
{
{ DVBFE_DVBT_CONST_QPSK, FE_QPSK },
{ DVBFE_DVBT_CONST_QAM_16, QAM_16 },
{ DVBFE_DVBT_CONST_QAM_32, QAM_32 },
{ DVBFE_DVBT_CONST_QAM_64, QAM_64 },
{ DVBFE_DVBT_CONST_QAM_128, QAM_128 },
{ DVBFE_DVBT_CONST_QAM_256, QAM_256 },
{ DVBFE_DVBT_CONST_AUTO, QAM_AUTO },
{ -1, -1 }
};
static int dvbfe_dvbc_mod_to_kapi[][2] =
{
{ DVBFE_DVBC_MOD_QAM_16, QAM_16 },
{ DVBFE_DVBC_MOD_QAM_32, QAM_32 },
{ DVBFE_DVBC_MOD_QAM_64, QAM_64 },
{ DVBFE_DVBC_MOD_QAM_128, QAM_128 },
{ DVBFE_DVBC_MOD_QAM_256, QAM_256 },
{ DVBFE_DVBC_MOD_AUTO, QAM_AUTO },
{ -1, -1 }
};
static int dvbfe_atsc_mod_to_kapi[][2] =
{
{ DVBFE_ATSC_MOD_QAM_64, QAM_64 },
{ DVBFE_ATSC_MOD_QAM_256, QAM_256 },
{ DVBFE_ATSC_MOD_VSB_8, VSB_8 },
{ DVBFE_ATSC_MOD_VSB_16, VSB_16 },
{ DVBFE_ATSC_MOD_AUTO, QAM_AUTO },
{ -1, -1 }
};
static int dvbfe_dvbt_transmit_mode_to_kapi[][2] =
{
{ DVBFE_DVBT_TRANSMISSION_MODE_2K, TRANSMISSION_MODE_2K },
{ DVBFE_DVBT_TRANSMISSION_MODE_8K, TRANSMISSION_MODE_8K },
{ DVBFE_DVBT_TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO },
{ -1, -1 }
};
static int dvbfe_dvbt_bandwidth_to_kapi[][2] =
{
{ DVBFE_DVBT_BANDWIDTH_8_MHZ, BANDWIDTH_8_MHZ },
{ DVBFE_DVBT_BANDWIDTH_7_MHZ, BANDWIDTH_7_MHZ },
{ DVBFE_DVBT_BANDWIDTH_6_MHZ, BANDWIDTH_6_MHZ },
{ DVBFE_DVBT_BANDWIDTH_AUTO, BANDWIDTH_AUTO },
{ -1, -1 }
};
static int dvbfe_dvbt_guard_interval_to_kapi[][2] =
{
{ DVBFE_DVBT_GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_32},
{ DVBFE_DVBT_GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_16},
{ DVBFE_DVBT_GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_8},
{ DVBFE_DVBT_GUARD_INTERVAL_1_4, GUARD_INTERVAL_1_4},
{ DVBFE_DVBT_GUARD_INTERVAL_AUTO, GUARD_INTERVAL_AUTO},
{ -1, -1 }
};
static int dvbfe_dvbt_hierarchy_to_kapi[][2] =
{
{ DVBFE_DVBT_HIERARCHY_NONE, HIERARCHY_NONE },
{ DVBFE_DVBT_HIERARCHY_1, HIERARCHY_1 },
{ DVBFE_DVBT_HIERARCHY_2, HIERARCHY_2 },
{ DVBFE_DVBT_HIERARCHY_4, HIERARCHY_4 },
{ DVBFE_DVBT_HIERARCHY_AUTO, HIERARCHY_AUTO },
{ -1, -1 }
};
static int lookupval(int val, int reverse, int table[][2])
{
int i =0;
while(table[i][0] != -1) {
if (!reverse) {
if (val == table[i][0]) {
return table[i][1];
}
} else {
if (val == table[i][1]) {
return table[i][0];
}
}
i++;
}
return -1;
}
struct dvbfe_handle {
int fd;
enum dvbfe_type type;
char *name;
};
struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly)
{
char filename[PATH_MAX+1];
struct dvbfe_handle *fehandle;
int fd;
struct dvb_frontend_info info;
// flags
int flags = O_RDWR;
if (readonly) {
flags = O_RDONLY;
}
// open it (try normal /dev structure first)
sprintf(filename, "/dev/dvb/adapter%i/frontend%i", adapter, frontend);
if ((fd = open(filename, flags)) < 0) {
// if that failed, try a flat /dev structure
sprintf(filename, "/dev/dvb%i.frontend%i", adapter, frontend);
if ((fd = open(filename, flags)) < 0) {
return NULL;
}
}
// determine fe type
if (ioctl(fd, FE_GET_INFO, &info)) {
close(fd);
return NULL;
}
// setup structure
fehandle = (struct dvbfe_handle*) malloc(sizeof(struct dvbfe_handle));
memset(fehandle, 0, sizeof(struct dvbfe_handle));
fehandle->fd = fd;
switch(info.type) {
case FE_QPSK:
fehandle->type = DVBFE_TYPE_DVBS;
break;
case FE_QAM:
fehandle->type = DVBFE_TYPE_DVBC;
break;
case FE_OFDM:
fehandle->type = DVBFE_TYPE_DVBT;
break;
case FE_ATSC:
fehandle->type = DVBFE_TYPE_ATSC;
break;
}
fehandle->name = strndup(info.name, sizeof(info.name));
// done
return fehandle;
}
void dvbfe_close(struct dvbfe_handle *fehandle)
{
close(fehandle->fd);
free(fehandle->name);
free(fehandle);
}
extern int dvbfe_get_info(struct dvbfe_handle *fehandle,
enum dvbfe_info_mask querymask,
struct dvbfe_info *result,
enum dvbfe_info_querytype querytype,
int timeout)
{
int returnval = 0;
struct dvb_frontend_event kevent;
int ok = 0;
result->name = fehandle->name;
result->type = fehandle->type;
switch(querytype) {
case DVBFE_INFO_QUERYTYPE_IMMEDIATE:
if (querymask & DVBFE_INFO_LOCKSTATUS) {
if (!ioctl(fehandle->fd, FE_READ_STATUS, &kevent.status)) {
returnval |= DVBFE_INFO_LOCKSTATUS;
}
}
if (querymask & DVBFE_INFO_FEPARAMS) {
if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kevent.parameters)) {
returnval |= DVBFE_INFO_FEPARAMS;
}
}
break;
case DVBFE_INFO_QUERYTYPE_LOCKCHANGE:
{
struct pollfd pollfd;
pollfd.fd = fehandle->fd;
pollfd.events = POLLIN | POLLERR;
ok = 1;
if (poll(&pollfd, 1, timeout) < 0)
ok = 0;
if (pollfd.revents & POLLERR)
ok = 0;
if (!(pollfd.revents & POLLIN))
ok = 0;
}
if (ok &&
((querymask & DVBFE_INFO_LOCKSTATUS) ||
(querymask & DVBFE_INFO_FEPARAMS))) {
if (!ioctl(fehandle->fd, FE_GET_EVENT, &kevent)) {
if (querymask & DVBFE_INFO_LOCKSTATUS)
returnval |= DVBFE_INFO_LOCKSTATUS;
if (querymask & DVBFE_INFO_FEPARAMS)
returnval |= DVBFE_INFO_FEPARAMS;
}
}
break;
}
if (returnval & DVBFE_INFO_LOCKSTATUS) {
result->signal = kevent.status & FE_HAS_SIGNAL ? 1 : 0;
result->carrier = kevent.status & FE_HAS_CARRIER ? 1 : 0;
result->viterbi = kevent.status & FE_HAS_VITERBI ? 1 : 0;
result->sync = kevent.status & FE_HAS_SYNC ? 1 : 0;
result->lock = kevent.status & FE_HAS_LOCK ? 1 : 0;
}
if (returnval & DVBFE_INFO_FEPARAMS) {
result->feparams.frequency = kevent.parameters.frequency;
result->feparams.inversion = lookupval(kevent.parameters.inversion, 1, dvbfe_spectral_inversion_to_kapi);
switch(fehandle->type) {
case FE_QPSK:
result->feparams.u.dvbs.symbol_rate = kevent.parameters.u.qpsk.symbol_rate;
result->feparams.u.dvbs.fec_inner =
lookupval(kevent.parameters.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi);
break;
case FE_QAM:
result->feparams.u.dvbc.symbol_rate = kevent.parameters.u.qam.symbol_rate;
result->feparams.u.dvbc.fec_inner =
lookupval(kevent.parameters.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi);
result->feparams.u.dvbc.modulation =
lookupval(kevent.parameters.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi);
break;
case FE_OFDM:
result->feparams.u.dvbt.bandwidth =
lookupval(kevent.parameters.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi);
result->feparams.u.dvbt.code_rate_HP =
lookupval(kevent.parameters.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi);
result->feparams.u.dvbt.code_rate_LP =
lookupval(kevent.parameters.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi);
result->feparams.u.dvbt.constellation =
lookupval(kevent.parameters.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi);
result->feparams.u.dvbt.transmission_mode =
lookupval(kevent.parameters.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi);
result->feparams.u.dvbt.guard_interval =
lookupval(kevent.parameters.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi);
result->feparams.u.dvbt.hierarchy_information =
lookupval(kevent.parameters.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi);
break;
case FE_ATSC:
result->feparams.u.atsc.modulation =
lookupval(kevent.parameters.u.vsb.modulation, 1, dvbfe_atsc_mod_to_kapi);
break;
}
}
if (querymask & DVBFE_INFO_BER) {
if (!ioctl(fehandle->fd, FE_READ_BER, &result->ber))
returnval |= DVBFE_INFO_BER;
}
if (querymask & DVBFE_INFO_SIGNAL_STRENGTH) {
if (!ioctl(fehandle->fd, FE_READ_SIGNAL_STRENGTH, &result->signal_strength))
returnval |= DVBFE_INFO_SIGNAL_STRENGTH;
}
if (querymask & DVBFE_INFO_SNR) {
if (!ioctl(fehandle->fd, FE_READ_SNR, &result->snr))
returnval |= DVBFE_INFO_SNR;
}
if (querymask & DVBFE_INFO_UNCORRECTED_BLOCKS) {
if (!ioctl(fehandle->fd, FE_READ_UNCORRECTED_BLOCKS, &result->ucblocks))
returnval |= DVBFE_INFO_UNCORRECTED_BLOCKS;
}
// done
return returnval;
}
int dvbfe_set(struct dvbfe_handle *fehandle,
struct dvbfe_parameters *params,
int timeout)
{
struct dvb_frontend_parameters kparams;
int res;
struct timeval endtime;
fe_status_t status;
kparams.frequency = params->frequency;
kparams.inversion = lookupval(params->inversion, 0, dvbfe_spectral_inversion_to_kapi);
switch(fehandle->type) {
case FE_QPSK:
kparams.u.qpsk.symbol_rate = params->u.dvbs.symbol_rate;
kparams.u.qpsk.fec_inner = lookupval(params->u.dvbs.fec_inner, 0, dvbfe_code_rate_to_kapi);
break;
case FE_QAM:
kparams.u.qam.symbol_rate = params->u.dvbc.symbol_rate;
kparams.u.qam.fec_inner = lookupval(params->u.dvbc.fec_inner, 0, dvbfe_code_rate_to_kapi);
kparams.u.qam.modulation = lookupval(params->u.dvbc.modulation, 0, dvbfe_dvbc_mod_to_kapi);
break;
case FE_OFDM:
kparams.u.ofdm.bandwidth = lookupval(params->u.dvbt.bandwidth, 0, dvbfe_dvbt_bandwidth_to_kapi);
kparams.u.ofdm.code_rate_HP = lookupval(params->u.dvbt.code_rate_HP, 0, dvbfe_code_rate_to_kapi);
kparams.u.ofdm.code_rate_LP = lookupval(params->u.dvbt.code_rate_LP, 0, dvbfe_code_rate_to_kapi);
kparams.u.ofdm.constellation = lookupval(params->u.dvbt.constellation, 0, dvbfe_dvbt_const_to_kapi);
kparams.u.ofdm.transmission_mode =
lookupval(params->u.dvbt.transmission_mode, 0, dvbfe_dvbt_transmit_mode_to_kapi);
kparams.u.ofdm.guard_interval =
lookupval(params->u.dvbt.guard_interval, 0, dvbfe_dvbt_guard_interval_to_kapi);
kparams.u.ofdm.hierarchy_information =
lookupval(params->u.dvbt.hierarchy_information, 0, dvbfe_dvbt_hierarchy_to_kapi);
break;
case FE_ATSC:
kparams.u.vsb.modulation = lookupval(params->u.atsc.modulation, 0, dvbfe_atsc_mod_to_kapi);
break;
default:
return -EINVAL;
}
// set it and check for error
res = ioctl(fehandle->fd, FE_SET_FRONTEND, &kparams);
if (res)
return res;
// 0 => return immediately
if (timeout == 0) {
return 0;
}
/* calculate timeout */
if (timeout > 0) {
gettimeofday(&endtime, NULL);
timeout *= 1000;
endtime.tv_sec += timeout / 1000000;
endtime.tv_usec += timeout % 1000000;
}
/* wait for a lock */
while(1) {
/* has it locked? */
if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) {
if (status & FE_HAS_LOCK) {
break;
}
}
/* check for timeout */
if (timeout > 0) {
struct timeval curtime;
gettimeofday(&curtime, NULL);
if ((curtime.tv_sec > endtime.tv_sec) ||
((curtime.tv_sec == endtime.tv_sec) && (curtime.tv_usec >= endtime.tv_usec))) {
break;
}
}
/* delay for a bit */
usleep(100000);
}
/* exit */
if (status & FE_HAS_LOCK)
return 0;
return -ETIMEDOUT;
}
int dvbfe_get_pollfd(struct dvbfe_handle *handle)
{
return handle->fd;
}
int dvbfe_set_22k_tone(struct dvbfe_handle *fehandle, enum dvbfe_sec_tone_mode tone)
{
int ret = 0;
switch (tone) {
case DVBFE_SEC_TONE_OFF:
ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF);
break;
case DVBFE_SEC_TONE_ON:
ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON);
break;
default:
print(verbose, ERROR, 1, "Invalid command !");
break;
}
if (ret == -1)
print(verbose, ERROR, 1, "IOCTL failed !");
return ret;
}
int dvbfe_set_tone_data_burst(struct dvbfe_handle *fehandle, enum dvbfe_sec_mini_cmd minicmd)
{
int ret = 0;
switch (minicmd) {
case DVBFE_SEC_MINI_A:
ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A);
break;
case DVBFE_SEC_MINI_B:
ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B);
break;
default:
print(verbose, ERROR, 1, "Invalid command");
break;
}
if (ret == -1)
print(verbose, ERROR, 1, "IOCTL failed");
return ret;
}
int dvbfe_set_voltage(struct dvbfe_handle *fehandle, enum dvbfe_sec_voltage voltage)
{
int ret = 0;
switch (voltage) {
case DVBFE_SEC_VOLTAGE_OFF:
ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF);
break;
case DVBFE_SEC_VOLTAGE_13:
ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13);
break;
case DVBFE_SEC_VOLTAGE_18:
ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18);
break;
default:
print(verbose, ERROR, 1, "Invalid command");
break;
}
if (ret == -1)
print(verbose, ERROR, 1, "IOCTL failed");
return ret;
}
int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on)
{
switch (on) {
case 0:
ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0);
break;
default:
ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1);
break;
}
return 0;
}
int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *fehandle, unsigned int cmd)
{
int ret = 0;
ret = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd);
if (ret == -1)
print(verbose, ERROR, 1, "IOCTL failed");
return ret;
}
int dvbfe_do_diseqc_command(struct dvbfe_handle *fehandle, uint8_t *data, uint8_t len)
{
int ret = 0;
struct dvb_diseqc_master_cmd diseqc_message;
if (len > 6)
return -EINVAL;
diseqc_message.msg_len = len;
memcpy(diseqc_message.msg, data, len);
ret = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &diseqc_message);
if (ret == -1)
print(verbose, ERROR, 1, "IOCTL failed");
return ret;
}
int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len)
{
struct dvb_diseqc_slave_reply reply;
int result;
if (len > 4)
len = 4;
reply.timeout = timeout;
reply.msg_len = len;
if ((result = ioctl(fehandle->fd, FE_DISEQC_RECV_SLAVE_REPLY, reply)) != 0)
return result;
if (reply.msg_len < len)
len = reply.msg_len;
memcpy(buf, reply.msg, len);
return len;
}