1 /*****************************************************************************
2 * dvb.c: linux-dvb input for DVBlast
3 *****************************************************************************
4 * Copyright (C) 2008-2010, 2015 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 #ifdef HAVE_DVB_SUPPORT
32 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
44 /* DVB Card Drivers */
45 #include <linux/dvb/version.h>
46 #include <linux/dvb/dmx.h>
47 #include <linux/dvb/frontend.h>
48 #include <linux/dvb/ca.h>
52 #if DVBAPI_VERSION < 508
53 #define DTV_STREAM_ID 42
54 #define FE_CAN_MULTISTREAM 0x4000000
55 #define FE_CAN_TURBO_FEC 0x8000000
58 #define MAX_DELIVERY_SYSTEMS 20
64 #include <bitstream/common.h>
66 /*****************************************************************************
68 *****************************************************************************/
69 #define DVR_READ_TIMEOUT 30000000 /* 30 s */
70 #define MAX_READ_ONCE 50
71 #define DVR_BUFFER_SIZE 40*188*1024 /* bytes */
73 int i_dvr_buffer_size
= DVR_BUFFER_SIZE
;
75 static int i_frontend
, i_dvr
, i_sec
;
76 static struct ev_io frontend_watcher
, dvr_watcher
;
77 static struct ev_timer lock_watcher
, mute_watcher
, print_watcher
;
78 static fe_status_t i_last_status
;
79 static block_t
*p_freelist
= NULL
;
81 /*****************************************************************************
83 *****************************************************************************/
84 static void DVRRead(struct ev_loop
*loop
, struct ev_io
*w
, int revents
);
85 static void DVRMuteCb(struct ev_loop
*loop
, struct ev_timer
*w
, int revents
);
86 static void FrontendRead(struct ev_loop
*loop
, struct ev_io
*w
, int revents
);
87 static void FrontendLockCb(struct ev_loop
*loop
, struct ev_timer
*w
, int revents
);
88 static void FrontendSet( bool b_reset
);
90 /*****************************************************************************
92 *****************************************************************************/
93 void dvb_OpenDvr( void )
97 sprintf( psz_tmp
, "/dev/dvb/adapter%d/dvr%d", i_adapter
, i_fenum
);
98 if( (i_dvr
= open(psz_tmp
, O_RDONLY
| O_NONBLOCK
)) < 0 )
100 msg_Info(NULL
, "opening device %s failed (%s), fallback on sec device",
101 psz_tmp
, strerror(errno
));
103 /* try to read from sec device */
104 sprintf(psz_tmp
, "/dev/dvb/adapter%d/sec%d", i_adapter
, i_fenum
);
105 if ( (i_dvr
= open(psz_tmp
, O_RDONLY
| O_NONBLOCK
)) < 0 )
107 msg_Err(NULL
, "opening device %s failed (%s)", psz_tmp
,
113 if ( ioctl( i_dvr
, DMX_SET_BUFFER_SIZE
, i_dvr_buffer_size
) < 0 )
115 msg_Warn( NULL
, "couldn't set %s buffer size (%s)", psz_tmp
,
119 ev_io_init(&dvr_watcher
, DVRRead
, i_dvr
, EV_READ
);
120 ev_io_start(event_loop
, &dvr_watcher
);
123 /*****************************************************************************
125 *****************************************************************************/
126 void dvb_OpenSec( void )
130 msg_Dbg( NULL
, "compiled with DVB API version %d.%d", DVB_API_VERSION
, DVB_API_VERSION_MINOR
);
134 sprintf( psz_tmp
, "/dev/dvb/adapter%d/sec%d", i_adapter
, i_secnum
);
135 if( (i_sec
= open(psz_tmp
, O_WRONLY
)) < 0 )
137 msg_Err(NULL
, "opening device %s failed (%s)", psz_tmp
,
143 /*****************************************************************************
145 *****************************************************************************/
146 void dvb_Open( void )
150 msg_Dbg( NULL
, "compiled with DVB API version %d.%d", DVB_API_VERSION
, DVB_API_VERSION_MINOR
);
154 sprintf( psz_tmp
, "/dev/dvb/adapter%d/frontend%d", i_adapter
, i_fenum
);
155 if( (i_frontend
= open(psz_tmp
, O_RDWR
| O_NONBLOCK
)) < 0 )
157 msg_Err( NULL
, "opening device %s failed (%s)", psz_tmp
,
171 if ( i_frontend
!= -1 )
173 ev_io_init(&frontend_watcher
, FrontendRead
, i_frontend
, EV_READ
);
174 ev_io_start(event_loop
, &frontend_watcher
);
177 ev_timer_init(&lock_watcher
, FrontendLockCb
,
178 i_frontend_timeout_duration
/ 1000000.,
179 i_frontend_timeout_duration
/ 1000000.);
180 ev_timer_init(&mute_watcher
, DVRMuteCb
,
181 DVR_READ_TIMEOUT
/ 1000000.,
182 DVR_READ_TIMEOUT
/ 1000000.);
187 /*****************************************************************************
189 *****************************************************************************/
190 void dvb_Reset( void )
196 /*****************************************************************************
198 *****************************************************************************/
199 static void DVRRead(struct ev_loop
*loop
, struct ev_io
*w
, int revents
)
202 block_t
*p_ts
= p_freelist
, **pp_current
= &p_ts
;
203 struct iovec p_iov
[MAX_READ_ONCE
];
205 for ( i
= 0; i
< MAX_READ_ONCE
; i
++ )
207 if ( (*pp_current
) == NULL
) *pp_current
= block_New();
208 p_iov
[i
].iov_base
= (*pp_current
)->p_ts
;
209 p_iov
[i
].iov_len
= TS_SIZE
;
210 pp_current
= &(*pp_current
)->p_next
;
213 if ( (i_len
= readv(i_dvr
, p_iov
, MAX_READ_ONCE
)) < 0 )
215 msg_Err( NULL
, "couldn't read from DVR device (%s)",
222 ev_timer_again(loop
, &mute_watcher
);
225 while ( i_len
&& *pp_current
)
227 pp_current
= &(*pp_current
)->p_next
;
231 p_freelist
= *pp_current
;
237 static void DVRMuteCb(struct ev_loop
*loop
, struct ev_timer
*w
, int revents
)
239 msg_Warn( NULL
, "no DVR output, resetting" );
240 ev_timer_stop(loop
, w
);
242 switch (i_print_type
) {
244 fprintf(print_fh
, "<EVENT type=\"reset\" cause=\"dvr\" />\n");
247 fprintf(print_fh
, "reset cause: dvr\n");
262 /*****************************************************************************
263 * dvb_SetFilter : controls the demux to add a filter
264 *****************************************************************************/
265 int dvb_SetFilter( uint16_t i_pid
)
267 struct dmx_pes_filter_params s_filter_params
;
271 sprintf( psz_tmp
, "/dev/dvb/adapter%d/demux%d", i_adapter
, i_fenum
);
272 if( (i_fd
= open(psz_tmp
, O_RDWR
)) < 0 )
274 msg_Err( NULL
, "DMXSetFilter: opening device failed (%s)",
279 s_filter_params
.pid
= i_pid
;
280 s_filter_params
.input
= DMX_IN_FRONTEND
;
281 s_filter_params
.output
= DMX_OUT_TS_TAP
;
282 s_filter_params
.flags
= DMX_IMMEDIATE_START
;
283 s_filter_params
.pes_type
= DMX_PES_OTHER
;
285 if ( ioctl( i_fd
, DMX_SET_PES_FILTER
, &s_filter_params
) < 0 )
287 msg_Err( NULL
, "failed setting filter on %d (%s)", i_pid
,
293 msg_Dbg( NULL
, "setting filter on PID %d", i_pid
);
298 /*****************************************************************************
299 * dvb_UnsetFilter : removes a filter
300 *****************************************************************************/
301 void dvb_UnsetFilter( int i_fd
, uint16_t i_pid
)
303 if ( ioctl( i_fd
, DMX_STOP
) < 0 )
304 msg_Err( NULL
, "DMX_STOP failed (%s)", strerror(errno
) );
306 msg_Dbg( NULL
, "unsetting filter on PID %d", i_pid
);
311 /*****************************************************************************
312 * dvb_WriteSec: write data to sec device
313 *****************************************************************************/
314 void dvb_WriteSec( block_t
*p_ts
)
318 for (block_t
*p_b
= p_ts
; p_b
; p_b
= p_b
->p_next
)
321 struct iovec p_iov
[i_iov
];
322 struct iovec
*p_current
= &p_iov
[0];
323 for (block_t
*p_b
= p_ts
; p_b
; p_b
= p_b
->p_next
)
325 p_current
->iov_base
= p_b
->p_ts
;
326 p_current
->iov_len
= TS_SIZE
;
331 if ( (i_len
= writev( i_sec
, p_iov
, i_iov
)) < 0 )
333 msg_Err( NULL
, "couldn't write to DVB sec (%s)", strerror(errno
) );
336 block_DeleteChain( p_ts
);
343 /*****************************************************************************
345 *****************************************************************************/
346 static void PrintCb( struct ev_loop
*loop
, struct ev_timer
*w
, int revents
)
349 uint16_t i_strength
= 0, i_snr
= 0;
350 uint32_t i_uncorrected
= 0;
352 ioctl(i_frontend
, FE_READ_BER
, &i_ber
);
353 ioctl(i_frontend
, FE_READ_SIGNAL_STRENGTH
, &i_strength
);
354 ioctl(i_frontend
, FE_READ_SNR
, &i_snr
);
355 ioctl(i_frontend
, FE_READ_UNCORRECTED_BLOCKS
, &i_uncorrected
);
357 int64_t i_strength_dbm
= i_strength
;
358 int64_t i_snr_db
= i_snr
;
360 #ifdef DTV_STAT_SIGNAL_STRENGTH
361 struct dtv_property prop
[] = {
362 { .cmd
= DTV_STAT_SIGNAL_STRENGTH
},
363 { .cmd
= DTV_STAT_CNR
},
366 struct dtv_properties props
= { .num
= 2, .props
= prop
};
367 if (ioctl(i_frontend
, FE_GET_PROPERTY
, &props
) != -1)
369 if (prop
[0].u
.st
.len
> 0 &&
370 prop
[0].u
.st
.stat
[0].scale
== FE_SCALE_DECIBEL
)
371 i_strength_dbm
= prop
[0].u
.st
.stat
[0].svalue
;
372 if (prop
[1].u
.st
.len
> 0 &&
373 prop
[1].u
.st
.stat
[0].scale
== FE_SCALE_DECIBEL
)
374 i_snr_db
= prop
[1].u
.st
.stat
[0].svalue
;
378 switch (i_print_type
)
382 "<STATUS type=\"frontend\" ber=\"%"PRIu32
"\" strength=\"%"PRId64
"\" snr=\"%"PRId64
"\" uncorrected=\"%"PRIu32
"\" />\n",
383 i_ber
, i_strength_dbm
, i_snr_db
, i_uncorrected
);
386 fprintf(print_fh
, "frontend ber: %"PRIu32
" strength: %"PRId64
" snr: %"PRId64
" uncorrected: %"PRIu32
"\n",
387 i_ber
, i_strength_dbm
, i_snr_db
, i_uncorrected
);
394 /*****************************************************************************
396 *****************************************************************************/
397 static void FrontendRead(struct ev_loop
*loop
, struct ev_io
*w
, int revents
)
399 struct dvb_frontend_event event
;
400 fe_status_t i_status
, i_diff
;
404 int i_ret
= ioctl( i_frontend
, FE_GET_EVENT
, &event
);
408 if( errno
== EWOULDBLOCK
)
409 return; /* no more events */
411 msg_Err( NULL
, "reading frontend event failed (%d) %s",
412 i_ret
, strerror(errno
) );
416 i_status
= event
.status
;
417 i_diff
= i_status
^ i_last_status
;
418 i_last_status
= i_status
;
423 if ( i_diff & (x) ) \
425 if ( i_status & (x) )
427 IF_UP( FE_HAS_SIGNAL
)
428 msg_Dbg( NULL
, "frontend has acquired signal" );
430 msg_Dbg( NULL
, "frontend has lost signal" );
432 IF_UP( FE_HAS_CARRIER
)
433 msg_Dbg( NULL
, "frontend has acquired carrier" );
435 msg_Dbg( NULL
, "frontend has lost carrier" );
437 IF_UP( FE_HAS_VITERBI
)
438 msg_Dbg( NULL
, "frontend has acquired stable FEC" );
440 msg_Dbg( NULL
, "frontend has lost FEC" );
443 msg_Dbg( NULL
, "frontend has acquired sync" );
445 msg_Dbg( NULL
, "frontend has lost sync" );
450 msg_Info( NULL
, "frontend has acquired lock" );
451 switch (i_print_type
) {
453 fprintf(print_fh
, "<STATUS type=\"lock\" status=\"1\" />\n");
456 fprintf(print_fh
, "lock status: 1\n");
462 ev_timer_stop(loop
, &lock_watcher
);
463 ev_timer_again(loop
, &mute_watcher
);
465 /* Read some statistics */
466 if( ioctl( i_frontend
, FE_READ_BER
, &i_value
) >= 0 )
467 msg_Dbg( NULL
, "- Bit error rate: %d", i_value
);
468 if( ioctl( i_frontend
, FE_READ_SIGNAL_STRENGTH
, &i_value
) >= 0 )
469 msg_Dbg( NULL
, "- Signal strength: %d", i_value
);
470 if( ioctl( i_frontend
, FE_READ_SNR
, &i_value
) >= 0 )
471 msg_Dbg( NULL
, "- SNR: %d", i_value
);
475 ev_timer_init( &print_watcher
, PrintCb
,
476 i_print_period
/ 1000000.,
477 i_print_period
/ 1000000. );
478 ev_timer_start( event_loop
, &print_watcher
);
483 msg_Dbg( NULL
, "frontend has lost lock" );
484 switch (i_print_type
) {
486 fprintf(print_fh
, "<STATUS type=\"lock\" status=\"0\"/>\n");
489 fprintf(print_fh
, "lock status: 0\n");
495 if (i_frontend_timeout_duration
)
497 ev_timer_stop(event_loop
, &lock_watcher
);
498 ev_timer_again(loop
, &mute_watcher
);
502 ev_timer_stop(event_loop
, &print_watcher
);
507 /* The frontend was reinited. */
508 msg_Warn( NULL
, "reiniting frontend");
517 static void FrontendLockCb(struct ev_loop
*loop
, struct ev_timer
*w
, int revents
)
519 if ( i_quit_timeout_duration
)
521 msg_Err( NULL
, "no lock" );
522 ev_break(loop
, EVBREAK_ALL
);
526 msg_Warn( NULL
, "no lock, tuning again" );
527 ev_timer_stop(loop
, w
);
529 switch (i_print_type
) {
531 fprintf(print_fh
, "<EVENT type=\"reset\" cause=\"nolock\" />\n");
534 fprintf(print_fh
, "reset cause: nolock\n");
543 static int FrontendDoDiseqc(void)
545 fe_sec_voltage_t fe_voltage
;
546 fe_sec_tone_mode_t fe_tone
;
551 case 0: fe_voltage
= SEC_VOLTAGE_OFF
; break;
553 case 13: fe_voltage
= SEC_VOLTAGE_13
; break;
554 case 18: fe_voltage
= SEC_VOLTAGE_18
; break;
557 fe_tone
= b_tone
? SEC_TONE_ON
: SEC_TONE_OFF
;
559 if ( strcmp( psz_lnb_type
, "universal" ) == 0 )
561 /* Automatic mode. */
562 if ( i_frequency
>= 950000 && i_frequency
<= 2150000 )
564 msg_Dbg( NULL
, "frequency %d is in IF-band", i_frequency
);
565 bis_frequency
= i_frequency
;
567 else if ( i_frequency
>= 2500000 && i_frequency
<= 2700000 )
569 msg_Dbg( NULL
, "frequency %d is in S-band", i_frequency
);
570 bis_frequency
= 3650000 - i_frequency
;
572 else if ( i_frequency
>= 3400000 && i_frequency
<= 4200000 )
574 msg_Dbg( NULL
, "frequency %d is in C-band (lower)", i_frequency
);
575 bis_frequency
= 5150000 - i_frequency
;
577 else if ( i_frequency
>= 4500000 && i_frequency
<= 4800000 )
579 msg_Dbg( NULL
, "frequency %d is in C-band (higher)", i_frequency
);
580 bis_frequency
= 5950000 - i_frequency
;
582 else if ( i_frequency
>= 10700000 && i_frequency
< 11700000 )
584 msg_Dbg( NULL
, "frequency %d is in Ku-band (lower)",
586 bis_frequency
= i_frequency
- 9750000;
588 else if ( i_frequency
>= 11700000 && i_frequency
<= 13250000 )
590 msg_Dbg( NULL
, "frequency %d is in Ku-band (higher)",
592 bis_frequency
= i_frequency
- 10600000;
593 fe_tone
= SEC_TONE_ON
;
597 msg_Err( NULL
, "frequency %d is out of any known band",
602 else if ( strcmp( psz_lnb_type
, "old-sky" ) == 0 )
604 if ( i_frequency
>= 11700000 && i_frequency
<= 13250000 )
606 msg_Dbg( NULL
, "frequency %d is in Ku-band (higher)",
608 bis_frequency
= i_frequency
- 11300000;
609 fe_tone
= SEC_TONE_ON
;
613 msg_Err( NULL
, "frequency %d is out of any known band",
620 msg_Err( NULL
, "lnb-type '%s' is not known. Valid type: universal old-sky",
625 /* Switch off continuous tone. */
626 if ( ioctl( i_frontend
, FE_SET_TONE
, SEC_TONE_OFF
) < 0 )
628 msg_Err( NULL
, "FE_SET_TONE failed (%s)", strerror(errno
) );
632 /* Configure LNB voltage. */
633 if ( ioctl( i_frontend
, FE_SET_VOLTAGE
, fe_voltage
) < 0 )
635 msg_Err( NULL
, "FE_SET_VOLTAGE failed (%s)", strerror(errno
) );
639 /* Wait for at least 15 ms. Currently 100 ms because of broken drivers. */
643 if ( i_satnum
> 0 && i_satnum
< 5 )
645 /* digital satellite equipment control,
646 * specification is available from http://www.eutelsat.com/
650 struct dvb_diseqc_master_cmd uncmd
=
651 { {0xe0, 0x10, 0x39, 0xf0, 0x00, 0x00}, 4};
654 struct dvb_diseqc_master_cmd cmd
=
655 { {0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4};
657 cmd
.msg
[3] = 0xf0 /* reset bits */
658 | ((i_satnum
- 1) << 2)
659 | (fe_voltage
== SEC_VOLTAGE_13
? 0 : 2)
660 | (fe_tone
== SEC_TONE_ON
? 1 : 0);
662 if ( i_uncommitted
> 0 && i_uncommitted
< 17 )
664 uncmd
.msg
[3] = 0xf0 /* reset bits */
665 | (i_uncommitted
- 1);
666 if( ioctl( i_frontend
, FE_DISEQC_SEND_MASTER_CMD
, &uncmd
) < 0 )
668 msg_Err( NULL
, "ioctl FE_SEND_MASTER_CMD failed (%s)",
672 /* Repeat uncommitted command */
673 uncmd
.msg
[0] = 0xe1; /* framing: master, no reply, repeated TX */
674 if( ioctl( i_frontend
, FE_DISEQC_SEND_MASTER_CMD
, &uncmd
) < 0 )
676 msg_Err( NULL
, "ioctl FE_SEND_MASTER_CMD failed (%s)",
680 /* Pause 125 ms between uncommitted & committed diseqc commands. */
684 if( ioctl( i_frontend
, FE_DISEQC_SEND_MASTER_CMD
, &cmd
) < 0 )
686 msg_Err( NULL
, "ioctl FE_SEND_MASTER_CMD failed (%s)",
690 msleep(100000); /* Should be 15 ms. */
692 /* Do it again just to be sure. */
693 cmd
.msg
[0] = 0xe1; /* framing: master, no reply, repeated TX */
694 if( ioctl( i_frontend
, FE_DISEQC_SEND_MASTER_CMD
, &cmd
) < 0 )
696 msg_Err( NULL
, "ioctl FE_SEND_MASTER_CMD failed (%s)",
700 msleep(100000); /* Again, should be 15 ms */
702 else if ( i_satnum
== 0xA || i_satnum
== 0xB )
704 /* A or B simple diseqc ("diseqc-compatible") */
705 if( ioctl( i_frontend
, FE_DISEQC_SEND_BURST
,
706 i_satnum
== 0xB ? SEC_MINI_B
: SEC_MINI_A
) < 0 )
708 msg_Err( NULL
, "ioctl FE_SEND_BURST failed (%s)", strerror(errno
) );
711 msleep(100000); /* ... */
714 if ( ioctl( i_frontend
, FE_SET_TONE
, fe_tone
) < 0 )
716 msg_Err( NULL
, "FE_SET_TONE failed (%s)", strerror(errno
) );
720 msleep(100000); /* ... */
722 msg_Dbg( NULL
, "configuring LNB to v=%d p=%d satnum=%x uncommitted=%x lnb-type=%s bis_frequency=%d",
723 i_voltage
, b_tone
, i_satnum
, i_uncommitted
, psz_lnb_type
, bis_frequency
);
724 return bis_frequency
;
727 #if DVB_API_VERSION >= 5
729 #if DVBAPI_VERSION < 505
730 #warning Your linux-dvb headers are old, you should consider upgrading your kernel and/or compiling against different kernel headers
733 /*****************************************************************************
734 * Helper functions for S2API
735 *****************************************************************************/
736 static fe_spectral_inversion_t
GetInversion(void)
738 switch ( i_inversion
)
740 case 0: return INVERSION_OFF
;
741 case 1: return INVERSION_ON
;
743 msg_Warn( NULL
, "invalid inversion %d", i_inversion
);
744 case -1: return INVERSION_AUTO
;
748 static fe_code_rate_t
GetFEC(fe_caps_t fe_caps
, int i_fec_value
)
750 #define GET_FEC_INNER(fec, val) \
751 if ( (fe_caps & FE_CAN_##fec) && (i_fec_value == val) ) \
754 GET_FEC_INNER(FEC_AUTO
, 999);
755 GET_FEC_INNER(FEC_AUTO
, -1);
756 if (i_fec_value
== 0)
758 GET_FEC_INNER(FEC_1_2
, 12);
759 GET_FEC_INNER(FEC_2_3
, 23);
760 GET_FEC_INNER(FEC_3_4
, 34);
761 if (i_fec_value
== 35)
763 GET_FEC_INNER(FEC_4_5
, 45);
764 GET_FEC_INNER(FEC_5_6
, 56);
765 GET_FEC_INNER(FEC_6_7
, 67);
766 GET_FEC_INNER(FEC_7_8
, 78);
767 GET_FEC_INNER(FEC_8_9
, 89);
768 if (i_fec_value
== 910)
772 msg_Warn(NULL
, "invalid FEC %d", i_fec_value
);
776 #define GetFECInner(caps) GetFEC(caps, i_fec)
777 #define GetFECLP(caps) GetFEC(caps, i_fec_lp)
779 static fe_modulation_t
GetModulation(void)
781 #define GET_MODULATION( mod ) \
782 if ( !strcasecmp( psz_modulation, #mod ) ) \
785 GET_MODULATION(QPSK
);
786 GET_MODULATION(QAM_16
);
787 GET_MODULATION(QAM_32
);
788 GET_MODULATION(QAM_64
);
789 GET_MODULATION(QAM_128
);
790 GET_MODULATION(QAM_256
);
791 GET_MODULATION(QAM_AUTO
);
792 GET_MODULATION(VSB_8
);
793 GET_MODULATION(VSB_16
);
794 GET_MODULATION(PSK_8
);
795 GET_MODULATION(APSK_16
);
796 GET_MODULATION(APSK_32
);
797 GET_MODULATION(DQPSK
);
799 #undef GET_MODULATION
800 msg_Err( NULL
, "invalid modulation %s", psz_modulation
);
804 static fe_pilot_t
GetPilot(void)
808 case 0: return PILOT_OFF
;
809 case 1: return PILOT_ON
;
811 msg_Warn( NULL
, "invalid pilot %d", i_pilot
);
812 case -1: return PILOT_AUTO
;
816 static fe_rolloff_t
GetRollOff(void)
821 case 0: return ROLLOFF_AUTO
;
822 case 20: return ROLLOFF_20
;
823 case 25: return ROLLOFF_25
;
825 msg_Warn( NULL
, "invalid rolloff %d", i_rolloff
);
826 case 35: return ROLLOFF_35
;
830 static fe_guard_interval_t
GetGuard(void)
834 case 32: return GUARD_INTERVAL_1_32
;
835 case 16: return GUARD_INTERVAL_1_16
;
836 case 8: return GUARD_INTERVAL_1_8
;
837 case 4: return GUARD_INTERVAL_1_4
;
839 msg_Warn( NULL
, "invalid guard interval %d", i_guard
);
841 case 0: return GUARD_INTERVAL_AUTO
;
845 static fe_transmit_mode_t
GetTransmission(void)
847 switch ( i_transmission
)
849 case 2: return TRANSMISSION_MODE_2K
;
850 case 8: return TRANSMISSION_MODE_8K
;
851 #ifdef TRANSMISSION_MODE_4K
852 case 4: return TRANSMISSION_MODE_4K
;
855 msg_Warn( NULL
, "invalid tranmission mode %d", i_transmission
);
857 case 0: return TRANSMISSION_MODE_AUTO
;
861 static fe_hierarchy_t
GetHierarchy(void)
863 switch ( i_hierarchy
)
865 case 0: return HIERARCHY_NONE
;
866 case 1: return HIERARCHY_1
;
867 case 2: return HIERARCHY_2
;
868 case 4: return HIERARCHY_4
;
870 msg_Warn( NULL
, "invalid intramission mode %d", i_transmission
);
871 case -1: return HIERARCHY_AUTO
;
875 /*****************************************************************************
876 * FrontendInfo : Print frontend info
877 *****************************************************************************/
878 static void FrontendInfo( struct dvb_frontend_info
*info
, uint32_t version
,
879 fe_delivery_system_t
*p_systems
, int i_systems
)
881 msg_Dbg( NULL
, "using DVB API version %d.%d", version
/ 256, version
% 256 );
882 msg_Dbg( NULL
, "Frontend \"%s\" supports:", info
->name
);
883 msg_Dbg( NULL
, " frequency min: %d, max: %d, stepsize: %d, tolerance: %d",
884 info
->frequency_min
, info
->frequency_max
,
885 info
->frequency_stepsize
, info
->frequency_tolerance
);
886 msg_Dbg( NULL
, " symbolrate min: %d, max: %d, tolerance: %d",
887 info
->symbol_rate_min
, info
->symbol_rate_max
, info
->symbol_rate_tolerance
);
888 msg_Dbg( NULL
, " capabilities:" );
890 #define FRONTEND_INFO(caps,val,msg) \
892 msg_Dbg( NULL, " %s", msg );
894 FRONTEND_INFO( info
->caps
, FE_IS_STUPID
, "FE_IS_STUPID" )
895 FRONTEND_INFO( info
->caps
, FE_CAN_INVERSION_AUTO
, "INVERSION_AUTO" )
896 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_1_2
, "FEC_1_2" )
897 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_2_3
, "FEC_2_3" )
898 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_3_4
, "FEC_3_4" )
899 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_4_5
, "FEC_4_5" )
900 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_5_6
, "FEC_5_6" )
901 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_6_7
, "FEC_6_7" )
902 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_7_8
, "FEC_7_8" )
903 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_8_9
, "FEC_8_9" )
904 FRONTEND_INFO( info
->caps
, FE_CAN_FEC_AUTO
,"FEC_AUTO")
905 FRONTEND_INFO( info
->caps
, FE_CAN_QPSK
, "QPSK" )
906 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_16
, "QAM_16" )
907 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_32
, "QAM_32" )
908 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_64
, "QAM_64" )
909 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_128
,"QAM_128")
910 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_256
,"QAM_256")
911 FRONTEND_INFO( info
->caps
, FE_CAN_QAM_AUTO
,"QAM_AUTO" )
912 FRONTEND_INFO( info
->caps
, FE_CAN_TRANSMISSION_MODE_AUTO
, "TRANSMISSION_MODE_AUTO" )
913 FRONTEND_INFO( info
->caps
, FE_CAN_BANDWIDTH_AUTO
, "BANDWIDTH_AUTO" )
914 FRONTEND_INFO( info
->caps
, FE_CAN_GUARD_INTERVAL_AUTO
, "GUARD_INTERVAL_AUTO" )
915 FRONTEND_INFO( info
->caps
, FE_CAN_HIERARCHY_AUTO
, "HIERARCHY_AUTO" )
916 FRONTEND_INFO( info
->caps
, FE_CAN_8VSB
, "8VSB" )
917 FRONTEND_INFO( info
->caps
, FE_CAN_16VSB
,"16VSB" )
918 FRONTEND_INFO( info
->caps
, FE_HAS_EXTENDED_CAPS
, "EXTENDED_CAPS" )
919 #if DVBAPI_VERSION >= 501
920 FRONTEND_INFO( info
->caps
, FE_CAN_2G_MODULATION
, "2G_MODULATION" )
922 FRONTEND_INFO( info
->caps
, FE_CAN_MULTISTREAM
, "MULTISTREAM" )
923 FRONTEND_INFO( info
->caps
, FE_CAN_TURBO_FEC
, "TURBO_FEC" )
924 FRONTEND_INFO( info
->caps
, FE_NEEDS_BENDING
, "NEEDS_BENDING" )
925 FRONTEND_INFO( info
->caps
, FE_CAN_RECOVER
, "FE_CAN_RECOVER" )
926 FRONTEND_INFO( info
->caps
, FE_CAN_MUTE_TS
, "FE_CAN_MUTE_TS" )
929 msg_Dbg( NULL
, " delivery systems:" );
931 for ( i
= 0; i
< i_systems
; i
++ )
933 switch ( p_systems
[i
] )
935 #define DELSYS_INFO(delsys, msg) \
936 case delsys: msg_Dbg( NULL, " %s", msg); break;
937 DELSYS_INFO( SYS_ATSC
, "ATSC" )
938 DELSYS_INFO( SYS_ATSCMH
, "ATSCMH" )
939 DELSYS_INFO( SYS_CMMB
, "CMBB" )
940 DELSYS_INFO( SYS_DAB
, "DAB" )
941 DELSYS_INFO( SYS_DSS
, "DSS" )
942 DELSYS_INFO( SYS_DVBC_ANNEX_B
, "DVBC_ANNEX_B" )
943 DELSYS_INFO( SYS_DVBH
, "DVBH" )
944 DELSYS_INFO( SYS_DVBS
, "DVBS" )
945 DELSYS_INFO( SYS_DVBS2
, "DVBS2" )
946 DELSYS_INFO( SYS_DVBT
, "DVBT" )
947 DELSYS_INFO( SYS_ISDBC
, "ISDBC" )
948 DELSYS_INFO( SYS_ISDBS
, "ISDBS" )
949 DELSYS_INFO( SYS_ISDBT
, "ISDBT" )
950 DELSYS_INFO( SYS_UNDEFINED
, "UNDEFINED" )
951 #if DVBAPI_VERSION >= 505
952 DELSYS_INFO( SYS_DVBC_ANNEX_A
, "DVBC_ANNEX_A" )
953 DELSYS_INFO( SYS_DVBC_ANNEX_C
, "DVBC_ANNEX_C" )
954 DELSYS_INFO( SYS_DVBT2
, "DVBT2" )
955 DELSYS_INFO( SYS_TURBO
, "TURBO" )
957 DELSYS_INFO( SYS_DVBC_ANNEX_AC
, "DVBC_ANNEX_AC" )
959 #if DVBAPI_VERSION >= 507
960 DELSYS_INFO( SYS_DTMB
, "DTMB" )
962 DELSYS_INFO( SYS_DMBTH
, "DMBTH" )
964 default: msg_Dbg( NULL
, " Unknown delivery system %u", p_systems
[i
]);
970 /*****************************************************************************
972 *****************************************************************************/
974 #if DVBAPI_VERSION >= 505
975 static struct dtv_property info_cmdargs
[] = {
976 { .cmd
= DTV_API_VERSION
, .u
.data
= 0 },
978 static struct dtv_properties info_cmdseq
= {
979 .num
= sizeof(info_cmdargs
)/sizeof(struct dtv_property
),
980 .props
= info_cmdargs
983 static struct dtv_property enum_cmdargs
[] = {
984 { .cmd
= DTV_ENUM_DELSYS
, .u
.data
= 0 },
986 static struct dtv_properties enum_cmdseq
= {
987 .num
= sizeof(enum_cmdargs
)/sizeof(struct dtv_property
),
988 .props
= enum_cmdargs
992 static struct dtv_property dvbs_cmdargs
[] = {
993 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBS
},
994 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
995 { .cmd
= DTV_MODULATION
, .u
.data
= QPSK
},
996 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
997 { .cmd
= DTV_SYMBOL_RATE
, .u
.data
= 27500000 },
998 { .cmd
= DTV_INNER_FEC
, .u
.data
= FEC_AUTO
},
1001 static struct dtv_properties dvbs_cmdseq
= {
1002 .num
= sizeof(dvbs_cmdargs
)/sizeof(struct dtv_property
),
1003 .props
= dvbs_cmdargs
1006 #define IDX_DVBS2_PILOT 6
1007 #define IDX_DVBS2_ROLLOFF 7
1008 #define IDX_DVBS2_STREAM_ID 8
1010 /* Commands 0..5 are the same as dvbs_cmdargs */
1011 /* Commands 6..8 are special for DVB-S2 */
1012 static struct dtv_property dvbs2_cmdargs
[] = {
1013 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBS2
},
1014 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1015 { .cmd
= DTV_MODULATION
, .u
.data
= PSK_8
},
1016 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1017 { .cmd
= DTV_SYMBOL_RATE
, .u
.data
= 27500000 },
1018 { .cmd
= DTV_INNER_FEC
, .u
.data
= FEC_AUTO
},
1019 { .cmd
= DTV_PILOT
, .u
.data
= PILOT_AUTO
}, /* idx: 6 */
1020 { .cmd
= DTV_ROLLOFF
, .u
.data
= ROLLOFF_AUTO
}, /* idx: 7 */
1021 { .cmd
= DTV_STREAM_ID
, .u
.data
= 0 }, /* idx: 8 */
1022 { .cmd
= DTV_TUNE
},
1024 static struct dtv_properties dvbs2_cmdseq
= {
1025 .num
= sizeof(dvbs2_cmdargs
)/sizeof(struct dtv_property
),
1026 .props
= dvbs2_cmdargs
1029 static struct dtv_property dvbc_cmdargs
[] = {
1030 #if DVBAPI_VERSION >= 505
1031 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBC_ANNEX_A
},
1033 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBC_ANNEX_AC
},
1035 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1036 { .cmd
= DTV_MODULATION
, .u
.data
= QAM_AUTO
},
1037 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1038 { .cmd
= DTV_SYMBOL_RATE
, .u
.data
= 27500000 },
1039 { .cmd
= DTV_TUNE
},
1041 static struct dtv_properties dvbc_cmdseq
= {
1042 .num
= sizeof(dvbc_cmdargs
)/sizeof(struct dtv_property
),
1043 .props
= dvbc_cmdargs
1046 static struct dtv_property dvbt_cmdargs
[] = {
1047 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBT
},
1048 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1049 { .cmd
= DTV_MODULATION
, .u
.data
= QAM_AUTO
},
1050 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1051 { .cmd
= DTV_BANDWIDTH_HZ
, .u
.data
= 8000000 },
1052 { .cmd
= DTV_CODE_RATE_HP
, .u
.data
= FEC_AUTO
},
1053 { .cmd
= DTV_CODE_RATE_LP
, .u
.data
= FEC_AUTO
},
1054 { .cmd
= DTV_GUARD_INTERVAL
, .u
.data
= GUARD_INTERVAL_AUTO
},
1055 { .cmd
= DTV_TRANSMISSION_MODE
,.u
.data
= TRANSMISSION_MODE_AUTO
},
1056 { .cmd
= DTV_HIERARCHY
, .u
.data
= HIERARCHY_AUTO
},
1057 { .cmd
= DTV_TUNE
},
1060 static struct dtv_property dvbt2_cmdargs
[] = {
1061 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_DVBT2
},
1062 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1063 { .cmd
= DTV_MODULATION
, .u
.data
= QAM_AUTO
},
1064 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1065 { .cmd
= DTV_BANDWIDTH_HZ
, .u
.data
= 8000000 },
1066 { .cmd
= DTV_CODE_RATE_HP
, .u
.data
= FEC_AUTO
},
1067 { .cmd
= DTV_CODE_RATE_LP
, .u
.data
= FEC_AUTO
},
1068 { .cmd
= DTV_GUARD_INTERVAL
, .u
.data
= GUARD_INTERVAL_AUTO
},
1069 { .cmd
= DTV_TRANSMISSION_MODE
,.u
.data
= TRANSMISSION_MODE_AUTO
},
1070 { .cmd
= DTV_HIERARCHY
, .u
.data
= HIERARCHY_AUTO
},
1071 { .cmd
= DTV_STREAM_ID
, .u
.data
= 0 },
1072 { .cmd
= DTV_TUNE
},
1075 static struct dtv_properties dvbt2_cmdseq
= {
1076 .num
= sizeof(dvbt2_cmdargs
)/sizeof(struct dtv_property
),
1077 .props
= dvbt2_cmdargs
1080 static struct dtv_properties dvbt_cmdseq
= {
1081 .num
= sizeof(dvbt_cmdargs
)/sizeof(struct dtv_property
),
1082 .props
= dvbt_cmdargs
1085 /* ATSC + DVB-C annex B */
1086 static struct dtv_property atsc_cmdargs
[] = {
1087 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_ATSC
},
1088 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1089 { .cmd
= DTV_MODULATION
, .u
.data
= QAM_AUTO
},
1090 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1091 { .cmd
= DTV_TUNE
},
1093 static struct dtv_properties atsc_cmdseq
= {
1094 .num
= sizeof(atsc_cmdargs
)/sizeof(struct dtv_property
),
1095 .props
= atsc_cmdargs
1098 static struct dtv_property isdbt_cmdargs
[] = {
1099 { .cmd
= DTV_DELIVERY_SYSTEM
, .u
.data
= SYS_ISDBT
},
1100 { .cmd
= DTV_FREQUENCY
, .u
.data
= 0 },
1101 { .cmd
= DTV_BANDWIDTH_HZ
, .u
.data
= 6000000 },
1102 { .cmd
= DTV_INVERSION
, .u
.data
= INVERSION_AUTO
},
1103 { .cmd
= DTV_ISDBT_LAYERA_FEC
, .u
.data
= FEC_AUTO
},
1104 { .cmd
= DTV_ISDBT_LAYERA_MODULATION
, .u
.data
= QAM_AUTO
},
1105 { .cmd
= DTV_ISDBT_LAYERA_SEGMENT_COUNT
, .u
.data
= 0 },
1106 { .cmd
= DTV_ISDBT_LAYERA_TIME_INTERLEAVING
,.u
.data
= 0 },
1107 { .cmd
= DTV_ISDBT_LAYERB_FEC
, .u
.data
= FEC_AUTO
},
1108 { .cmd
= DTV_ISDBT_LAYERB_MODULATION
, .u
.data
= QAM_AUTO
},
1109 { .cmd
= DTV_ISDBT_LAYERB_SEGMENT_COUNT
, .u
.data
= 0 },
1110 { .cmd
= DTV_ISDBT_LAYERB_TIME_INTERLEAVING
,.u
.data
= 0 },
1111 { .cmd
= DTV_ISDBT_LAYERC_FEC
, .u
.data
= FEC_AUTO
},
1112 { .cmd
= DTV_ISDBT_LAYERC_MODULATION
, .u
.data
= QAM_AUTO
},
1113 { .cmd
= DTV_ISDBT_LAYERC_SEGMENT_COUNT
, .u
.data
= 0 },
1114 { .cmd
= DTV_ISDBT_LAYERC_TIME_INTERLEAVING
,.u
.data
= 0 },
1115 { .cmd
= DTV_TUNE
},
1118 static struct dtv_properties isdbt_cmdseq
= {
1119 .num
= sizeof(isdbt_cmdargs
)/sizeof(struct dtv_property
),
1120 .props
= isdbt_cmdargs
1125 #define MODULATION 2
1127 #define SYMBOL_RATE 4
1132 #define TRANSMISSION 8
1138 #define ISDBT_BANDWIDTH 2
1139 #define ISDBT_LAYERA_FEC 4
1140 #define ISDBT_LAYERA_MODULATION 5
1141 #define ISDBT_LAYERA_SEGMENT_COUNT 6
1142 #define ISDBT_LAYERA_TIME_INTERLEAVING 7
1143 #define ISDBT_LAYERB_FEC 8
1144 #define ISDBT_LAYERB_MODULATION 9
1145 #define ISDBT_LAYERB_SEGMENT_COUNT 10
1146 #define ISDBT_LAYERB_TIME_INTERLEAVING 11
1147 #define ISDBT_LAYERC_FEC 12
1148 #define ISDBT_LAYERC_MODULATION 13
1149 #define ISDBT_LAYERC_SEGMENT_COUNT 14
1150 #define ISDBT_LAYERC_TIME_INTERLEAVING 15
1152 struct dtv_property pclear
[] = {
1153 { .cmd
= DTV_CLEAR
},
1156 struct dtv_properties cmdclear
= {
1161 static fe_delivery_system_t
1162 FrontendGuessSystem( fe_delivery_system_t
*p_systems
, int i_systems
)
1164 if ( psz_delsys
!= NULL
)
1166 if ( !strcasecmp( psz_delsys
, "DVBS" ) )
1168 if ( !strcasecmp( psz_delsys
, "DVBS2" ) )
1170 if ( !strcasecmp( psz_delsys
, "DVBC_ANNEX_A" ) )
1171 #if DVBAPI_VERSION >= 505
1172 return SYS_DVBC_ANNEX_A
;
1174 return SYS_DVBC_ANNEX_AC
;
1176 if ( !strcasecmp( psz_delsys
, "DVBC_ANNEX_B" ) )
1177 return SYS_DVBC_ANNEX_B
;
1178 if ( !strcasecmp( psz_delsys
, "DVBT" ) )
1180 if ( !strcasecmp( psz_delsys
, "DVBT2" ) )
1182 if ( !strcasecmp( psz_delsys
, "ATSC" ) )
1184 if ( !strcasecmp( psz_delsys
, "ISDBT" ) )
1186 msg_Err( NULL
, "unknown delivery system %s", psz_delsys
);
1190 if ( i_systems
== 1 )
1191 return p_systems
[0];
1194 for ( i
= 0; i
< i_systems
; i
++ )
1196 switch ( p_systems
[i
] )
1199 if ( i_frequency
< 50000000 )
1202 #if DVBAPI_VERSION >= 505
1203 case SYS_DVBC_ANNEX_A
:
1204 if ( i_frequency
> 50000000 || i_srate
!= 27500000 ||
1205 psz_modulation
!= NULL
)
1206 return SYS_DVBC_ANNEX_A
;
1209 case SYS_DVBC_ANNEX_AC
:
1210 if ( i_frequency
> 50000000 || i_srate
!= 27500000 ||
1211 psz_modulation
!= NULL
)
1212 return SYS_DVBC_ANNEX_AC
;
1216 if ( i_frequency
> 50000000 )
1220 if ( i_frequency
> 50000000 && (dvb_plp_id
) )
1228 msg_Warn( NULL
, "couldn't guess delivery system, use --delsys" );
1229 return p_systems
[0];
1232 static void FrontendSet( bool b_init
)
1234 struct dvb_frontend_info info
;
1235 struct dtv_properties
*p
;
1236 fe_delivery_system_t p_systems
[MAX_DELIVERY_SYSTEMS
] = { 0 };
1239 if ( ioctl( i_frontend
, FE_GET_INFO
, &info
) < 0 )
1241 msg_Err( NULL
, "FE_GET_INFO failed (%s)", strerror(errno
) );
1245 uint32_t version
= 0x300;
1246 #if DVBAPI_VERSION >= 505
1247 if ( ioctl( i_frontend
, FE_GET_PROPERTY
, &info_cmdseq
) < 0 )
1251 switch ( info
.type
)
1254 p_systems
[i_systems
++] = SYS_DVBT
;
1255 #if DVBAPI_VERSION >= 505
1256 if ( info
.caps
& FE_CAN_2G_MODULATION
)
1257 p_systems
[i_systems
++] = SYS_DVBT2
;
1261 #if DVBAPI_VERSION >= 505
1262 p_systems
[i_systems
++] = SYS_DVBC_ANNEX_A
;
1264 p_systems
[i_systems
++] = SYS_DVBC_ANNEX_AC
;
1268 p_systems
[i_systems
++] = SYS_DVBS
;
1269 if ( info
.caps
& FE_CAN_2G_MODULATION
)
1270 p_systems
[i_systems
++] = SYS_DVBS2
;
1273 if ( info
.caps
& (FE_CAN_8VSB
| FE_CAN_16VSB
) )
1274 p_systems
[i_systems
++] = SYS_ATSC
;
1275 if ( info
.caps
& (FE_CAN_QAM_64
| FE_CAN_QAM_256
| FE_CAN_QAM_AUTO
) )
1276 p_systems
[i_systems
++] = SYS_DVBC_ANNEX_B
;
1279 msg_Err( NULL
, "unknown frontend type %d", info
.type
);
1282 #if DVBAPI_VERSION >= 505
1286 version
= info_cmdargs
[0].u
.data
;
1287 if ( ioctl( i_frontend
, FE_GET_PROPERTY
, &enum_cmdseq
) < 0 )
1289 msg_Err( NULL
, "unable to query frontend" );
1292 i_systems
= enum_cmdargs
[0].u
.buffer
.len
;
1293 if ( i_systems
< 1 )
1295 msg_Err( NULL
, "no available delivery system" );
1300 for ( i
= 0; i
< i_systems
; i
++ )
1301 p_systems
[i
] = enum_cmdargs
[0].u
.buffer
.data
[i
];
1306 FrontendInfo( &info
, version
, p_systems
, i_systems
);
1308 /* Clear frontend commands */
1309 if ( ioctl( i_frontend
, FE_SET_PROPERTY
, &cmdclear
) < 0 )
1311 msg_Err( NULL
, "Unable to clear frontend" );
1315 fe_delivery_system_t system
= FrontendGuessSystem( p_systems
, i_systems
);
1320 p
->props
[DELSYS
].u
.data
= system
;
1321 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1322 p
->props
[INVERSION
].u
.data
= GetInversion();
1323 if ( psz_modulation
!= NULL
)
1324 p
->props
[MODULATION
].u
.data
= GetModulation();
1325 p
->props
[BANDWIDTH
].u
.data
= i_bandwidth
* 1000000;
1326 p
->props
[FEC_INNER
].u
.data
= GetFECInner(info
.caps
);
1327 p
->props
[FEC_LP
].u
.data
= GetFECLP(info
.caps
);
1328 p
->props
[GUARD
].u
.data
= GetGuard();
1329 p
->props
[TRANSMISSION
].u
.data
= GetTransmission();
1330 p
->props
[HIERARCHY
].u
.data
= GetHierarchy();
1332 msg_Dbg( NULL
, "tuning DVB-T frontend to f=%d bandwidth=%d inversion=%d fec_hp=%d fec_lp=%d hierarchy=%d modulation=%s guard=%d transmission=%d",
1333 i_frequency
, i_bandwidth
, i_inversion
, i_fec
, i_fec_lp
,
1335 psz_modulation
== NULL
? "qam_auto" : psz_modulation
,
1336 i_guard
, i_transmission
);
1340 p
->props
[DELSYS
].u
.data
= system
;
1341 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1342 p
->props
[INVERSION
].u
.data
= GetInversion();
1343 if ( psz_modulation
!= NULL
)
1344 p
->props
[MODULATION
].u
.data
= GetModulation();
1345 p
->props
[BANDWIDTH
].u
.data
= i_bandwidth
* 1000000;
1346 p
->props
[FEC_INNER
].u
.data
= GetFECInner(info
.caps
);
1347 p
->props
[FEC_LP
].u
.data
= GetFECLP(info
.caps
);
1348 p
->props
[GUARD
].u
.data
= GetGuard();
1349 p
->props
[TRANSMISSION
].u
.data
= GetTransmission();
1350 p
->props
[HIERARCHY
].u
.data
= GetHierarchy();
1351 p
->props
[PLP_ID
].u
.data
= dvb_plp_id
;
1353 msg_Dbg( NULL
, "tuning DVB-T2 frontend to f=%d bandwidth=%d inversion=%d fec_hp=%d fec_lp=%d hierarchy=%d modulation=%s guard=%d transmission=%d PLP_ID=%d ",
1354 i_frequency
, i_bandwidth
, i_inversion
, i_fec
, i_fec_lp
,
1356 psz_modulation
== NULL
? "qam_auto" : psz_modulation
,
1357 i_guard
, i_transmission
, p
->props
[PLP_ID
].u
.data
);
1359 #if DVBAPI_VERSION >= 505
1360 case SYS_DVBC_ANNEX_A
:
1362 case SYS_DVBC_ANNEX_AC
:
1365 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1366 p
->props
[INVERSION
].u
.data
= GetInversion();
1367 if ( psz_modulation
!= NULL
)
1368 p
->props
[MODULATION
].u
.data
= GetModulation();
1369 p
->props
[SYMBOL_RATE
].u
.data
= i_srate
;
1371 msg_Dbg( NULL
, "tuning DVB-C frontend to f=%d srate=%d inversion=%d modulation=%s",
1372 i_frequency
, i_srate
, i_inversion
,
1373 psz_modulation
== NULL
? "qam_auto" : psz_modulation
);
1376 case SYS_DVBC_ANNEX_B
:
1378 p
->props
[DELSYS
].u
.data
= system
;
1379 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1380 p
->props
[INVERSION
].u
.data
= GetInversion();
1381 if ( psz_modulation
!= NULL
)
1382 p
->props
[MODULATION
].u
.data
= GetModulation();
1384 msg_Dbg( NULL
, "tuning ATSC cable frontend to f=%d inversion=%d modulation=%s",
1385 i_frequency
, i_inversion
,
1386 psz_modulation
== NULL
? "qam_auto" : psz_modulation
);
1391 if ( psz_modulation
!= NULL
)
1394 p
->props
[MODULATION
].u
.data
= GetModulation();
1395 p
->props
[IDX_DVBS2_PILOT
].u
.data
= GetPilot();
1396 p
->props
[IDX_DVBS2_ROLLOFF
].u
.data
= GetRollOff();
1397 p
->props
[IDX_DVBS2_STREAM_ID
].u
.data
= i_mis
;
1402 p
->props
[INVERSION
].u
.data
= GetInversion();
1403 p
->props
[SYMBOL_RATE
].u
.data
= i_srate
;
1404 p
->props
[FEC_INNER
].u
.data
= GetFECInner(info
.caps
);
1405 p
->props
[FREQUENCY
].u
.data
= FrontendDoDiseqc();
1407 msg_Dbg( NULL
, "tuning DVB-S frontend to f=%d srate=%d inversion=%d fec=%d rolloff=%d modulation=%s pilot=%d mis=%d /pls-mode: %s (%d) pls-code: %d is-id: %d /",
1408 i_frequency
, i_srate
, i_inversion
, i_fec
, i_rolloff
,
1409 psz_modulation
== NULL
? "legacy" : psz_modulation
, i_pilot
,
1410 i_mis
, psz_mis_pls_mode
, i_mis_pls_mode
, i_mis_pls_code
, i_mis_is_id
);
1415 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1416 p
->props
[INVERSION
].u
.data
= GetInversion();
1417 if ( psz_modulation
!= NULL
)
1418 p
->props
[MODULATION
].u
.data
= GetModulation();
1420 msg_Dbg( NULL
, "tuning ATSC frontend to f=%d inversion=%d modulation=%s",
1421 i_frequency
, i_inversion
,
1422 psz_modulation
== NULL
? "qam_auto" : psz_modulation
);
1426 p
->props
[DELSYS
].u
.data
= system
;
1427 p
->props
[FREQUENCY
].u
.data
= i_frequency
;
1428 p
->props
[ISDBT_BANDWIDTH
].u
.data
= i_bandwidth
* 1000000;
1429 p
->props
[INVERSION
].u
.data
= GetInversion();
1430 p
->props
[ISDBT_LAYERA_FEC
].u
.data
= FEC_AUTO
;
1431 p
->props
[ISDBT_LAYERA_MODULATION
].u
.data
= QAM_AUTO
;
1432 p
->props
[ISDBT_LAYERA_SEGMENT_COUNT
].u
.data
= 0;
1433 p
->props
[ISDBT_LAYERA_TIME_INTERLEAVING
].u
.data
= 0;
1434 p
->props
[ISDBT_LAYERB_FEC
].u
.data
= FEC_AUTO
;
1435 p
->props
[ISDBT_LAYERB_MODULATION
].u
.data
= QAM_AUTO
;
1436 p
->props
[ISDBT_LAYERB_SEGMENT_COUNT
].u
.data
= 0;
1437 p
->props
[ISDBT_LAYERB_TIME_INTERLEAVING
].u
.data
= 0;
1438 p
->props
[ISDBT_LAYERC_FEC
].u
.data
= FEC_AUTO
;
1439 p
->props
[ISDBT_LAYERC_MODULATION
].u
.data
= QAM_AUTO
;
1440 p
->props
[ISDBT_LAYERC_SEGMENT_COUNT
].u
.data
= 0;
1441 p
->props
[ISDBT_LAYERC_TIME_INTERLEAVING
].u
.data
= 0;
1443 msg_Dbg( NULL
, "tuning ISDB-T frontend to f=%d bandwidth=%d ",
1444 i_frequency
, i_bandwidth
);
1448 msg_Err( NULL
, "unknown frontend type %d", info
.type
);
1452 /* Empty the event queue */
1455 struct dvb_frontend_event event
;
1456 if ( ioctl( i_frontend
, FE_GET_EVENT
, &event
) < 0
1457 && errno
== EWOULDBLOCK
)
1461 /* Now send it all to the frontend device */
1462 if ( ioctl( i_frontend
, FE_SET_PROPERTY
, p
) < 0 )
1464 msg_Err( NULL
, "setting frontend failed (%s)", strerror(errno
) );
1470 if (i_frontend_timeout_duration
)
1471 ev_timer_again(event_loop
, &lock_watcher
);
1476 #warning "You are trying to compile DVBlast with an outdated linux-dvb interface."
1477 #warning "DVBlast will be very limited and some options will have no effect."
1479 static void FrontendSet( bool b_init
)
1481 struct dvb_frontend_info info
;
1482 struct dvb_frontend_parameters fep
;
1484 if ( ioctl( i_frontend
, FE_GET_INFO
, &info
) < 0 )
1486 msg_Err( NULL
, "FE_GET_INFO failed (%s)", strerror(errno
) );
1490 switch ( info
.type
)
1493 fep
.frequency
= i_frequency
;
1494 fep
.inversion
= INVERSION_AUTO
;
1496 switch ( i_bandwidth
)
1498 case 6: fep
.u
.ofdm
.bandwidth
= BANDWIDTH_6_MHZ
; break;
1499 case 7: fep
.u
.ofdm
.bandwidth
= BANDWIDTH_7_MHZ
; break;
1501 case 8: fep
.u
.ofdm
.bandwidth
= BANDWIDTH_8_MHZ
; break;
1504 fep
.u
.ofdm
.code_rate_HP
= FEC_AUTO
;
1505 fep
.u
.ofdm
.code_rate_LP
= FEC_AUTO
;
1506 fep
.u
.ofdm
.constellation
= QAM_AUTO
;
1507 fep
.u
.ofdm
.transmission_mode
= TRANSMISSION_MODE_AUTO
;
1508 fep
.u
.ofdm
.guard_interval
= GUARD_INTERVAL_AUTO
;
1509 fep
.u
.ofdm
.hierarchy_information
= HIERARCHY_AUTO
;
1511 msg_Dbg( NULL
, "tuning OFDM frontend to f=%d, bandwidth=%d",
1512 i_frequency
, i_bandwidth
);
1516 fep
.frequency
= i_frequency
;
1517 fep
.inversion
= INVERSION_AUTO
;
1518 fep
.u
.qam
.symbol_rate
= i_srate
;
1519 fep
.u
.qam
.fec_inner
= FEC_AUTO
;
1520 fep
.u
.qam
.modulation
= QAM_AUTO
;
1522 msg_Dbg( NULL
, "tuning QAM frontend to f=%d, srate=%d",
1523 i_frequency
, i_srate
);
1527 fep
.inversion
= INVERSION_AUTO
;
1528 fep
.u
.qpsk
.symbol_rate
= i_srate
;
1529 fep
.u
.qpsk
.fec_inner
= FEC_AUTO
;
1530 fep
.frequency
= FrontendDoDiseqc();
1532 msg_Dbg( NULL
, "tuning QPSK frontend to f=%d, srate=%d",
1533 i_frequency
, i_srate
);
1536 #if DVBAPI_VERSION >= 301
1538 fep
.frequency
= i_frequency
;
1540 fep
.u
.vsb
.modulation
= QAM_AUTO
;
1542 msg_Dbg( NULL
, "tuning ATSC frontend to f=%d", i_frequency
);
1547 msg_Err( NULL
, "unknown frontend type %d", info
.type
);
1551 /* Empty the event queue */
1554 struct dvb_frontend_event event
;
1555 if ( ioctl( i_frontend
, FE_GET_EVENT
, &event
) < 0
1556 && errno
== EWOULDBLOCK
)
1560 /* Now send it all to the frontend device */
1561 if ( ioctl( i_frontend
, FE_SET_FRONTEND
, &fep
) < 0 )
1563 msg_Err( NULL
, "setting frontend failed (%s)", strerror(errno
) );
1569 if (i_frontend_timeout_duration
)
1570 ev_timer_again(event_loop
, &lock_watcher
);
1575 /*****************************************************************************
1576 * dvb_FrontendStatus
1577 *****************************************************************************/
1578 uint8_t dvb_FrontendStatus( uint8_t *p_answer
, ssize_t
*pi_size
)
1580 struct ret_frontend_status
*p_ret
= (struct ret_frontend_status
*)p_answer
;
1582 if ( ioctl( i_frontend
, FE_GET_INFO
, &p_ret
->info
) < 0 )
1584 msg_Err( NULL
, "ioctl FE_GET_INFO failed (%s)", strerror(errno
) );
1588 if ( ioctl( i_frontend
, FE_READ_STATUS
, &p_ret
->i_status
) < 0 )
1590 msg_Err( NULL
, "ioctl FE_READ_STATUS failed (%s)", strerror(errno
) );
1594 if ( p_ret
->i_status
& FE_HAS_LOCK
)
1596 if ( ioctl( i_frontend
, FE_READ_BER
, &p_ret
->i_ber
) < 0 )
1597 msg_Err( NULL
, "ioctl FE_READ_BER failed (%s)", strerror(errno
) );
1599 if ( ioctl( i_frontend
, FE_READ_SIGNAL_STRENGTH
, &p_ret
->i_strength
)
1601 msg_Err( NULL
, "ioctl FE_READ_SIGNAL_STRENGTH failed (%s)",
1604 if ( ioctl( i_frontend
, FE_READ_SNR
, &p_ret
->i_snr
) < 0 )
1605 msg_Err( NULL
, "ioctl FE_READ_SNR failed (%s)", strerror(errno
) );
1608 *pi_size
= sizeof(struct ret_frontend_status
);
1609 return RET_FRONTEND_STATUS
;