1 /* szap-s2 -- simple zapping tool for the Linux DVB S2 API
3 * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
4 * Copyright (C) 2013 CrazyCat (crazycat69@narod.ru)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <sys/ioctl.h>
29 #include <sys/types.h>
32 #include <sys/param.h>
40 #include <linux/dvb/frontend.h>
41 #include <linux/dvb/dmx.h>
42 #include <linux/dvb/audio.h>
43 #include <linux/dvb/version.h>
46 #if DVB_API_VERSION < 5 || DVB_API_VERSION_MINOR < 2
47 #error szap-s2 requires Linux DVB driver API version 5.2 and newer!
51 #define DTV_STREAM_ID DTV_ISDBS_TS_ID
54 #ifndef NO_STREAM_ID_FILTER
55 #define NO_STREAM_ID_FILTER (~0U)
65 /* location of channel list file */
66 #define CHANNEL_FILE "channels.conf"
68 /* one line of the szap channel file has the following format:
69 * ^name:frequency_MHz:polarization:sat_no:symbolrate:vpid:apid:service_id$
70 * one line of the VDR channel file has the following format:
71 * ^name:frequency_MHz:polarization[coderate][delivery][modulation][rolloff]:sat_no:symbolrate:vpid:apid:?:?:service_id:?:?:?$
75 #define FRONTENDDEVICE "/dev/dvb/adapter%d/frontend%d"
76 #define DEMUXDEVICE "/dev/dvb/adapter%d/demux%d"
77 #define AUDIODEVICE "/dev/dvb/adapter%d/audio%d"
79 struct t_channel_parameter_map
{
82 const char *user_string
;
84 /* --- Channel Parameter Maps From VDR---*/
86 static struct t_channel_parameter_map inversion_values
[] = {
87 { 0, INVERSION_OFF
, "off" },
88 { 1, INVERSION_ON
, "on" },
89 { 999, INVERSION_AUTO
},
93 static struct t_channel_parameter_map coderate_values
[] = {
94 { 0, FEC_NONE
, "none" },
95 { 12, FEC_1_2
, "1/2" },
96 // { 13, FEC_1_3, "1/3" },
97 // { 14, FEC_1_4, "1/4" },
98 { 23, FEC_2_3
, "2/3" },
99 // { 25, FEC_2_5, "2/5" },
100 { 34, FEC_3_4
, "3/4" },
101 { 35, FEC_3_5
, "3/5" },
102 { 45, FEC_4_5
, "4/5" },
103 { 56, FEC_5_6
, "5/6" },
104 { 67, FEC_6_7
, "6/7" },
105 { 78, FEC_7_8
, "7/8" },
106 { 89, FEC_8_9
, "8/9" },
107 { 910, FEC_9_10
, "9/10" },
108 { 999, FEC_AUTO
, "auto" },
112 static struct t_channel_parameter_map modulation_values
[] = {
113 // { 0, NONE, "none" },
114 // { 4, QAM_4, "QAM4" },
115 { 16, QAM_16
, "QAM16" },
116 { 32, QAM_32
, "QAM32" },
117 { 64, QAM_64
, "QAM64" },
118 { 128, QAM_128
, "QAM128" },
119 { 256, QAM_256
, "QAM256" },
120 // { 512, QAM_512, "QAM512" },
121 // {1024, QAM_1024, "QAM1024" },
122 // { 1, BPSK, "BPSK" },
124 // { 3, OQPSK, "OQPSK" },
125 { 5, PSK_8
, "8PSK" },
126 { 6, APSK_16
, "16APSK" },
127 { 7, APSK_32
, "32APSK" },
128 // { 8, OFDM, "OFDM" },
129 // { 9, COFDM, "COFDM" },
130 { 10, VSB_8
, "VSB8" },
131 { 11, VSB_16
, "VSB16" },
132 { 998, QAM_AUTO
, "QAMAUTO" },
137 static struct t_channel_parameter_map system_values
[] = {
138 { 0, SYS_DVBS
, "DVB-S" },
139 { 1, SYS_DVBS2
, "DVB-S2" },
144 static struct t_channel_parameter_map rolloff_values
[] = {
145 // { 0, ROLLOFF_AUTO, "auto"},
146 { 20, ROLLOFF_20
, "0.20" },
147 { 25, ROLLOFF_25
, "0.25" },
148 { 35, ROLLOFF_35
, "0.35" },
152 static int user_index(int value
, const struct t_channel_parameter_map
* map
)
154 const struct t_channel_parameter_map
*umap
= map
;
155 while (umap
&& umap
->user_value
!= -1) {
156 if (umap
->user_value
== value
)
163 static int driver_index(int value
, const struct t_channel_parameter_map
*map
)
165 const struct t_channel_parameter_map
*umap
= map
;
166 while (umap
&& umap
->user_value
!= -1) {
167 if (umap
->driver_value
== value
)
174 static int map_to_user(int value
, const struct t_channel_parameter_map
*map
, char **string
)
176 int n
= driver_index(value
, map
);
179 *string
= (char *)map
[n
].user_string
;
180 return map
[n
].user_value
;
185 static int map_to_driver(int value
, const struct t_channel_parameter_map
*map
)
187 int n
= user_index(value
, map
);
189 return map
[n
].driver_value
;
193 static struct lnb_types_st lnb_type
;
195 static int exit_after_tuning
;
196 static int interactive
;
198 static char *usage_str
=
199 "\nusage: szap-s2 -q\n"
200 " list known channels\n"
201 " szap-s2 [options] {-n channel-number|channel_name}\n"
202 " zap to channel via number or full name (case insensitive)\n"
203 " -a number : use given adapter (default 0)\n"
204 " -f number : use given frontend (default 0)\n"
205 " -d number : use given demux (default 0)\n"
206 " -c file : read channels list from 'file'\n"
207 " -V : use VDR channels list file format (default zap)\n"
208 " -b : enable Audio Bypass (default no)\n"
209 " -x : exit after tuning\n"
210 " -H : human readable output\n"
211 " -D : params debug\n"
212 " -r : set up /dev/dvb/adapterX/dvr0 for TS recording\n"
213 " -l lnb-type (DVB-S Only) (use -l help to print types) or \n"
214 " -l low[,high[,switch]] in Mhz\n"
215 " -i : run interactively, allowing you to type in channel names\n"
216 " -p : add pat and pmt to TS recording (implies -r)\n"
217 " or -n numbers for zapping\n"
218 " -t : add teletext to TS recording (needs -V)\n"
219 " -S : delivery system type DVB-S=0, DVB-S2=1\n"
220 " -M : modulation 1=BPSK 2=QPSK 5=8PSK\n"
221 " -C : fec 0=NONE 12=1/2 23=2/3 34=3/4 35=3/5 45=4/5 56=5/6 67=6/7 89=8/9 910=9/10 999=AUTO\n"
222 " -O : rolloff 35=0.35 25=0.25 20=0.20 0=UNKNOWN\n"
223 " -m : input stream 0-255\n";
225 static int set_demux(int dmxfd
, int pid
, int pes_type
, int dvr
)
227 struct dmx_pes_filter_params pesfilter
;
229 if (pid
< 0 || pid
>= 0x1fff) /* ignore this pid to allow radio services */
233 int buffersize
= 64 * 1024;
234 if (ioctl(dmxfd
, DMX_SET_BUFFER_SIZE
, buffersize
) == -1)
235 perror("DMX_SET_BUFFER_SIZE failed");
239 pesfilter
.input
= DMX_IN_FRONTEND
;
240 pesfilter
.output
= dvr
? DMX_OUT_TS_TAP
: DMX_OUT_DECODER
;
241 pesfilter
.pes_type
= pes_type
;
242 pesfilter
.flags
= DMX_IMMEDIATE_START
;
244 if (ioctl(dmxfd
, DMX_SET_PES_FILTER
, &pesfilter
) == -1) {
245 fprintf(stderr
, "DMX_SET_PES_FILTER failed "
246 "(PID = 0x%04x): %d %m\n", pid
, errno
);
254 int get_pmt_pid(char *dmxdev
, int sid
)
260 unsigned char buft
[4096];
261 unsigned char *buf
= buft
;
262 struct dmx_sct_filter_params f
;
264 memset(&f
, 0, sizeof(f
));
266 f
.filter
.filter
[0] = 0x00;
267 f
.filter
.mask
[0] = 0xff;
269 f
.flags
= DMX_IMMEDIATE_START
| DMX_CHECK_CRC
;
271 if ((patfd
= open(dmxdev
, O_RDWR
)) < 0) {
272 perror("openening pat demux failed");
276 if (ioctl(patfd
, DMX_SET_FILTER
, &f
) == -1) {
277 perror("ioctl DMX_SET_FILTER failed");
283 if (((count
= read(patfd
, buf
, sizeof(buft
))) < 0) && errno
== EOVERFLOW
)
284 count
= read(patfd
, buf
, sizeof(buft
));
286 perror("read_sections: read error");
291 section_length
= ((buf
[1] & 0x0f) << 8) | buf
[2];
292 if (count
!= section_length
+ 3)
298 patread
= 1; /* assumes one section contains the whole pat */
299 while (section_length
> 0) {
300 int service_id
= (buf
[0] << 8) | buf
[1];
301 if (service_id
== sid
) {
302 pmt_pid
= ((buf
[2] & 0x1f) << 8) | buf
[3];
314 struct dvb_diseqc_master_cmd cmd
;
318 void diseqc_send_msg(int fd
, fe_sec_voltage_t v
, struct diseqc_cmd
*cmd
,
319 fe_sec_tone_mode_t t
, fe_sec_mini_cmd_t b
)
321 if (ioctl(fd
, FE_SET_TONE
, SEC_TONE_OFF
) == -1)
322 perror("FE_SET_TONE failed");
323 if (ioctl(fd
, FE_SET_VOLTAGE
, v
) == -1)
324 perror("FE_SET_VOLTAGE failed");
326 if (ioctl(fd
, FE_DISEQC_SEND_MASTER_CMD
, &cmd
->cmd
) == -1)
327 perror("FE_DISEQC_SEND_MASTER_CMD failed");
328 usleep(cmd
->wait
* 1000);
330 if (ioctl(fd
, FE_DISEQC_SEND_BURST
, b
) == -1)
331 perror("FE_DISEQC_SEND_BURST failed");
333 if (ioctl(fd
, FE_SET_TONE
, t
) == -1)
334 perror("FE_SET_TONE failed");
341 /* digital satellite equipment control,
342 * specification is available from http://www.eutelsat.com/
344 static int diseqc(int secfd
, int sat_no
, int pol_vert
, int hi_band
)
346 struct diseqc_cmd cmd
=
347 { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
350 * param: high nibble: reset bits, low nibble set bits,
351 * bits are: option, position, polarizaion, band
354 0xf0 | (((sat_no
* 4) & 0x0f) | (hi_band
? 1 : 0) | (pol_vert
? 0 : 2));
356 diseqc_send_msg(secfd
, pol_vert
? SEC_VOLTAGE_13
: SEC_VOLTAGE_18
,
357 &cmd
, hi_band
? SEC_TONE_ON
: SEC_TONE_OFF
,
358 (sat_no
/ 4) % 2 ? SEC_MINI_B
: SEC_MINI_A
);
363 static int do_tune(int fefd
, unsigned int ifreq
, unsigned int sr
, enum fe_delivery_system delsys
,
364 int modulation
, int fec
, int rolloff
, int stream_id
)
366 struct dvb_frontend_event ev
;
367 struct dtv_property p
[] = {
368 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= delsys
},
369 { .cmd
= DTV_FREQUENCY
, .u
.data
= ifreq
},
370 { .cmd
= DTV_MODULATION
, .u
.data
= modulation
},
371 { .cmd
= DTV_SYMBOL_RATE
, .u
.data
= sr
},
372 { .cmd
= DTV_INNER_FEC
, .u
.data
= fec
},
373 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
374 { .cmd
= DTV_ROLLOFF
, .u
.data
= rolloff
},
375 { .cmd
= DTV_PILOT
, .u
.data
= PILOT_AUTO
},
376 { .cmd
= DTV_STREAM_ID
, .u
.data
= stream_id
},
379 struct dtv_properties cmdseq
= {
380 .num
= sizeof(p
)/sizeof(p
[0]),
384 /* discard stale QPSK events */
386 if (ioctl(fefd
, FE_GET_EVENT
, &ev
) == -1)
390 if ((delsys
!= SYS_DVBS
) && (delsys
!= SYS_DVBS2
))
393 if ((ioctl(fefd
, FE_SET_PROPERTY
, &cmdseq
)) == -1) {
394 perror("FE_SET_PROPERTY failed");
403 int check_frontend (int fe_fd
, int dvr
, int human_readable
, int params_debug
,
408 uint16_t snr
, signal
;
409 uint32_t ber
, uncorrected_blocks
;
412 struct dtv_property p
[] = {
413 { .cmd
= DTV_DELIVERY_SYSTEM
},
414 { .cmd
= DTV_MODULATION
},
415 { .cmd
= DTV_INNER_FEC
},
416 { .cmd
= DTV_ROLLOFF
},
417 { .cmd
= DTV_FREQUENCY
},
418 { .cmd
= DTV_SYMBOL_RATE
},
420 struct dtv_properties cmdseq
= {
421 .num
= sizeof(p
)/sizeof(p
[0]),
426 if (ioctl(fe_fd
, FE_READ_STATUS
, &status
) == -1)
427 perror("FE_READ_STATUS failed");
428 /* some frontends might not support all these ioctls, thus we
429 * avoid printing errors
431 if (ioctl(fe_fd
, FE_READ_SIGNAL_STRENGTH
, &signal
) == -1)
433 if (ioctl(fe_fd
, FE_READ_SNR
, &snr
) == -1)
435 if (ioctl(fe_fd
, FE_READ_BER
, &ber
) == -1)
437 if (ioctl(fe_fd
, FE_READ_UNCORRECTED_BLOCKS
, &uncorrected_blocks
) == -1)
438 uncorrected_blocks
= -2;
440 if (human_readable
) {
441 printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ",
442 status
, (signal
* 100) / 0xffff, (snr
* 100) / 0xffff, ber
, uncorrected_blocks
);
444 printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
445 status
, signal
, snr
, ber
, uncorrected_blocks
);
447 if (status
& FE_HAS_LOCK
)
448 printf("FE_HAS_LOCK");
451 if (exit_after_tuning
&& ((status
& FE_HAS_LOCK
) || (++timeout
>= 10)))
457 if ((status
& FE_HAS_LOCK
) == 0)
460 if ((ioctl(fe_fd
, FE_GET_PROPERTY
, &cmdseq
)) == -1) {
461 perror("FE_GET_PROPERTY failed");
464 /* printout found parameters here */
466 printf("delivery 0x%x, ", p
[0].u
.data
);
467 printf("modulation 0x%x\n", p
[1].u
.data
);
468 printf("coderate 0x%x, ", p
[2].u
.data
);
469 printf("rolloff 0x%x\n", p
[3].u
.data
);
470 printf("intermediate frequency %d,", p
[4].u
.data
);
473 map_to_user(p
[0].u
.data
, system_values
, &field
);
474 printf("delivery %s, ", field
);
476 map_to_user(p
[1].u
.data
, modulation_values
, &field
);
477 printf("modulation %s\n", field
);
479 map_to_user(p
[2].u
.data
, coderate_values
, &field
);
480 printf("coderate %s, ", field
);
482 map_to_user(p
[3].u
.data
, rolloff_values
, &field
);
483 printf("rolloff %s\n", field
);
485 printf("frequency %lu,",lnb_type
.high_val
+ p
[4].u
.data
);
487 printf("frequency %lu,",lnb_type
.low_val
+ p
[4].u
.data
);
491 printf("symbol_rate %d\n", p
[5].u
.data
);
497 int zap_to(unsigned int adapter
, unsigned int frontend
, unsigned int demux
,
498 unsigned int sat_no
, unsigned int freq
, unsigned int pol
,
499 unsigned int sr
, unsigned int vpid
, unsigned int apid
,
500 unsigned int tpid
, int sid
,
501 int dvr
, int rec_psi
, int bypass
, unsigned int delivery
,
502 int modulation
, int fec
, int rolloff
, int stream_id
, int human_readable
,
505 struct dtv_property p
[] = {
506 { .cmd
= DTV_CLEAR
},
509 struct dtv_properties cmdseq
= {
510 .num
= sizeof(p
)/sizeof(p
[0]),
514 char fedev
[128], dmxdev
[128], auddev
[128];
515 static int fefd
, dmxfda
, dmxfdv
, dmxfdt
= -1, audiofd
= -1, patfd
, pmtfd
;
521 snprintf(fedev
, sizeof(fedev
), FRONTENDDEVICE
, adapter
, frontend
);
522 snprintf(dmxdev
, sizeof(dmxdev
), DEMUXDEVICE
, adapter
, demux
);
523 snprintf(auddev
, sizeof(auddev
), AUDIODEVICE
, adapter
, demux
);
524 printf("using '%s' and '%s'\n", fedev
, dmxdev
);
526 if ((fefd
= open(fedev
, O_RDWR
| O_NONBLOCK
)) < 0) {
527 perror("opening frontend failed");
531 if ((dmxfdv
= open(dmxdev
, O_RDWR
)) < 0) {
532 perror("opening video demux failed");
537 if ((dmxfda
= open(dmxdev
, O_RDWR
)) < 0) {
538 perror("opening audio demux failed");
543 if ((dmxfdt
= open(dmxdev
, O_RDWR
)) < 0) {
544 perror("opening teletext demux failed");
549 if (dvr
== 0) /* DMX_OUT_DECODER */
550 audiofd
= open(auddev
, O_RDWR
);
553 if ((patfd
= open(dmxdev
, O_RDWR
)) < 0) {
554 perror("opening pat demux failed");
563 if ((pmtfd
= open(dmxdev
, O_RDWR
)) < 0) {
564 perror("opening pmt demux failed");
578 if (lnb_type
.switch_val
&& lnb_type
.high_val
&&
579 freq
>= lnb_type
.switch_val
)
583 ifreq
= freq
- lnb_type
.high_val
;
585 if (freq
< lnb_type
.low_val
)
586 ifreq
= lnb_type
.low_val
- freq
;
588 ifreq
= freq
- lnb_type
.low_val
;
592 if ((ioctl(fefd
, FE_SET_PROPERTY
, &cmdseq
)) == -1) {
593 perror("FE_SET_PROPERTY DTV_CLEAR failed");
597 if (diseqc(fefd
, sat_no
, pol
, hiband
))
598 if (do_tune(fefd
, ifreq
, sr
, delivery
, modulation
, fec
, rolloff
, stream_id
))
599 if (set_demux(dmxfdv
, vpid
, DMX_PES_VIDEO
, dvr
))
601 (void)ioctl(audiofd
, AUDIO_SET_BYPASS_MODE
, bypass
);
602 if (set_demux(dmxfda
, apid
, DMX_PES_AUDIO
, dvr
)) {
604 pmtpid
= get_pmt_pid(dmxdev
, sid
);
609 fprintf(stderr
,"couldn't find pmt-pid for sid %04x\n",sid
);
612 if (set_demux(patfd
, 0, DMX_PES_OTHER
, dvr
))
613 if (set_demux(pmtfd
, pmtpid
, DMX_PES_OTHER
, dvr
))
620 if (tpid
!= -1 && !set_demux(dmxfdt
, tpid
, DMX_PES_TELETEXT
, dvr
)) {
621 fprintf(stderr
, "set_demux DMX_PES_TELETEXT failed\n");
624 check_frontend (fefd
, dvr
, human_readable
, params_debug
, hiband
);
639 static char *parse_parameter(const char *s
, int *value
, const struct t_channel_parameter_map
*map
)
644 int n
= strtol(s
, &p
, 10);
645 if (!errno
&& p
!= s
) {
646 value
[0] = map_to_driver(n
, map
);
651 fprintf(stderr
, "ERROR: invalid value for parameter '%C'\n", *(s
- 1));
655 static int read_channels(const char *filename
, int list_channels
,
656 uint32_t chan_no
, const char *chan_name
,
657 unsigned int adapter
, unsigned int frontend
,
658 unsigned int demux
, int dvr
, int rec_psi
,
659 int bypass
, unsigned int delsys
,
660 int modulation
, int fec
, int rolloff
, int stream_id
,
661 int human_readable
, int params_debug
,
662 int use_vdr_format
, int use_tpid
)
667 char *field
, *tmp
, *p
;
669 unsigned int freq
, pol
, sat_no
, sr
, vpid
, apid
, tpid
, sid
;
674 if (!(cfp
= fopen(filename
, "r"))) {
675 fprintf(stderr
, "error opening channel list '%s': %d %m\n",
681 fprintf(stderr
, "\n>>> ");
682 if (!fgets(inp
, sizeof(inp
), stdin
)) {
686 if (inp
[0] == '-' && inp
[1] == 'n') {
687 chan_no
= strtoul(inp
+2, NULL
, 0);
690 fprintf(stderr
, "bad channel number\n");
694 p
= strchr(inp
, '\n');
703 if (fgets(buf
, sizeof(buf
), cfp
)) {
706 if (chan_no
&& chan_no
!= line
)
710 field
= strsep(&tmp
, ":");
716 printf("%03u %s\n", line
, field
);
720 if (chan_name
&& strcasecmp(chan_name
, field
) != 0)
723 printf("zapping to %d '%s':\n", line
, field
);
725 if (!(field
= strsep(&tmp
, ":")))
728 freq
= strtoul(field
, NULL
, 0);
730 if (!(field
= strsep(&tmp
, ":")))
733 while (field
&& *field
) {
734 switch (toupper(*field
)) {
737 field
= parse_parameter(field
, &fec
, coderate_values
);
739 field
= parse_parameter(field
, &trash
, coderate_values
);
745 case 'I':/* ignore */
746 field
= parse_parameter(field
, &ret
, inversion_values
);
753 if (modulation
== -1)
754 field
= parse_parameter(field
, &modulation
, modulation_values
);
756 field
= parse_parameter(field
, &trash
, modulation_values
);
761 field
= parse_parameter(field
, &rolloff
, rolloff_values
);
763 field
= parse_parameter(field
, &trash
, rolloff_values
);
766 stream_id
= strtol(++field
, &field
, 10);
774 field
= parse_parameter(field
, &delsys
, system_values
);
776 field
= parse_parameter(field
, &trash
, system_values
);
786 /* default values for empty parameters */
790 if (modulation
== -1)
797 rolloff
= ROLLOFF_35
;
800 if (stream_id
<0 || stream_id
>255)
801 stream_id
= NO_STREAM_ID_FILTER
;
804 if (!(field
= strsep(&tmp
, ":")))
807 sat_no
= strtoul(field
, NULL
, 0);
809 if (!(field
= strsep(&tmp
, ":")))
812 sr
= strtoul(field
, NULL
, 0) * 1000;
814 if (!(field
= strsep(&tmp
, ":")))
817 vpid
= strtoul(field
, NULL
, 0);
821 if (!(field
= strsep(&tmp
, ":")))
824 p
= strchr(field
, ';');
836 apid
= strtoul(field
, NULL
, 0);
841 if (use_vdr_format
) {
842 if (!(field
= strsep(&tmp
, ":")))
846 tpid
= strtoul(field
, NULL
, 0);
848 if (!(field
= strsep(&tmp
, ":")))
851 strtoul(field
, NULL
, 0);
854 if (!(field
= strsep(&tmp
, ":")))
857 sid
= strtoul(field
, NULL
, 0);
861 printf("delivery 0x%x, ", delsys
);
864 map_to_user(delsys
, system_values
, &field
);
865 printf("delivery %s, ", field
);
869 printf("modulation 0x%x\n", modulation
);
872 map_to_user(modulation
, modulation_values
, &field
);
873 printf("modulation %s\n", field
);
876 printf("sat %u, frequency %u MHz %c, symbolrate %u, ",
877 sat_no
, freq
, pol
? 'V' : 'H', sr
);
880 printf("coderate 0x%x, ", fec
);
883 map_to_user(fec
, coderate_values
, &field
);
884 printf("coderate %s, ", field
);
888 printf("rolloff 0x%x stream_id %d\n"
889 "vpid 0x%04x, apid 0x%04x, sid 0x%04x\n", rolloff
, stream_id
, vpid
, apid
, sid
);
892 map_to_user(rolloff
, rolloff_values
, &field
);
893 printf("rolloff %s stream_id %d\n"
894 "vpid 0x%04x, apid 0x%04x, sid 0x%04x\n", field
, stream_id
, vpid
, apid
, sid
);
897 ret
= zap_to(adapter
, frontend
, demux
, sat_no
, freq
* 1000,
898 pol
, sr
, vpid
, apid
, tpid
, sid
, dvr
, rec_psi
, bypass
,
899 delsys
, modulation
, fec
, rolloff
, stream_id
, human_readable
,
911 fprintf(stderr
, "syntax error in line %u: '%s'\n", line
, buf
);
912 } else if (ferror(cfp
)) {
913 fprintf(stderr
, "error reading channel list '%s': %d %m\n",
923 if (!list_channels
) {
924 fprintf(stderr
, "channel not found\n");
935 static void handle_sigint(int sig
)
937 fprintf(stderr
, "Interrupted by SIGINT!\n");
942 bad_usage(char *pname
, int prlnb
)
945 struct lnb_types_st
*lnbp
;
949 fprintf (stderr
, usage_str
, pname
);
952 fprintf(stderr
, "-l <lnb-type> or -l low[,high[,switch]] in Mhz\nwhere <lnb-type> is:\n");
953 while(NULL
!= (lnbp
= lnb_enum(i
))) {
954 fprintf (stderr
, "%s\n", lnbp
->name
);
955 for (cp
= lnbp
->desc
; *cp
; cp
++) {
956 fprintf (stderr
, " %s\n", *cp
);
963 int main(int argc
, char *argv
[])
966 char chanfile
[2 * PATH_MAX
];
967 int list_channels
= 0;
968 unsigned int chan_no
= 0;
969 const char *chan_name
= NULL
;
970 unsigned int adapter
= 0, frontend
= 0, demux
= 0, dvr
= 0, rec_psi
= 0;
973 int human_readable
= 0;
974 int params_debug
= 0;
975 int use_vdr_format
= 0;
983 int stream_id
= NO_STREAM_ID_FILTER
;
985 lnb_type
= *lnb_enum(0);
986 while ((opt
= getopt(argc
, argv
, "M:m:C:O:HDVhqrpn:a:f:d:S:c:l:xib")) != -1) {
991 bad_usage(argv
[0], 0);
994 parse_parameter(--optarg
, &fec
, coderate_values
);
997 parse_parameter(--optarg
, &modulation
, modulation_values
);
1001 parse_parameter(--optarg
, &rolloff
, rolloff_values
);
1004 stream_id
= strtol(optarg
, NULL
, 0);
1007 parse_parameter(--optarg
, &delsys
, system_values
);
1019 chan_no
= strtoul(optarg
, NULL
, 0);
1022 adapter
= strtoul(optarg
, NULL
, 0);
1025 frontend
= strtoul(optarg
, NULL
, 0);
1031 demux
= strtoul(optarg
, NULL
, 0);
1035 strncpy(chanfile
, optarg
, sizeof(chanfile
));
1038 if (lnb_decode(optarg
, &lnb_type
) < 0) {
1039 bad_usage(argv
[0], 1);
1044 exit_after_tuning
= 1;
1060 exit_after_tuning
= 1;
1063 lnb_type
.low_val
*= 1000; /* convert to kiloherz */
1064 lnb_type
.high_val
*= 1000; /* convert to kiloherz */
1065 lnb_type
.switch_val
*= 1000; /* convert to kiloherz */
1067 chan_name
= argv
[optind
];
1068 if (chan_name
&& chan_no
) {
1069 bad_usage(argv
[0], 0);
1072 if (list_channels
&& (chan_name
|| chan_no
)) {
1073 bad_usage(argv
[0], 0);
1076 if (!list_channels
&& !chan_name
&& !chan_no
&& !interactive
) {
1077 bad_usage(argv
[0], 0);
1082 if (!(home
= getenv("HOME"))) {
1083 fprintf(stderr
, "error: $HOME not set\n");
1086 snprintf(chanfile
, sizeof(chanfile
),
1087 "%s/.szap/%i/%s", home
, adapter
, CHANNEL_FILE
);
1088 if (access(chanfile
, R_OK
))
1089 snprintf(chanfile
, sizeof(chanfile
),
1090 "%s/.szap/%s", home
, CHANNEL_FILE
);
1093 printf("reading channels from file '%s'\n", chanfile
);
1098 signal(SIGINT
, handle_sigint
);
1100 if (!read_channels(chanfile
, list_channels
, chan_no
, chan_name
,
1101 adapter
, frontend
, demux
, dvr
, rec_psi
, bypass
, delsys
,
1102 modulation
, fec
, rolloff
, stream_id
, human_readable
, params_debug
,
1103 use_vdr_format
, use_tpid
))