aboutsummaryrefslogtreecommitdiffstats
path: root/util/szap/szap.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/szap/szap.c')
-rw-r--r--util/szap/szap.c222
1 files changed, 189 insertions, 33 deletions
diff --git a/util/szap/szap.c b/util/szap/szap.c
index 581c970..ed1aa51 100644
--- a/util/szap/szap.c
+++ b/util/szap/szap.c
@@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
+#include <sys/param.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
@@ -45,6 +46,7 @@
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
+#include <linux/dvb/audio.h>
#include "lnb.h"
#ifndef TRUE
@@ -64,6 +66,7 @@
#define FRONTENDDEVICE "/dev/dvb/adapter%d/frontend%d"
#define DEMUXDEVICE "/dev/dvb/adapter%d/demux%d"
+#define AUDIODEVICE "/dev/dvb/adapter%d/audio%d"
static struct lnb_types_st lnb_type;
@@ -79,18 +82,21 @@ static char *usage_str =
" -f number : use given frontend (default 0)\n"
" -d number : use given demux (default 0)\n"
" -c file : read channels list from 'file'\n"
+ " -b : enable Audio Bypass (default no)\n"
" -x : exit after tuning\n"
+ " -H : human readable output\n"
" -r : set up /dev/dvb/adapterX/dvr0 for TS recording\n"
" -l lnb-type (DVB-S Only) (use -l help to print types) or \n"
" -l low[,high[,switch]] in Mhz\n"
" -i : run interactively, allowing you to type in channel names\n"
+ " -p : add pat and pmt to TS recording (implies -r)\n"
" or -n numbers for zapping\n";
-static int set_demux(int dmxfd, int pid, int audio, int dvr)
+static int set_demux(int dmxfd, int pid, int pes_type, int dvr)
{
struct dmx_pes_filter_params pesfilter;
- if (pid <= 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */
+ if (pid < 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */
return TRUE;
if (dvr) {
@@ -102,7 +108,7 @@ static int set_demux(int dmxfd, int pid, int audio, int dvr)
pesfilter.pid = pid;
pesfilter.input = DMX_IN_FRONTEND;
pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER;
- pesfilter.pes_type = audio ? DMX_PES_AUDIO : DMX_PES_VIDEO;
+ pesfilter.pes_type = pes_type;
pesfilter.flags = DMX_IMMEDIATE_START;
if (ioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) {
@@ -114,6 +120,65 @@ static int set_demux(int dmxfd, int pid, int audio, int dvr)
return TRUE;
}
+int get_pmt_pid(char *dmxdev, int sid)
+{
+ int patfd, count;
+ int pmt_pid = 0;
+ int patread = 0;
+ int section_length;
+ unsigned char buft[4096];
+ unsigned char *buf = buft;
+ struct dmx_sct_filter_params f;
+
+ memset(&f, 0, sizeof(f));
+ f.pid = 0;
+ f.filter.filter[0] = 0x00;
+ f.filter.mask[0] = 0xff;
+ f.timeout = 0;
+ f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
+
+ if ((patfd = open(dmxdev, O_RDWR)) < 0) {
+ perror("openening pat demux failed");
+ return -1;
+ }
+
+ if (ioctl(patfd, DMX_SET_FILTER, &f) == -1) {
+ perror("ioctl DMX_SET_FILTER failed");
+ close(patfd);
+ return -1;
+ }
+
+ while (!patread){
+ if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW)
+ count = read(patfd, buf, sizeof(buft));
+ if (count < 0) {
+ perror("read_sections: read error");
+ close(patfd);
+ return -1;
+ }
+
+ section_length = ((buf[1] & 0x0f) << 8) | buf[2];
+ if (count != section_length + 3)
+ continue;
+
+ buf += 8;
+ section_length -= 8;
+
+ patread = 1; /* assumes one section contains the whole pat */
+ while (section_length > 0) {
+ int service_id = (buf[0] << 8) | buf[1];
+ if (service_id == sid) {
+ pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];
+ section_length = 0;
+ }
+ buf += 4;
+ section_length -= 4;
+ }
+ }
+
+ close(patfd);
+ return pmt_pid;
+}
struct diseqc_cmd {
struct dvb_diseqc_master_cmd cmd;
@@ -151,14 +216,14 @@ static int diseqc(int secfd, int sat_no, int pol_vert, int hi_band)
{ {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
/* param: high nibble: reset bits, low nibble set bits,
- * bits are: option, position, polarizaion, band
+ * bits are: option, position, polarization, band
*/
cmd.cmd.msg[3] =
0xf0 | (((sat_no * 4) & 0x0f) | (hi_band ? 1 : 0) | (pol_vert ? 0 : 2));
diseqc_send_msg(secfd, pol_vert ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18,
&cmd, hi_band ? SEC_TONE_ON : SEC_TONE_OFF,
- (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A);
+ sat_no % 2 ? SEC_MINI_B : SEC_MINI_A);
return TRUE;
}
@@ -189,8 +254,9 @@ static int do_tune(int fefd, unsigned int ifreq, unsigned int sr)
static
-int check_frontend (int fe_fd, int dvr)
+int check_frontend (int fe_fd, int dvr, int human_readable)
{
+ (void)dvr;
fe_status_t status;
uint16_t snr, signal;
uint32_t ber, uncorrected_blocks;
@@ -210,8 +276,13 @@ int check_frontend (int fe_fd, int dvr)
if (ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) == -1)
uncorrected_blocks = -2;
- printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
- status, signal, snr, ber, uncorrected_blocks);
+ if (human_readable) {
+ printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ",
+ status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber, uncorrected_blocks);
+ } else {
+ printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
+ status, signal, snr, ber, uncorrected_blocks);
+ }
if (status & FE_HAS_LOCK)
printf("FE_HAS_LOCK");
@@ -230,10 +301,12 @@ int check_frontend (int fe_fd, int dvr)
static
int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux,
unsigned int sat_no, unsigned int freq, unsigned int pol,
- unsigned int sr, unsigned int vpid, unsigned int apid, int dvr)
+ unsigned int sr, unsigned int vpid, unsigned int apid, int sid,
+ int dvr, int rec_psi, int bypass, int human_readable)
{
- char fedev[128], dmxdev[128];
- static int fefd, videofd, audiofd;
+ char fedev[128], dmxdev[128], auddev[128];
+ static int fefd, dmxfda, dmxfdv, audiofd = -1, patfd, pmtfd;
+ int pmtpid;
uint32_t ifreq;
int hiband, result;
static struct dvb_frontend_info fe_info;
@@ -241,6 +314,7 @@ int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux,
if (!fefd) {
snprintf(fedev, sizeof(fedev), FRONTENDDEVICE, adapter, frontend);
snprintf(dmxdev, sizeof(dmxdev), DEMUXDEVICE, adapter, demux);
+ snprintf(auddev, sizeof(auddev), AUDIODEVICE, adapter, demux);
printf("using '%s' and '%s'\n", fedev, dmxdev);
if ((fefd = open(fedev, O_RDWR | O_NONBLOCK)) < 0) {
@@ -262,18 +336,41 @@ int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux,
return FALSE;
}
- if ((videofd = open(dmxdev, O_RDWR)) < 0) {
+ if ((dmxfdv = open(dmxdev, O_RDWR)) < 0) {
perror("opening video demux failed");
close(fefd);
return FALSE;
}
- if ((audiofd = open(dmxdev, O_RDWR)) < 0) {
+ if ((dmxfda = open(dmxdev, O_RDWR)) < 0) {
perror("opening audio demux failed");
- close(videofd);
close(fefd);
return FALSE;
}
+
+ if (dvr == 0) /* DMX_OUT_DECODER */
+ audiofd = open(auddev, O_RDWR);
+
+ if (rec_psi){
+ if ((patfd = open(dmxdev, O_RDWR)) < 0) {
+ perror("opening pat demux failed");
+ close(audiofd);
+ close(dmxfda);
+ close(dmxfdv);
+ close(fefd);
+ return FALSE;
+ }
+
+ if ((pmtfd = open(dmxdev, O_RDWR)) < 0) {
+ perror("opening pmt demux failed");
+ close(patfd);
+ close(audiofd);
+ close(dmxfda);
+ close(dmxfdv);
+ close(fefd);
+ return FALSE;
+ }
+ }
}
hiband = 0;
@@ -293,15 +390,36 @@ int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux,
if (diseqc(fefd, sat_no, pol, hiband))
if (do_tune(fefd, ifreq, sr))
- if (set_demux(videofd, vpid, 0, dvr))
- if (set_demux(audiofd, apid, 1, dvr))
- result = TRUE;
-
- check_frontend (fefd, dvr);
+ if (set_demux(dmxfdv, vpid, DMX_PES_VIDEO, dvr))
+ if (audiofd >= 0)
+ (void)ioctl(audiofd, AUDIO_SET_BYPASS_MODE, bypass);
+ if (set_demux(dmxfda, apid, DMX_PES_AUDIO, dvr)) {
+ if (rec_psi) {
+ pmtpid = get_pmt_pid(dmxdev, sid);
+ if (pmtpid < 0) {
+ result = FALSE;
+ }
+ if (pmtpid == 0) {
+ fprintf(stderr,"couldn't find pmt-pid for sid %04x\n",sid);
+ result = FALSE;
+ }
+ if (set_demux(patfd, 0, DMX_PES_OTHER, dvr))
+ if (set_demux(pmtfd, pmtpid, DMX_PES_OTHER, dvr))
+ result = TRUE;
+ } else {
+ result = TRUE;
+ }
+ }
+
+ check_frontend (fefd, dvr, human_readable);
if (!interactive) {
- close(audiofd);
- close(videofd);
+ close(patfd);
+ close(pmtfd);
+ if (audiofd >= 0)
+ close(audiofd);
+ close(dmxfda);
+ close(dmxfdv);
close(fefd);
}
@@ -312,14 +430,15 @@ int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux,
static int read_channels(const char *filename, int list_channels,
uint32_t chan_no, const char *chan_name,
unsigned int adapter, unsigned int frontend,
- unsigned int demux, int dvr)
+ unsigned int demux, int dvr, int rec_psi,
+ int bypass, int human_readable)
{
FILE *cfp;
char buf[4096];
char inp[256];
char *field, *tmp, *p;
unsigned int line;
- unsigned int freq, pol, sat_no, sr, vpid, apid;
+ unsigned int freq, pol, sat_no, sr, vpid, apid, sid;
int ret;
again:
@@ -399,20 +518,41 @@ again:
goto syntax_err;
vpid = strtoul(field, NULL, 0);
+ if (!vpid)
+ vpid = 0x1fff;
if (!(field = strsep(&tmp, ":")))
goto syntax_err;
+ p = strchr(field, ';');
+
+ if (p) {
+ *p = '\0';
+ p++;
+ if (bypass) {
+ if (!p || !*p)
+ goto syntax_err;
+ field = p;
+ }
+ }
+
apid = strtoul(field, NULL, 0);
+ if (!apid)
+ apid = 0x1fff;
+
+ if (!(field = strsep(&tmp, ":")))
+ goto syntax_err;
+
+ sid = strtoul(field, NULL, 0);
printf("sat %u, frequency = %u MHz %c, symbolrate %u, "
- "vpid = 0x%04x, apid = 0x%04x\n",
- sat_no, freq, pol ? 'V' : 'H', sr, vpid, apid);
+ "vpid = 0x%04x, apid = 0x%04x sid = 0x%04x\n",
+ sat_no, freq, pol ? 'V' : 'H', sr, vpid, apid, sid);
fclose(cfp);
- ret = zap_to(adapter, frontend, demux,
- sat_no, freq * 1000, pol, sr, vpid, apid, dvr);
+ ret = zap_to(adapter, frontend, demux, sat_no, freq * 1000,
+ pol, sr, vpid, apid, sid, dvr, rec_psi, bypass, human_readable);
if (interactive)
goto again;
@@ -475,17 +615,22 @@ int main(int argc, char *argv[])
int list_channels = 0;
unsigned int chan_no = 0;
const char *chan_name = NULL;
- unsigned int adapter = 0, frontend = 0, demux = 0, dvr = 0;
+ unsigned int adapter = 0, frontend = 0, demux = 0, dvr = 0, rec_psi = 0;
+ int bypass = 0;
int opt, copt = 0;
+ int human_readable = 0;
lnb_type = *lnb_enum(0);
- while ((opt = getopt(argc, argv, "hqrn:a:f:d:c:l:xi")) != -1) {
+ while ((opt = getopt(argc, argv, "Hhqrpn:a:f:d:c:l:xib")) != -1) {
switch (opt)
{
case '?':
case 'h':
default:
bad_usage(argv[0], 0);
+ case 'b':
+ bypass = 1;
+ break;
case 'q':
list_channels = 1;
break;
@@ -501,6 +646,9 @@ int main(int argc, char *argv[])
case 'f':
frontend = strtoul(optarg, NULL, 0);
break;
+ case 'p':
+ rec_psi = 1;
+ break;
case 'd':
demux = strtoul(optarg, NULL, 0);
break;
@@ -517,6 +665,9 @@ int main(int argc, char *argv[])
case 'x':
exit_after_tuning = 1;
break;
+ case 'H':
+ human_readable = 1;
+ break;
case 'i':
interactive = 1;
exit_after_tuning = 1;
@@ -545,16 +696,21 @@ int main(int argc, char *argv[])
fprintf(stderr, "error: $HOME not set\n");
return TRUE;
}
- strncpy(chanfile, home, sizeof(chanfile));
- strcat(chanfile, "/.szap/" CHANNEL_FILE);
+ snprintf(chanfile, sizeof(chanfile),
+ "%s/.szap/%i/%s", home, adapter, CHANNEL_FILE);
+ if (access(chanfile, R_OK))
+ snprintf(chanfile, sizeof(chanfile),
+ "%s/.szap/%s", home, CHANNEL_FILE);
}
printf("reading channels from file '%s'\n", chanfile);
+ if (rec_psi)
+ dvr=1;
+
if (!read_channels(chanfile, list_channels, chan_no, chan_name,
- adapter, frontend, demux, dvr))
+ adapter, frontend, demux, dvr, rec_psi, bypass, human_readable))
return TRUE;
return FALSE;
}
-