diff options
author | Mark Purcell <msp@debian.org> | 2008-06-22 11:00:40 +1000 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:42 +0200 |
commit | 891c51ff368ed700dec6025eeb47ce4d96f76418 (patch) | |
tree | 3729664829e4faa691d403274f38eb10890b533c /util/szap/szap.c | |
parent | 1c6e1f28f54ec2606c23936c1d8689f2be55a86c (diff) | |
parent | ab959d7b4194715870128e616b8e29d4a101e488 (diff) | |
download | linux-dvb-apps-debian/1.1.1+rev1207-1.tar.gz |
Imported Debian patch 1.1.1+rev1207-1debian/1.1.1+rev1207-1
Diffstat (limited to 'util/szap/szap.c')
-rw-r--r-- | util/szap/szap.c | 222 |
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; } - |