Commit 9e0f8b24 authored by massiot's avatar massiot

* asi.c, asi.h: Support for Computer Modules ASI input cards (-A).


git-svn-id: svn://svn.videolan.org/dvblast/trunk@86 55d3f8b6-4a41-4d2d-a900-313d1436a5b8
parent e286f26c
......@@ -7,12 +7,12 @@ CFLAGS += -I/usr/src/kernel/linux-2.6.29.1/include
LDFLAGS += -lrt
LDFLAGS_DVBLAST += -ldvbpsi -lpthread
OBJ_DVBLAST = dvblast.o util.o dvb.o udp.o demux.o output.o en50221.o comm.o
OBJ_DVBLAST = dvblast.o util.o dvb.o udp.o asi.o demux.o output.o en50221.o comm.o
OBJ_DVBLASTCTL = util.o dvblastctl.o
all: dvblast dvblastctl
$(OBJ_DVBLAST) $(OBJ_DVBLASTCTL): Makefile dvblast.h en50221.h comm.h version.h
$(OBJ_DVBLAST) $(OBJ_DVBLASTCTL): Makefile dvblast.h en50221.h comm.h version.h asi.h
dvblast: $(OBJ_DVBLAST)
$(CC) -o $@ $(OBJ_DVBLAST) $(LDFLAGS_DVBLAST) $(LDFLAGS)
......
/*****************************************************************************
* asi.c: support for Computer Modules ASI cards
*****************************************************************************
* Copyright (C) 2004, 2009 VideoLAN
* $Id: asi.c 9 2007-03-15 16:58:05Z cmassiot $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include "asi.h"
#include "dvblast.h"
/*
* The problem with hardware filtering is that on startup, when you only
* set a filter on PID 0, it can take a very long time for a large buffer
* (typically ~100 TS packets) to fill up. And the buffer size cannot be
* adjusted afer startup. --Meuuh
*/
#undef USE_HARDWARE_FILTERING
/*****************************************************************************
* Local declarations
*****************************************************************************/
#define ASI_DEVICE "/dev/asirx%u"
#define ASI_TIMESTAMPS_FILE "/sys/class/asi/asirx%u/timestamps"
#define ASI_BUFSIZE_FILE "/sys/class/asi/asirx%u/bufsize"
static int i_handle;
static int i_bufsize;
static uint8_t p_pid_filter[8192 / 8];
/*****************************************************************************
* Local helpers
*****************************************************************************/
#define MAXLEN 256
static int ReadULSysfs( const char *psz_fmt, unsigned int i_link )
{
char psz_file[MAXLEN], psz_data[MAXLEN];
char *psz_tmp;
int i_fd;
ssize_t i_ret;
unsigned int i_data;
snprintf( psz_file, sizeof(psz_file), psz_fmt, i_link );
psz_file[sizeof(psz_file) - 1] = '\0';
if ( (i_fd = open( psz_file, O_RDONLY )) < 0 )
return i_fd;
i_ret = read( i_fd, psz_data, sizeof(psz_data) );
close( i_fd );
if ( i_ret < 0 )
return i_ret;
i_data = strtoul( psz_data, &psz_tmp, 0 );
if ( *psz_tmp != '\n' )
return -1;
return i_data;
}
static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
unsigned int i_buf )
{
char psz_file[MAXLEN], psz_data[MAXLEN];
int i_fd;
ssize_t i_ret;
snprintf( psz_file, sizeof(psz_file), psz_fmt, i_link );
psz_file[sizeof(psz_file) - 1] = '\0';
snprintf( psz_data, sizeof(psz_data), "%u\n", i_buf );
psz_file[sizeof(psz_data) - 1] = '\0';
if ( (i_fd = open( psz_file, O_WRONLY )) < 0 )
return i_fd;
i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
close( i_fd );
return i_ret;
}
/*****************************************************************************
* asi_Open
*****************************************************************************/
void asi_Open( void )
{
char psz_dev[MAXLEN];
/* No timestamp - we wouldn't know what to do with them */
if ( WriteULSysfs( ASI_TIMESTAMPS_FILE, i_asi_adapter, 0 ) < 0 )
{
msg_Err( NULL, "couldn't write file " ASI_TIMESTAMPS_FILE,
i_asi_adapter );
exit(EXIT_FAILURE);
}
if ( (i_bufsize = ReadULSysfs( ASI_BUFSIZE_FILE, i_asi_adapter )) < 0 )
{
msg_Err( NULL, "couldn't read file " ASI_BUFSIZE_FILE, i_asi_adapter );
exit(EXIT_FAILURE);
}
if ( i_bufsize % TS_SIZE )
{
msg_Err( NULL, ASI_BUFSIZE_FILE " must be a multiple of 188",
i_asi_adapter );
exit(EXIT_FAILURE);
}
snprintf( psz_dev, sizeof(psz_dev), ASI_DEVICE, i_asi_adapter );
psz_dev[sizeof(psz_dev) - 1] = '\0';
if ( (i_handle = open( psz_dev, O_RDONLY, 0 )) < 0 )
{
msg_Err( NULL, "couldn't open device " ASI_DEVICE " (%s)",
i_asi_adapter, strerror(errno) );
exit(EXIT_FAILURE);
}
#ifdef USE_HARDWARE_FILTERING
memset( p_pid_filter, 0x0, sizeof(p_pid_filter) );
#else
memset( p_pid_filter, 0xff, sizeof(p_pid_filter) );
p_pid_filter[8191 / 8] &= ~(0x01 << (8191 % 8)); /* padding */
#endif
if ( ioctl( i_handle, ASI_IOC_RXSETPF, p_pid_filter ) < 0 )
{
msg_Warn( NULL, "couldn't filter padding" );
}
fsync( i_handle );
}
/*****************************************************************************
* asi_Read : read packets from the device
*****************************************************************************/
block_t *asi_Read( void )
{
int i, i_len;
struct iovec p_iov[i_bufsize / TS_SIZE];
block_t *p_ts, **pp_current = &p_ts;
for ( ; ; )
{
struct pollfd pfd;
pfd.fd = i_handle;
pfd.events = POLLIN | POLLPRI;
if ( poll(&pfd, 1, -1) < 0 )
{
msg_Err( NULL, "couldn't poll from device " ASI_DEVICE " (%s)",
i_asi_adapter, strerror(errno) );
continue;
}
if ( (pfd.revents & POLLPRI) )
{
unsigned int i_val;
if ( ioctl(i_handle, ASI_IOC_RXGETEVENTS, &i_val) < 0 )
msg_Err( NULL, "couldn't RXGETEVENTS (%s)", strerror(errno) );
else
{
if ( i_val & ASI_EVENT_RX_BUFFER )
msg_Warn( NULL, "driver receive buffer queue overrun" );
if ( i_val & ASI_EVENT_RX_FIFO )
msg_Warn( NULL, "onboard receive FIFO overrun" );
if ( i_val & ASI_EVENT_RX_CARRIER )
msg_Warn( NULL, "carrier status change" );
if ( i_val & ASI_EVENT_RX_LOS )
msg_Warn( NULL, "loss of packet synchronization" );
if ( i_val & ASI_EVENT_RX_AOS )
msg_Warn( NULL, "acquisition of packet synchronization" );
if ( i_val & ASI_EVENT_RX_DATA )
msg_Warn( NULL, "receive data status change" );
}
}
if ( (pfd.revents & POLLIN) )
break;
}
for ( i = 0; i < i_bufsize / TS_SIZE; i++ )
{
*pp_current = block_New();
p_iov[i].iov_base = (*pp_current)->p_ts;
p_iov[i].iov_len = TS_SIZE;
pp_current = &(*pp_current)->p_next;
}
if ( (i_len = readv(i_handle, p_iov, i_bufsize / TS_SIZE)) < 0 )
{
msg_Err( NULL, "couldn't read from device " ASI_DEVICE " (%s)",
i_asi_adapter, strerror(errno) );
i_len = 0;
}
i_len /= TS_SIZE;
pp_current = &p_ts;
while ( i_len && *pp_current )
{
pp_current = &(*pp_current)->p_next;
i_len--;
}
if ( *pp_current )
msg_Dbg( NULL, "partial buffer received" );
block_DeleteChain( *pp_current );
*pp_current = NULL;
return p_ts;
}
/*****************************************************************************
* asi_SetFilter
*****************************************************************************/
int asi_SetFilter( uint16_t i_pid )
{
#ifdef USE_HARDWARE_FILTERING
p_pid_filter[ i_pid / 8 ] |= (0x01 << (i_pid % 8));
if ( ioctl( i_handle, ASI_IOC_RXSETPF, p_pid_filter ) < 0 )
msg_Warn( NULL, "couldn't add filter on PID %u", i_pid );
return 1;
#else
return -1;
#endif
}
/*****************************************************************************
* asi_UnsetFilter: normally never called
*****************************************************************************/
void asi_UnsetFilter( int i_fd, uint16_t i_pid )
{
#ifdef USE_HARDWARE_FILTERING
p_pid_filter[ i_pid / 8 ] &= ~(0x01 << (i_pid % 8));
if ( ioctl( i_handle, ASI_IOC_RXSETPF, p_pid_filter ) < 0 )
msg_Warn( NULL, "couldn't remove filter on PID %u", i_pid );
#endif
}
/* asi.h
*
* Shared header file for the Linux user-space API for
* Linear Systems Ltd. DVB Master ASI interface boards.
*
* Copyright (C) 1999 Tony Bolger <d7v@indigo.ie>
* Copyright (C) 2000-2008 Linear Systems Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Linear Systems Ltd. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY LINEAR SYSTEMS LTD. "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL LINEAR SYSTEMS LTD. OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Linear Systems can be contacted at <http://www.linsys.ca/>.
*
*/
#ifndef _ASI_H
#define _ASI_H
/* Driver info */
#define ASI_DRIVER_NAME "asi"
#define ASI_MAJOR 61 /* Set to 0 for dynamic allocation.
* Otherwise, 61 is available.
* See /usr/src/linux/Documentation/devices.txt */
#define ASI_TX_BUFFERS_MIN 2 /* This must be at least 2 */
/* The minimum transmit buffer size must be positive, divisible by 8,
* and large enough that the buffers aren't transferred to the onboard FIFOs
* too quickly for the machine to handle the interrupts.
* This is especially a problem at startup, when the FIFOs are empty.
* Relevant factors include onboard FIFO size, PCI bus throughput,
* processor speed, and interrupt latency. */
#define ASI_TX_BUFSIZE_MIN 1024
#define ASI_RX_BUFFERS_MIN 2 /* This must be at least 2 */
#define ASI_RX_BUFSIZE_MIN 8 /* This must be positive and divisible by 8 */
#define ASI_TX_BUFFERS 54 /* This must be at least 2 */
#define ASI_TX_BUFSIZE 38352 /* This must be positive and divisible by 8 */
#define ASI_RX_BUFFERS 54 /* This must be at least 2 */
#define ASI_RX_BUFSIZE 38352 /* This must be positive and divisible by 8 */
/* Ioctl () definitions */
#define ASI_IOC_MAGIC '?' /* This ioctl magic number is currently free. See
* /usr/src/linux/Documentation/ioctl-number.txt */
#define ASI_IOC_TXGETCAP _IOR(ASI_IOC_MAGIC, 1, unsigned int)
#define ASI_IOC_TXGETEVENTS _IOR(ASI_IOC_MAGIC, 2, unsigned int)
#define ASI_IOC_TXGETBUFLEVEL _IOR(ASI_IOC_MAGIC, 3, unsigned int)
#define ASI_IOC_TXSETSTUFFING _IOW(ASI_IOC_MAGIC, 4, struct asi_txstuffing)
#define ASI_IOC_TXGETBYTECOUNT _IOR(ASI_IOC_MAGIC, 5, unsigned int)
/* #define ASI_IOC_TXGETFIFO _IOR(ASI_IOC_MAGIC, 6, int) */
#define ASI_IOC_TXGETTXD _IOR(ASI_IOC_MAGIC, 7, int)
#define ASI_IOC_TXGET27COUNT _IOR(ASI_IOC_MAGIC, 8, unsigned int)
#define ASI_IOC_TXSETPID _IOR(ASI_IOC_MAGIC, 9, unsigned int)
#define ASI_IOC_TXGETPCRSTAMP _IOR(ASI_IOC_MAGIC, 10, struct asi_pcrstamp)
#define ASI_IOC_TXCHANGENEXTIP _IOR(ASI_IOC_MAGIC, 11, int)
#define ASI_IOC_RXGETCAP _IOR(ASI_IOC_MAGIC, 65, unsigned int)
#define ASI_IOC_RXGETEVENTS _IOR(ASI_IOC_MAGIC, 66, unsigned int)
#define ASI_IOC_RXGETBUFLEVEL _IOR(ASI_IOC_MAGIC, 67, unsigned int)
/* #define ASI_IOC_RXSETREFRAME _IOW(ASI_IOC_MAGIC, 68, int) */
#define ASI_IOC_RXGETSTATUS _IOR(ASI_IOC_MAGIC, 69, int)
#define ASI_IOC_RXGETBYTECOUNT _IOR(ASI_IOC_MAGIC, 70, unsigned int)
/* #define ASI_IOC_RXGETFIFO _IOR(ASI_IOC_MAGIC, 71, int) */
#define ASI_IOC_RXSETINVSYNC _IOW(ASI_IOC_MAGIC, 72, int)
#define ASI_IOC_RXGETCARRIER _IOR(ASI_IOC_MAGIC, 73, int)
#define ASI_IOC_RXSETDSYNC _IOW(ASI_IOC_MAGIC, 74, int)
#define ASI_IOC_RXGETRXD _IOR(ASI_IOC_MAGIC, 75, int)
#define ASI_IOC_RXSETPF _IOW(ASI_IOC_MAGIC, 76, unsigned int [256])
/* #define ASI_IOC_RXSETPFE _IOW(ASI_IOC_MAGIC, 77, int) */
#define ASI_IOC_RXSETPID0 _IOW(ASI_IOC_MAGIC, 78, int)
#define ASI_IOC_RXGETPID0COUNT _IOR(ASI_IOC_MAGIC, 79, unsigned int)
#define ASI_IOC_RXSETPID1 _IOW(ASI_IOC_MAGIC, 80, int)
#define ASI_IOC_RXGETPID1COUNT _IOR(ASI_IOC_MAGIC, 81, unsigned int)
#define ASI_IOC_RXSETPID2 _IOW(ASI_IOC_MAGIC, 82, int)
#define ASI_IOC_RXGETPID2COUNT _IOR(ASI_IOC_MAGIC, 83, unsigned int)
#define ASI_IOC_RXSETPID3 _IOW(ASI_IOC_MAGIC, 84, int)
#define ASI_IOC_RXGETPID3COUNT _IOR(ASI_IOC_MAGIC, 85, unsigned int)
/* #define ASI_IOC_RXGETSTAMP _IOR(ASI_IOC_MAGIC, 86, unsigned int) */
#define ASI_IOC_RXGET27COUNT _IOR(ASI_IOC_MAGIC, 87, unsigned int)
#define ASI_IOC_RXGETSTATUS2 _IOR(ASI_IOC_MAGIC, 88, int)
#define ASI_IOC_RXSETINPUT _IOR(ASI_IOC_MAGIC, 89, int)
#define ASI_IOC_RXGETRXD2 _IOR(ASI_IOC_MAGIC, 90, int)
#define ASI_IOC_GETID _IOR(ASI_IOC_MAGIC, 129, unsigned int)
#define ASI_IOC_GETVERSION _IOR(ASI_IOC_MAGIC, 130, unsigned int)
/* Transmitter event flag bit locations */
#define ASI_EVENT_TX_BUFFER_ORDER 0
#define ASI_EVENT_TX_BUFFER (1 << ASI_EVENT_TX_BUFFER_ORDER)
#define ASI_EVENT_TX_FIFO_ORDER 1
#define ASI_EVENT_TX_FIFO (1 << ASI_EVENT_TX_FIFO_ORDER)
#define ASI_EVENT_TX_DATA_ORDER 2
#define ASI_EVENT_TX_DATA (1 << ASI_EVENT_TX_DATA_ORDER)
/* Receiver event flag bit locations */
#define ASI_EVENT_RX_BUFFER_ORDER 0
#define ASI_EVENT_RX_BUFFER (1 << ASI_EVENT_RX_BUFFER_ORDER)
#define ASI_EVENT_RX_FIFO_ORDER 1
#define ASI_EVENT_RX_FIFO (1 << ASI_EVENT_RX_FIFO_ORDER)
#define ASI_EVENT_RX_CARRIER_ORDER 2
#define ASI_EVENT_RX_CARRIER (1 << ASI_EVENT_RX_CARRIER_ORDER)
#define ASI_EVENT_RX_AOS_ORDER 3
#define ASI_EVENT_RX_AOS (1 << ASI_EVENT_RX_AOS_ORDER)
#define ASI_EVENT_RX_LOS_ORDER 4
#define ASI_EVENT_RX_LOS (1 << ASI_EVENT_RX_LOS_ORDER)
#define ASI_EVENT_RX_DATA_ORDER 5
#define ASI_EVENT_RX_DATA (1 << ASI_EVENT_RX_DATA_ORDER)
/**
* asi_txstuffing - Transmitter stuffing parameters
* @ib: interbyte stuffing
* @ip: interpacket stuffing
* @normal_ip: FT0
* @big_ip: FT1
* @il_normal: IL0
* @il_big: IL1
**/
struct asi_txstuffing {
/* Number of K28.5 characters to insert between packet bytes */
unsigned int ib;
/* Base number of K28.5 characters to insert between packets,
* not including the two required by ASI */
unsigned int ip;
/* Number of packets with (ip) bytes of interpacket stuffing
* per finetuning cycle */
unsigned int normal_ip;
/* Number of packets with (ip + 1) bytes of interpacket stuffing
* per finetuning cycle */
unsigned int big_ip;
/* Number of packets with (ip) bytes of interpacket stuffing
* per interleaved finetuning cycle */
unsigned int il_normal;
/* Number of packets with (ip + 1) bytes of interpacket stuffing
* per interleaved finetuning cycle */
unsigned int il_big;
};
/**
* asi_pcrstamp - PCR - departure time pair
* @adaptation_field_length: adaptation field length
* @adaptation_field_flags: adaptation field flags
* @PCR: a program clock reference
* @count: departure time of this PCR, in 1 / 27 MHz
**/
struct asi_pcrstamp {
unsigned char adaptation_field_length;
unsigned char adaptation_field_flags;
unsigned char PCR[6];
long long int count;
};
/* Interface capabilities */
#define ASI_CAP_TX_MAKE204 0x00000004
#define ASI_CAP_TX_FINETUNING 0x00000008
#define ASI_CAP_TX_BYTECOUNTER 0x00000010
#define ASI_CAP_TX_SETCLKSRC 0x00000020
#define ASI_CAP_TX_FIFOUNDERRUN 0x00000040
#define ASI_CAP_TX_LARGEIB 0x00000080
#define ASI_CAP_TX_INTERLEAVING 0x00000100
#define ASI_CAP_TX_DATA 0x00000200
#define ASI_CAP_TX_RXCLKSRC 0x00000400
/* #define ASI_CAP_TX_COMPOSITEREF 0x00000800 */
#define ASI_CAP_TX_PCRSTAMP 0x00001000
#define ASI_CAP_TX_CHANGENEXTIP 0x00002000
#define ASI_CAP_TX_27COUNTER 0x00004000
#define ASI_CAP_TX_BYTESOR27 0x00008000
#define ASI_CAP_TX_TIMESTAMPS 0x00010000
#define ASI_CAP_TX_PTIMESTAMPS 0x00020000
#define ASI_CAP_TX_NULLPACKETS 0x00040000
#define ASI_CAP_RX_SYNC 0x00000004
#define ASI_CAP_RX_MAKE188 0x00000008
#define ASI_CAP_RX_BYTECOUNTER 0x00000010
/* #define ASI_CAP_RX_FIFOSTATUS 0x00000020 */
#define ASI_CAP_RX_INVSYNC 0x00000040
#define ASI_CAP_RX_CD 0x00000080
#define ASI_CAP_RX_DSYNC 0x00000100
#define ASI_CAP_RX_DATA 0x00000200
#define ASI_CAP_RX_PIDFILTER 0x00000400
#define ASI_CAP_RX_PIDCOUNTER 0x00000800
#define ASI_CAP_RX_4PIDCOUNTER 0x00001000
#define ASI_CAP_RX_FORCEDMA 0x00002000
#define ASI_CAP_RX_27COUNTER 0x00004000
#define ASI_CAP_RX_BYTESOR27 0x00008000
#define ASI_CAP_RX_TIMESTAMPS 0x00010000
#define ASI_CAP_RX_PTIMESTAMPS 0x00020000
#define ASI_CAP_RX_NULLPACKETS 0x00040000
#define ASI_CAP_RX_REDUNDANT 0x00080000
#define ASI_CAP_RX_DATA2 0x00100000
/* Transmitter clock source settings */
#define ASI_CTL_TX_CLKSRC_ONBOARD 0
#define ASI_CTL_TX_CLKSRC_EXT 1
#define ASI_CTL_TX_CLKSRC_RX 2
/* #define ASI_CTL_TX_CLKSRC_EXT_PAL 3 */
/* Transmitter mode settings */
#define ASI_CTL_TX_MODE_188 0
#define ASI_CTL_TX_MODE_204 1
#define ASI_CTL_TX_MODE_MAKE204 2
/* Receiver mode settings */
#define ASI_CTL_RX_MODE_RAW 0
#define ASI_CTL_RX_MODE_188 1
#define ASI_CTL_RX_MODE_204 2
#define ASI_CTL_RX_MODE_AUTO 3
#define ASI_CTL_RX_MODE_AUTOMAKE188 4
#define ASI_CTL_RX_MODE_204MAKE188 5
/* Timestamping settings */
#define ASI_CTL_TSTAMP_NONE 0
#define ASI_CTL_TSTAMP_APPEND 1
#define ASI_CTL_TSTAMP_PREPEND 2
/* Transport settings */
#define ASI_CTL_TRANSPORT_DVB_ASI 0
#define ASI_CTL_TRANSPORT_SMPTE_310M 1
#endif
......@@ -66,6 +66,7 @@ int i_verbose = DEFAULT_VERBOSITY;
uint16_t i_src_port = DEFAULT_PORT;
in_addr_t i_src_addr = { 0 };
int b_src_rawudp = 0;
int i_asi_adapter = 0;
void (*pf_Open)( void ) = NULL;
block_t * (*pf_Read)( void ) = NULL;
......@@ -219,7 +220,7 @@ static void DisplayVersion()
*****************************************************************************/
void usage()
{
msg_Raw( NULL, "Usage: dvblast [-q] [-c <config file>] [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>] [-n <frontend number>] [-S <diseqc>] [-f <frequency>|-D <src mcast>:<port>] [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-W] [-U] [-d <dest IP:port>] [-e] [-T]" );
msg_Raw( NULL, "Usage: dvblast [-q] [-c <config file>] [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>] [-n <frontend number>] [-S <diseqc>] [-f <frequency>|-D <src mcast>:<port>|-A <ASI adapter>] [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-W] [-U] [-d <dest IP:port>] [-e] [-T]" );
msg_Raw( NULL, " -q: be quiet (less verbosity, repeat or use number for even quieter)" );
msg_Raw( NULL, " -v: voltage to apply to the LNB (QPSK)" );
msg_Raw( NULL, " -p: force 22kHz pulses for high-band selection (DVB-S)" );
......@@ -232,6 +233,7 @@ void usage()
msg_Raw( NULL, " -U: use raw UDP rather than RTP (required by some IPTV set top boxes)" );
msg_Raw( NULL, " -d: duplicate all received packets to a given destination" );
msg_Raw( NULL, " -D: read packets from a multicast address instead of a DVB card" );
msg_Raw( NULL, " -A: read packets from an ASI adapter (0-n)" );
msg_Raw( NULL, " -e: enable EPG pass through (EIT data)" );
msg_Raw( NULL, " -T: generate unique TS ID for each program" );
msg_Raw( NULL, " -h: display this full help" );
......@@ -250,7 +252,7 @@ int main( int i_argc, char **pp_argv )
if ( i_argc == 1 )
usage();
while ( ( c = getopt(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:s:S:v:pb:m:uWUTd:D:ehV")) != -1 )
while ( ( c = getopt(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:s:S:v:pb:m:uWUTd:D:A:ehV")) != -1 )
{
switch ( c )
{
......@@ -410,6 +412,21 @@ int main( int i_argc, char **pp_argv )
break;
}
case 'A':
i_asi_adapter = strtol( optarg, NULL, 0 );
if ( pf_Open != NULL )
usage();
if ( psz_srv_socket != NULL )
{
msg_Err( NULL, "-r is only available for linux-dvb input" );
usage();
}
pf_Open = asi_Open;
pf_Read = asi_Read;
pf_SetFilter = asi_SetFilter;
pf_UnsetFilter = asi_UnsetFilter;
break;
case 'e':
b_enable_epg = 1;
break;
......
......@@ -105,6 +105,7 @@ extern int i_comm_fd;
extern uint16_t i_src_port;
extern in_addr_t i_src_addr;
extern int b_src_rawudp;
extern int i_asi_adapter;
extern void (*pf_Open)( void );
extern block_t * (*pf_Read)( void );
......@@ -134,6 +135,11 @@ block_t * udp_Read( void );
int udp_SetFilter( uint16_t i_pid );
void udp_UnsetFilter( int i_fd, uint16_t i_pid );
void asi_Open( void );
block_t * asi_Read( void );
int asi_SetFilter( uint16_t i_pid );
void asi_UnsetFilter( int i_fd, uint16_t i_pid );
void demux_Open( void );
void demux_Run( void );
void demux_Change( output_t *p_output, uint16_t i_sid,
......
......@@ -136,6 +136,8 @@ block_t *udp_Read( void )
i_len--;
}
if ( *pp_current )
msg_Dbg( NULL, "partial buffer received" );
block_DeleteChain( *pp_current );
*pp_current = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment