diff options
author | rjkm <devnull@localhost> | 2001-09-16 22:27:03 -0300 |
---|---|---|
committer | rjkm <devnull@localhost> | 2001-09-16 22:27:03 -0300 |
commit | 9034551a3bbc76b79a152806c781b1b8e8ea3a9a (patch) | |
tree | 31fe111120a3102afe9ea193836907a2c3a63fc7 /dvb-spec | |
parent | c2ca96fee8c574074c67c9da023e4165f2f9b2e3 (diff) | |
download | mediapointer-dvb-s2-9034551a3bbc76b79a152806c781b1b8e8ea3a9a.tar.gz mediapointer-dvb-s2-9034551a3bbc76b79a152806c781b1b8e8ea3a9a.tar.bz2 |
new API docs
Diffstat (limited to 'dvb-spec')
-rw-r--r-- | dvb-spec/dvbapi/Makefile | 30 | ||||
-rw-r--r-- | dvb-spec/dvbapi/audio.tex | 436 | ||||
-rw-r--r-- | dvb-spec/dvbapi/bibsection.sty | 29 | ||||
-rw-r--r-- | dvb-spec/dvbapi/ca.tex | 127 | ||||
-rw-r--r-- | dvb-spec/dvbapi/cimlogo.psi | 122 | ||||
-rw-r--r-- | dvb-spec/dvbapi/demux.tex | 392 | ||||
-rw-r--r-- | dvb-spec/dvbapi/devices.tex | 12 | ||||
-rw-r--r-- | dvb-spec/dvbapi/dvbapi.tex | 166 | ||||
-rw-r--r-- | dvb-spec/dvbapi/dvbstb.fig | 59 | ||||
-rw-r--r-- | dvb-spec/dvbapi/examples.tex | 365 | ||||
-rwxr-xr-x | dvb-spec/dvbapi/fig2pstex | 6 | ||||
-rwxr-xr-x | dvb-spec/dvbapi/getbb | 12 | ||||
-rw-r--r-- | dvb-spec/dvbapi/intro.tex | 192 | ||||
-rw-r--r-- | dvb-spec/dvbapi/kdapi.tex | 1007 | ||||
-rw-r--r-- | dvb-spec/dvbapi/sec.tex | 282 | ||||
-rw-r--r-- | dvb-spec/dvbapi/title.tex | 24 | ||||
-rw-r--r-- | dvb-spec/dvbapi/video.tex | 684 |
17 files changed, 3945 insertions, 0 deletions
diff --git a/dvb-spec/dvbapi/Makefile b/dvb-spec/dvbapi/Makefile new file mode 100644 index 000000000..fe9827cff --- /dev/null +++ b/dvb-spec/dvbapi/Makefile @@ -0,0 +1,30 @@ +all: dvbapi.ps dvbapi.pdf + +TEXS= dvbapi.tex devices.tex video.tex audio.tex ca.tex sec.tex frontend.tex \ + intro.tex title.tex dvbstb.ps + +dvbapi.pdf: dvbapi.dvi + dvipdf $< $@ + +dvbapi.ps: dvbapi.dvi + dvips -o $@ $< + +dvbapi.dvi: dvbapi.bbl $(TEXS) + -latex dvbapi + -bibtex dvbapi + -makeindex dvbapi + -latex dvbapi + -latex dvbapi + +dvbapi.bbl: $(TEXS) + -latex dvbapi + -bibtex dvbapi + -makeindex dvbapi + +%.ps: %.fig + ./fig2pstex $< + +clean: + rm -f dvbapi.dvi + rm -f *.aux *.bbl *.blg *.idx *.ilg *.ind *.log *.out *.toc + rm -f *.pdf *.pst *.ps diff --git a/dvb-spec/dvbapi/audio.tex b/dvb-spec/dvbapi/audio.tex new file mode 100644 index 000000000..8c5b4fe82 --- /dev/null +++ b/dvb-spec/dvbapi/audio.tex @@ -0,0 +1,436 @@ +\devsec{DVB Audio Device} + +The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. +It can be accessed through \texttt{/dev/ost/audio}. + + +\devsubsec{Audio Data Types} + +This section describes the structures, data types and defines used when +talking to the audio device. + +\devsubsubsec{audioStreamSource\_t} +\label{audiostreamsource} +The audio stream source is set through the AUDIO\_SELECT\_SOURCE +call and can take the following values, depending on whether we are +replaying from an internal (demuxer) or external (user write) source. +\begin{verbatim} +typedef enum { + AUDIO_SOURCE_DEMUX, + AUDIO_SOURCE_MEMORY +} audioStreamSource_t; +\end{verbatim} +AUDIO\_SOURCE\_DEMUX selects the demultiplexer (fed +either by the frontend or the DVR device) as the source of +the video stream. +If AUDIO\_SOURCE\_MEMORY is selected the stream +comes from the application through the \texttt{write()} +system call. + +\devsubsubsec{audioPlayState\_t} +The following values can be returned by the AUDIO\_GET\_STATUS call +representing the state of audio playback. +\label{audioplaystate} +\begin{verbatim} +typedef enum { + AUDIO_STOPPED, + AUDIO_PLAYING, + AUDIO_PAUSED +} audioPlayState_t; +\end{verbatim} + +\devsubsubsec{audioChannelSelect\_t} +\label{audiochannelselect} +The audio channel selected via AUDIO\_CHANNEL\_SELECT is determined by +the following values. +\begin{verbatim} +typedef enum { + AUDIO_STEREO, + AUDIO_MONO_LEFT, + AUDIO_MONO_RIGHT, +} audioChannelSelect_t; +\end{verbatim} + +\devsubsubsec{audioStatus\_t} +\label{audiostatus} +The AUDIO\_GET\_STATUS call returns the following structure informing +about various states of the playback operation. +\begin{verbatim} +typedef struct audioStatus { + boolean AVSyncState; + boolean muteState; + audioPlayState_t playState; + audioStreamSource_t streamSource; + audioChannelSelect_t channelSelect; + boolean bypassMode; +} audioStatus_t; +\end{verbatim} + +\devsubsubsec{audioMixer\_t} +\label{audiomixer} +The following structure is used by the AUDIO\_SET\_MIXER call to set +the audio volume. +\begin{verbatim} +typedef struct audioMixer { + unsigned int volume_left; + unsigned int volume_right; +} audioMixer_t; +\end{verbatim} + +\devsubsubsec{audio encodings} +\label{audiotypes} +A call to AUDIO\_GET\_CAPABILITIES returns an unsigned integer with +the following bits set according to the hardwares capabilities. +\begin{verbatim} +#define AUDIO_CAP_DTS 1 +#define AUDIO_CAP_LPCM 2 +#define AUDIO_CAP_MP1 4 +#define AUDIO_CAP_MP2 8 +#define AUDIO_CAP_MP3 16 +#define AUDIO_CAP_AAC 32 +#define AUDIO_CAP_OGG 64 +#define AUDIO_CAP_SDDS 128 +#define AUDIO_CAP_AC3 256 +\end{verbatim} + + +\devsubsubsec{audio karaoke} +\label{audiokaraoke} +The ioctl AUDIO\_SET\_KARAOKE uses the following format: +\begin{verbatim} +typedef +struct audioKaraoke{ /* if Vocal1 or Vocal2 are non-zero, they get mixed */ + int vocal1; /* into left and right t at 70% each */ + int vocal2; /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets */ + int melody; /* mixed into the left channel and */ + /* Vocal2 into the right channel at 100% each. */ + /* if Melody is non-zero, the melody channel gets mixed */ /* into left and right */ +} audioKaraoke_t; +\end{verbatim} + +\devsubsubsec{audio attributes} +\label{aattrib} +The following attributes can be set by a call to AUDIO\_SET\_ATTRIBUTES: +\begin{verbatim} +typedef uint16_t audioAttributes_t; +/* bits: descr. */ +/* 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */ +/* 12 multichannel extension */ +/* 11-10 audio type (0=not spec, 1=language included) */ +/* 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */ +/* 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, */ +/* 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */ +/* 2- 0 number of audio channels (n+1 channels) */ +\end{verbatim} + + +\clearpage + +\devsubsec{Audio Function Calls} + +\function{open()}{ + int open(const char *deviceName, int flags);}{ + This system call opens a named audio device (e.g. /dev/ost/audio) for subsequent + use. When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect + the semantics of the open() call itself. A device opened in blocking mode can + later be put into non-blocking mode (and vice versa) using the F\_SETFL command + of the fcntl system call. This is a standard system call, documented in the + Linux manual page for fcntl. + Only one user can open the Audio Device in O\_RDWR mode. All other attempts to + open the device in this mode will fail, and an error code will be returned. + If the Audio Device is opened in O\_RDONLY mode, the only ioctl call that can + be used is AUDIO\_GET\_STATUS. All other call will return with an error code. + }{ + const char *deviceName & Name of specific audio device.\\ + int flags & A bit-wise OR of the following flags:\\ + & \hspace{1em} O\_RDONLY read-only access\\ + & \hspace{1em} O\_RDWR read/write access\\ + & \hspace{1em} O\_NONBLOCK open in non-blocking mode \\ + & \hspace{1em} (blocking mode is the default)\\ + }{ + ENODEV & Device driver not loaded/available.\\ + EINTERNAL & Internal error.\\ + EBUSY & Device or resource busy.\\ + EINVAL & Invalid argument.\\ +} + +\function{close()}{ + int close(int fd);}{ + This system call closes a previously opened audio device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + }{ + EBADF & fd is not a valid open file descriptor.\\ +} + +\function{write()}{ + size\_t write(int fd, const void *buf, size\_t count);}{ + This system call can only be used if AUDIO\_SOURCE\_MEMORY is selected + in the ioctl call AUDIO\_SELECT\_SOURCE. + The data provided shall be in PES format. + If O\_NONBLOCK is not specified the function will block until buffer space is + available. The amount of data to be transferred is implied by count. + }{ + int fd & File descriptor returned by a previous call to open().\\ + void *buf & Pointer to the buffer containing the PES data.\\ + size\_t count& Size of buf.\\ + }{ + EPERM& Mode AUDIO\_SOURCE\_MEMORY not selected.\\ + ENOMEM& Attempted to write more data than the internal buffer can hold.\\ + EBADF& fd is not a valid open file descriptor.\\ +} + +\ifunction{AUDIO\_STOP}{ + int ioctl(int fd, int request = AUDIO\_STOP);}{ + This ioctl call asks the Audio Device to stop playing the current stream. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals AUDIO\_STOP for this command. + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error. +} + +\ifunction{AUDIO\_PLAY}{ + int ioctl(int fd, int request = AUDIO\_PLAY);}{ + This ioctl call asks the Audio Device to start playing an audio stream + from the selected source. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals AUDIO\_PLAY for this command. + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error. +} + +\ifunction{AUDIO\_PAUSE}{ + int ioctl(int fd, int request = AUDIO\_PAUSE);}{ + This ioctl call suspends the audio stream being played. + Decoding and playing are paused. + It is then possible to restart again decoding and playing process of the + audio stream using AUDIO\_CONTINUE command.\\ + If AUDIO\_SOURCE\_MEMORY is selected in the ioctl call + AUDIO\_SELECT\_SOURCE, the DVB-subsystem will not decode (consume) + any more data until the ioctl call + AUDIO\_CONTINUE or AUDIO\_PLAY is performed. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals AUDIO\_PAUSE for this command. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error. +} + +\ifunction{AUDIO\_SELECT\_SOURCE}{ + int ioctl(int fd, int request = AUDIO\_SELECT\_SOURCE, + audioStreamSource\_t source);}{ + This ioctl call informs the audio device which source shall be used for the + input data. The possible sources are demux or memory. + If AUDIO\_SOURCE\_MEMORY + is selected, the data is fed to the Audio Device through the write command. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SELECT\_SOURCE for this command.\\ + audioStreamSource\_t source& Indicates the source that shall be used for the + Audio stream. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal input parameter. +} + +\ifunction{AUDIO\_SET\_MUTE}{ + int ioctl(int fd, int request = AUDIO\_SET\_MUTE, boolean state);}{ + This ioctl call asks the audio device to mute the stream that is + currently being played. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_MUTE for this command.\\ + boolean state & Indicates if audio device shall mute or not.\\ + &TRUE Audio Mute\\ + &FALSE Audio Un-mute\\ + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal input parameter. +} + +\ifunction{AUDIO\_SET\_AV\_SYNC}{ + int ioctl(int fd, int request = AUDIO\_SET\_AV\_SYNC, boolean state);}{ + This ioctl call asks the Audio Device to turn ON or OFF A/V synchronization. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_AV\_SYNC for this command.\\ + boolean state& Tells the DVB subsystem if A/V + synchronization shall be ON or OFF.\\ + & TRUE AV-sync ON \\ + & FALSE AV-sync OFF\\ + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal input parameter. +} + +\ifunction{AUDIO\_SET\_BYPASS\_MODE}{ + int ioctl(int fd, int request = AUDIO\_SET\_BYPASS\_MODE, boolean mode);}{ + This ioctl call asks the Audio Device to bypass the Audio decoder and forward + the stream without decoding. This mode shall be used if streams that can't be + handled by the DVB system shall be decoded. + Dolby DigitalTM streams are automatically forwarded by the DVB + subsystem if the hardware can handle it. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_BYPASS\_MODE for this command.\\ + boolean mode& Enables or disables the decoding of the current + Audio stream in the DVB subsystem.\\ + &TRUE Bypass is disabled\\ + &FALSE Bypass is enabled\\ + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal input parameter. +} + +\ifunction{AUDIO\_CHANNEL\_SELECT}{ + int ioctl(int fd, int request = AUDIO\_CHANNEL\_SELECT, + audioChannelSelect\_t);}{ + This ioctl call asks the Audio Device to select the requested channel + if possible. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_CHANNEL\_SELECT for this command.\\ + audioChannelSelect\_t ch & + Select the output format of the audio (mono left/right, stereo). + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal input parameter ch. +} + +\ifunction{AUDIO\_GET\_STATUS}{ + int ioctl(int fd, int request = AUDIO\_GET\_STATUS, + struct audioStatus *status);}{ + This ioctl call asks the Audio Device to return the current state + of the Audio Device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_GET\_STATUS for this command.\\ + struct audioStatus *status & Returns the current state of Audio Device. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EFAULT & status points to invalid address. +} + +\ifunction{AUDIO\_GET\_CAPABILITIES}{ + int ioctl(int fd, int request = AUDIO\_GET\_CAPABILITIES, + unsigned int *cap);}{ + This ioctl call asks the Audio Device to tell us about the + decoding capabilities of the audio hardware. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_GET\_CAPABILITIES for this command.\\ + unsigned int *cap & Returns a bit array of supported sound formats. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EFAULT & cap points to an invalid address. +} + +\ifunction{AUDIO\_CLEAR\_BUFFER}{ + int ioctl(int fd, int request = AUDIO\_CLEAR\_BUFFER);}{ + This ioctl call asks the Audio Device to clear all software + and hardware buffers of the audio decoder device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_CLEAR\_BUFFER for this command. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error. +} + +\ifunction{AUDIO\_SET\_ID}{ + int ioctl(int fd, int request = AUDIO\_SET\_ID, int id);}{ + This ioctl selects which sub-stream is to be decoded if a program or + system stream is sent to the video device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_ID for this command.\\ + int id& audio sub-stream id + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Invalid sub-stream id. +} + +\ifunction{AUDIO\_SET\_MIXER}{ + int ioctl(int fd, int request = AUDIO\_SET\_MIXER, audioMixer\_t *mix);}{ + This ioctl lets you adjust the mixer settings of the audio decoder. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_ID for this command.\\ + audioMixer\_t *mix& mixer settings. + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EFAULT & mix points to an invalid address. +} + +\ifunction{AUDIO\_SET\_STREAMTYPE}{ + int ioctl(fd, int request = AUDIO\_SET\_STREAMTYPE, int type);}{ + This ioctl tells the driver which kind of audio stream to expect. + This is useful if the stream offers several audio sub-streams + like MPEG2 audio and AC3. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_STREAMTYPE for this command.\\ + int type & stream type\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& type is not a valid or supported stream type.\\ +} + + +\ifunction{AUDIO\_SET\_EXT\_ID}{ + int ioctl(fd, int request = AUDIO\_SET\_EXT\_ID, int id);}{ + This ioctl can be used to set the audio sub\_stream\_id for DVD playback + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_EXT\_ID for this command.\\ + int id & audio sub\_stream\_id\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& id is not a valid id.\\ +} + +\ifunction{AUDIO\_SET\_ATTRIBUTES}{ + int ioctl(fd, int request = AUDIO\_SET\_ATTRIBUTES, audioAttributes\_t attr );}{ + This ioctl is intended for DVD playback and allows you to set + certain information about the audio stream. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_ATTRIBUTES for this command.\\ + iaudioAttributes\_t attr & audio attributes according to section \ref{aattrib}\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& attr is not a valid or supported attribute setting.\\ +} + +\ifunction{AUDIO\_SET\_KARAOKE}{ + int ioctl(fd, int request = AUDIO\_SET\_STREAMTYPE, audioKaraoke\_t *karaoke);}{ + This ioctl allows one to set the mixer settings for a karaoke DVD. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals AUDIO\_SET\_STREAMTYPE for this command.\\ + audioKaraoke\_t *karaoke & karaoke settings according to section \ref{audiokaraoke}.\\ + }{ + EBADF & fd is not a valid open file descriptor \\ + EINVAL& karaoke is not a valid or supported karaoke setting.\\ +} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/bibsection.sty b/dvb-spec/dvbapi/bibsection.sty new file mode 100644 index 000000000..7f9eedc6a --- /dev/null +++ b/dvb-spec/dvbapi/bibsection.sty @@ -0,0 +1,29 @@ +\def\thebibliography#1{\chapter*{\bibname\@mkboth + {\uppercase{\bibname}}{\uppercase{\bibname}}} + \setcounter{chapter}{0} + \setcounter{section}{0} + \def\thechapter{Bib} + \def\thesection{\Alph{section}} + \edef\biblab{#1} + \addcontentsline{toc}{chapter}{\bibname} + } + +\def\bibtitle#1#2{\expandafter\def\csname bibtitle#1\endcsname{ + \bibsection{#2}} } + +\def\bibsection#1{\section{#1} + \begin{list} + {\@biblabel{\arabic{enumiv}}}{\settowidth\labelwidth{\@biblabel{\biblab}}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \usecounter{enumiv}% + \let\p@enumiv\@empty + \def\theenumiv{\arabic{enumiv}}}% + \def\newblock{\hskip .11em plus.33em minus.07em}% + \sloppy\clubpenalty4000\widowpenalty4000 + \sfcode`\.=\@m} + +\def\endbibsection{\end{list}} + +\def\endthebibliography{\endbibsection} + diff --git a/dvb-spec/dvbapi/ca.tex b/dvb-spec/dvbapi/ca.tex new file mode 100644 index 000000000..eba512b1b --- /dev/null +++ b/dvb-spec/dvbapi/ca.tex @@ -0,0 +1,127 @@ +\devsec{DVB CA Device} + +The DVB CA device controls the conditional access hardware. +It can be accessed through \texttt{/dev/ost/ca}. + + +\devsubsec{CA Data Types} + +\devsubsubsec{ca\_slot\_info\_t} +\label{caslotinfo} + +\begin{verbatim} +/* slot interface types and info */ + +typedef struct ca_slot_info_s { + int num; /* slot number */ + + int type; /* CA interface this slot supports */ +#define CA_CI 1 /* CI high level interface */ +#define CA_CI_LINK 2 /* CI link layer level interface */ +#define CA_CI_PHYS 4 /* CI physical layer level interface */ +#define CA_SC 128 /* simple smart card interface */ + + unsigned int flags; +#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */ +#define CA_CI_MODULE_READY 2 +} ca_slot_info_t; +\end{verbatim} + +\devsubsubsec{ca\_descr\_info\_t} +\label{cadescrinfo} + +\begin{verbatim} +typedef struct ca_descr_info_s { + unsigned int num; /* number of available descramblers (keys) */ + unsigned int type; /* type of supported scrambling system */ +#define CA_ECD 1 +#define CA_NDS 2 +#define CA_DSS 4 +} ca_descr_info_t; +\end{verbatim} + +\devsubsubsec{ca\_cap\_t} +\label{cacap} + +\begin{verbatim} +typedef struct ca_cap_s { + unsigned int slot_num; /* total number of CA card and module slots */ + unsigned int slot_type; /* OR of all supported types */ + unsigned int descr_num; /* total number of descrambler slots (keys) */ + unsigned int descr_type;/* OR of all supported types */ +} ca_cap_t; +\end{verbatim} + + +\devsubsubsec{ca\_msg\_t} +\label{camsg} + +\begin{verbatim} +/* a message to/from a CI-CAM */ +typedef struct ca_msg_s { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; +} ca_msg_t; +\end{verbatim} + + +\devsubsubsec{ca\_descr\_t} +\label{cadescr} + +\begin{verbatim} +typedef struct ca_descr_s { + unsigned int index; + unsigned int parity; + unsigned char cw[8]; +} ca_descr_t; +\end{verbatim} + +\clearpage + +\devsubsec{CA Function Calls} + +\function{open()}{ + int open(const char *deviceName, int flags);}{ + This system call opens a named ca device (e.g. /dev/ost/ca) + for subsequent use. + + When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in + the documentation for functions where there is a difference. + It does not affect the semantics of the open() call itself. + A device opened in blocking mode can later be put into non-blocking mode + (and vice versa) using the F\_SETFL command of the fcntl system + call. + This is a standard system call, documented in the Linux manual + page for fcntl. + Only one user can open the CA Device in O\_RDWR mode. All other attempts to + open the device in this mode will fail, and an error code will be returned. + }{ + const char *deviceName & Name of specific video device.\\ + int flags & A bit-wise OR of the following flags:\\ + & \hspace{1em} O\_RDONLY read-only access\\ + & \hspace{1em} O\_RDWR read/write access\\ + & \hspace{1em} O\_NONBLOCK open in non-blocking mode \\ + & \hspace{1em} (blocking mode is the default)\\ + }{ + ENODEV & Device driver not loaded/available.\\ + EINTERNAL & Internal error.\\ + EBUSY & Device or resource busy.\\ + EINVAL & Invalid argument.\\ +} + +\function{close()}{ + int close(int fd);}{ + This system call closes a previously opened audio device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + }{ + EBADF & fd is not a valid open file descriptor.\\ +} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/cimlogo.psi b/dvb-spec/dvbapi/cimlogo.psi new file mode 100644 index 000000000..b7b089a49 --- /dev/null +++ b/dvb-spec/dvbapi/cimlogo.psi @@ -0,0 +1,122 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: /home/rjkm/dvbapi/cimlogo.ps +%%Creator: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) - by John Bradley +%%BoundingBox: 275 411 309 440 +%%Pages: 1 +%%DocumentFonts: +%%EndComments +%%EndProlog + +%%Page: 1 1 + +% remember original state +/origstate save def + +% build a temporary dictionary +20 dict begin + +% define string to hold a scanline's worth of data +/pix 45 string def + +% define space for color conversions +/grays 45 string def % space for gray scale line +/npixls 0 def +/rgbindx 0 def + +% lower left corner +275 411 translate + +% size of image (on paper, in 1/72inch coords) +33.76800 28.51200 scale + +45 38 8 % dimensions of data +[45 0 0 -38 0 38] % mapping matrix +{currentfile pix readhexstring pop} +image + +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffff00ffffffffffff0000000000ffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffff0000000000ffffffff000000000000ffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffff0000000000000000ffffff000000000000ffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffff0000000000000000ffffffff000000000000ffffffffffffffffffff +ffffffffffffffffff +ffffffffffffff000000000000000000ffffff000000000000ffffffffffffffffffffff +ffffffffffffffffff +ffffffffffff0000000000000000ffffffffff000000000000ffffff00000000ffffffff +ffffffffffffffffff +ffffffffff00000000000000ffffffffffffff0000000000ffffff0000000000ffffffff +ffffffffffffffffff +ffffffffff000000000000ffffffffffffff000000000000ffffff000000000000ffffff +ffffffffffffffffff +ffffffff00000000000000ffffffffffffff000000000000ffffffff000000000000ffff +ffffffffffffffffff +ffffffff000000000000ffffffffffffffff000000000000ffffffff000000000000ffff +ffffffffffffffffff +ffffffff0000000000ffffffffffffffff000000000000ffffffffffff0000000000ffff +ffffffffffffffffff +ffffff000000000000ffffffffffffffff000000000000ffffffffffff0000000000ffff +ffffffffffffffffff +ffffff0000000000ffffffffffffffffff000000000000ffffffffffff000000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffffffff0000000000ffffffffffffff000000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffffff000000000000ffffffffffffffff0000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffffff000000000000ffffffffffffff000000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffffff0000000000ffffffffffffffffff0000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffff000000000000ffffffffffffffff000000000000ff +ffffffffffffffffff +ffffff0000000000ffffffffffffff000000000000ffffffffffffffff0000000000ffff +ffffffffffffffffff +ffffff000000000000ffffffffffffff00000000ffffffffffffffffff0000000000ffff +ffffffffffffffffff +ffffffff0000000000ffffffffffffffff0000ffffffffffffffffff000000000000ffff +ffffffffffffffffff +ffffffff000000000000ffffffffffffffffffffffffffffffffffff000000000000ffff +ffffffffffffffffff +ffffffff000000000000ffffffffffffffffffffffffffffffffff000000000000ffffff +ffffffffffffffffff +ffffffffff00000000000000ffffffffffffffffffffffffffff000000000000ffffffff +ff0000000000ffffff +ffffffffff0000000000000000ffffffffffffffffffffffff00000000000000ffffffff +00000000000000ffff +ffffffffffff000000000000000000ffffffffffffffff0000000000000000ffffffffff +00000000000000ffff +ffffffffffffff0000000000000000000000000000000000000000000000ffffffffffff +0000000000000000ff +ffffffffffffffff000000000000000000000000000000000000000000ffffffffffffff +00000000000000ffff +ffffffffffffffffffff0000000000000000000000000000000000ffffffffffffffffff +00000000000000ffff +ffffffffffffffffffffffff00000000000000000000000000ffffffffffffffffffffff +ff0000000000ffffff +ffffffffffffffffffffffffffffff00ff0000000000ffffffffffffffffffffffffffff +ffffff0000ffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffff + +showpage + +% stop using temporary dictionary +end + +% restore original state +origstate restore + +%%Trailer diff --git a/dvb-spec/dvbapi/demux.tex b/dvb-spec/dvbapi/demux.tex new file mode 100644 index 000000000..541ee633a --- /dev/null +++ b/dvb-spec/dvbapi/demux.tex @@ -0,0 +1,392 @@ +\devsec{DVB Demux Device} + +The DVB demux device controls the filters of the DVB hardware/software. +It can be accessed through \texttt{/dev/ost/demux}. + +\devsubsec{Demux Data Types} + +\begin{verbatim} +typedef uint16_t dvb_pid_t; +\end{verbatim} + + +\devsubsubsec{dmxOutput\_t} +\label{dmxoutput} + +\begin{verbatim} +typedef enum +{ + DMX_OUT_DECODER, + DMX_OUT_TAP, + DMX_OUT_TS_TAP +} dmxOutput_t; +\end{verbatim} +/* Output multiplexed into a new TS */ +/* (to be retrieved by reading from the */ +/* logical DVR device). */ + + +\devsubsubsec{dmxInput\_t} +\label{dmxinput} + +\begin{verbatim} +typedef enum +{ + DMX_IN_FRONTEND, /* Input from a front-end device. */ + DMX_IN_DVR /* Input from the logical DVR device. */ +} dmxInput_t; +\end{verbatim} + + +\devsubsubsec{dmxPesType\_t} +\label{dmxpestype} + +\begin{verbatim} +typedef enum +{ + DMX_PES_AUDIO, + DMX_PES_VIDEO, + DMX_PES_TELETEXT, + DMX_PES_SUBTITLE, + DMX_PES_PCR, + DMX_PES_OTHER +} dmxPesType_t; +\end{verbatim} + + +\devsubsubsec{dmxEvent\_t} +\label{dmxeventt} + +\begin{verbatim} +typedef enum +{ + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV +} dmxEvent_t; +\end{verbatim} + + +\devsubsubsec{dmxScramblingStatus\_t} +\label{dmxscramblingstatus} + +\begin{verbatim} +typedef enum +{ + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON +} dmxScramblingStatus_t; +\end{verbatim} + + +\devsubsubsec{dmxFilter\_t} +\label{dmxfilter} + +\begin{verbatim} +typedef struct dmxFilter +{ + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; +} dmxFilter_t; +\end{verbatim} + + +\devsubsubsec{dmxSctFilterParams} +\label{dmxsctfilterparams} + +\begin{verbatim} +struct dmxSctFilterParams +{ + dvb_pid_t pid; + dmxFilter_t filter; + uint32_t timeout; + uint32_t flags; +#define DMX_CHECK_CRC 1 +#define DMX_ONESHOT 2 +#define DMX_IMMEDIATE_START 4 +}; +\end{verbatim} + + +\devsubsubsec{dmxPesFilterParams} +\label{dmxpesfilterparams} + +\begin{verbatim} +struct dmxPesFilterParams +{ + dvb_pid_t pid; + dmxInput_t input; + dmxOutput_t output; + dmxPesType_t pesType; + uint32_t flags; +}; +\end{verbatim} + + +\devsubsubsec{dmxEvent} +\label{dmxevent} + +\begin{verbatim} +struct dmxEvent +{ + dmxEvent_t event; + time_t timeStamp; + union + { + dmxScramblingStatus_t scrambling; + } u; +}; +\end{verbatim} + +\clearpage + +\devsubsec{Demux Function Calls} +\function{open()}{ + int open(const char *deviceName, int flags);}{ + This system call, used with a device name of /dev/ost/demuxn, where n + denotes the specific demux device to be opened, allocates a new filter + and returns a handle which can be used for subsequent control of that + filter. This call has to be made for each filter to be used, i.e. every + returned file descriptor is a reference to a single filter. + /dev/ost/dvrn is a logical device to be used for retrieving Transport + Streams for digital video recording. n identifies the physical demux + device that provides the actual DVR functionality. When reading from + this device a transport stream containing the packets from all PES + filters set in the corresponding demux device (/dev/ost/demuxn) + having the output set to DMX\_OUT\_TS\_TAP. A recorded Transport Stream + is replayed by writing to this device. +% This device can only be opened in read-write mode. + + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not + affect the semantics of the open() call itself. A device opened in + blocking mode can later be put into non-blocking mode + (and vice versa) using the F\_SETFL command of the fcntl system call. + }{ + const char *deviceName & Name of demux device.\\ + int flags & A bit-wise OR of the following flags:\\ + & \hspace{1em} O\_RDWR read/write access\\ + & \hspace{1em} O\_NONBLOCK open in non-blocking mode \\ + & \hspace{1em} (blocking mode is the default)\\ + }{ + ENODEV & Device driver not loaded/available.\\ + EINVAL & Invalid argument.\\ + EMFILE & ``Too many open files'', i.e. no more filters available.\\ + ENOMEM & The driver failed to allocate enough memory.\\ +} + +\function{close()}{ + int close(int fd);}{ + This system call deactivates and deallocates a filter that was previously + allocated via the open() call. + }{ + int fd & File descriptor returned by a previous call to open().\\ + }{ + EBADF & fd is not a valid open file descriptor.\\ +} + +\function{read()}{ + size\_t read(int fd, void *buf, size\_t count); + }{ + This system call returns filtered data, which might be section or PES + data. The filtered data is transferred from the driver's internal circular + buffer to buf. The maximum amount of data to be transferred is implied by + count.\\ + When returning section data the driver always tries to return a complete + single section (even though buf would provide buffer space for more data). + If the size of the buffer is smaller than the section as much as possible + will be returned, and the remaining data will be provided in subsequent + calls.\\ + The size of the internal buffer is 2 * 4096 bytes (the size of two maximum + sized sections) by default. The size of this buffer may be changed by + using the DMX\_SET\_BUFFER\_SIZE function. If the buffer is not large enough, + or if the read operations are not performed fast enough, this may result + in a buffer overflow error. In this case EBUFFEROVERFLOW will be returned, + and the circular buffer will be emptied. + This call is blocking if there is no data to return, i.e. the process + will be put to sleep waiting for data, unless the O\_NONBLOCK flag is + specified.\\ + Note that in order to be able to read, the filtering process has to be + started by defining either a section or a PES filter by means of the + ioctl functions, and then starting the filtering process via the DMX\_START + ioctl function or by setting the DMX\_IMMEDIATE\_START flag. + If the reading is done from a logical DVR demux device, the data will + constitute a Transport Stream including the packets from all PES filters + in the corresponding demux device /dev/ost/demuxn having the output set + to DMX\_OUT\_TS\_TAP. + }{ + int fd & File descriptor returned by a previous call to open().\\ + void *buf & Pointer to the buffer to be used for returned filtered data.\\ + size\_t count & Size of buf.\\ + }{ + EWOULDBLOCK & No data to return and O\_NONBLOCK was specified.\\ + EBADF & fd is not a valid open file descriptor.\\ + ECRC & Last section had a CRC error - no data returned. + The buffer is flushed.\\ + EBUFFEROVERFLOW & \\ +& The filtered data was not read from the buffer in + due time, resulting in non-read data being lost. + The buffer is flushed.\\ + ETIMEDOUT & The section was not loaded within the stated + timeout period. See ioctl DMX\_SET\_FILTER for + how to set a timeout.\\ + EFAULT & The driver failed to write to the callers buffer + due to an invalid *buf pointer.\\ +} + +\function{write()}{ + ssize\_t write(int fd, const void *buf, size\_t count); + }{ + This system call is only provided by the logical device /dev/ost/dvrn, + where n identifies the physical demux device that provides the actual + DVR functionality. It is used for replay of a digitally recorded + Transport Stream. Matching filters have to be defined in the + corresponding physical demux device, /dev/ost/demuxn. + The amount of data to be transferred is implied by count. + }{ + int fd & File descriptor returned by a previous call to open().\\ + void *buf & Pointer to the buffer containing the Transport Stream.\\ + size\_t count & Size of buf.\\ + }{ + EWOULDBLOCK & No data was written. This might happen if + O\_NONBLOCK was specified and there is no more + buffer space available (if O\_NONBLOCK is not + specified the function will block until buffer + space is available).\\ + EBUSY & This error code indicates that there are + conflicting requests. The corresponding demux + device is setup to receive data from the front- + end. Make sure that these filters are stopped + and that the filters with input set to DMX\_IN\_DVR + are started.\\ + EBADF & fd is not a valid open file descriptor.\\ +} + +\ifunction{DMX\_START}{ + int ioctl( int fd, int request = DMX\_START); + }{ + This ioctl call is used to start the actual filtering operation + defined via the ioctl calls DMX\_SET\_FILTER or DMX\_SET\_PES\_FILTER. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_START for this command.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EINVAL & Invalid argument, i.e. no filtering parameters + provided via the DMX\_SET\_FILTER or + DMX\_SET\_PES\_FILTER functions.\\ + EBUSY & This error code indicates that there are + conflicting requests. There are active filters + filtering data from another input source. Make + sure that these filters are stopped before starting + this filter.\\ +} + +\ifunction{DMX\_STOP}{ + int ioctl( int fd, int request = DMX\_STOP); + }{ + This ioctl call is used to stop the actual filtering operation defined + via the ioctl calls DMX\_SET\_FILTER or DMX\_SET\_PES\_FILTER and started via + the DMX\_START command. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_STOP for this command.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ +} + +\ifunction{DMX\_SET\_FILTER}{ + int ioctl( int fd, int request = DMX\_SET\_FILTER, struct dmxSctFilterParams *params); + }{ + This ioctl call sets up a filter according to the filter and mask + parameters provided. A timeout may be defined stating number of seconds + to wait for a section to be loaded. A value of 0 means that no timeout + should be applied. Finally there is a flag field where it is possible to + state whether a section should be CRC-checked, whether the filter should + be a "one-shot" filter, i.e. if the filtering operation should be stopped + after the first section is received, and whether the filtering operation + should be started immediately (without waiting for a DMX\_START ioctl call). + If a filter was previously set-up, this filter will be canceled, and the + receive buffer will be flushed. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_SET\_FILTER for this command.\\ + struct dmxSctFilterParams *params + & Pointer to structure containing filter parameters.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EINVAL & Invalid argument.\\ +} + +\ifunction{DMX\_SET\_PES\_FILTER}{ + int ioctl( int fd, int request = DMX\_SET\_PES\_FILTER, + struct dmxPesFilterParams *params); + }{ + This ioctl call sets up a PES filter according to the parameters provided. + By a PES filter is meant a filter that is based just on the packet + identifier (PID), i.e. no PES header or payload filtering capability is + supported.\\ + The transport stream destination for the filtered output may be set. Also + the PES type may be stated in order to be able to e.g. direct a video + stream directly to the video decoder. Finally there is a flag field where + it is possible to state whether the filtering operation should be started + immediately (without waiting for a DMX\_START ioctl call). + If a filter was previously set-up, this filter will be cancelled, and the + receive buffer will be flushed. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_SET\_PES\_FILTER for this command.\\ + struct dmxPesFilterParams *params + & Pointer to structure containing filter parameters.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EINVAL & Invalid argument.\\ + EBUSY & This error code indicates that there are + conflicting requests. There are active filters + filtering data from another input source. Make + sure that these filters are stopped before starting + this filter.\\ +} + +\ifunction{DMX\_SET\_BUFFER\_SIZE}{ + int ioctl( int fd, int request = DMX\_SET\_BUFFER\_SIZE, unsigned long size); + }{ + This ioctl call is used to set the size of the circular buffer used + for filtered data. The default size is two maximum sized sections, i.e. + if this function is not called a buffer size of 2 * 4096 bytes will be + used. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_SET\_BUFFER\_SIZE for this command.\\ + unsigned long size & Size of circular buffer.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + ENOMEM & The driver was not able to allocate a buffer of the requested size.\\ +} + +\ifunction{DMX\_GET\_EVENT}{ + int ioctl( int fd, int request = DMX\_GET\_EVENT, struct dmxEvent *ev); + }{ + This ioctl call returns an event if available. If an event is not + available, the behavior depends on whether the device is in blocking or + non-blocking mode. In the latter case, the call fails immediately with + errno set to EWOULDBLOCK. In the former case, the call blocks until an + event becomes available.\\ + The standard Linux poll() and/or select() system calls can be used with + the device file descriptor to watch for new events. For select(), the + file descriptor should be included in the exceptfds argument, and for + poll(), POLLPRI should be specified as the wake-up condition. + Only the latest event for each filter is saved. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals DMX\_GET\_EVENT for this command.\\ + struct dmxEvent *ev & Pointer to the location where the event is to be stored.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EFAULT & ev points to an invalid address.\\ + EWOULDBLOCK & There is no event pending, and the device is in non-blocking mode.\\ +} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/devices.tex b/dvb-spec/dvbapi/devices.tex new file mode 100644 index 000000000..9c561e853 --- /dev/null +++ b/dvb-spec/dvbapi/devices.tex @@ -0,0 +1,12 @@ +\input{video.tex} +\input{audio.tex} +\input{frontend.tex} +\input{sec.tex} +\input{demux.tex} +\input{ca.tex} +\input{kdapi.tex} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/dvbapi.tex b/dvb-spec/dvbapi/dvbapi.tex new file mode 100644 index 000000000..f9fcb841c --- /dev/null +++ b/dvb-spec/dvbapi/dvbapi.tex @@ -0,0 +1,166 @@ +\documentclass[10pt]{book} +\usepackage[dvips,colorlinks=true]{hyperref} + +\usepackage{times} + +%\usepackage[hang]{caption} +\usepackage{fancyheadings} +%\usepackage{lucidabr} +%\usepackage{fancybox} +\usepackage{array} +\usepackage{graphicx} +%\usepackage{latexsym} +%\usepackage{pstricks,pst-node,pst-tree} +%\usepackage{verbatim} +%\usepackage{rotating} +%\usepackage{pdftex} +%\usepackage{color} +%\usepackage{subfigure} +%\usepackage{wrapfig} + +\newcommand{\devsec}[1]{\chapter{#1}} +\newcommand{\devsubsec}[1]{\section{#1}} +\newcommand{\devsubsubsec}[1]{\subsection{#1}} +\newcommand{\function}[5]{ + \subsection{#1} + + \noindent DESCRIPTION + \medskip + + \begin{tabular}[h]{p{11cm}} + #3 + \end{tabular} + + \medskip + \noindent SYNOPSIS + \medskip + + \begin{tabular}[h]{p{11cm}} + {\tt #2} + \end{tabular} + + %\item[] +\medskip +\noindent PARAMETERS +\medskip + + \begin{tabular}[h]{p{3cm}p{8cm}} + #4 + \end{tabular} + + %\item[] +\medskip +\noindent ERRORS +\medskip + + \begin{tabular}[h]{p{3cm}p{8cm}} + #5 + \end{tabular} + + %\end{itemize} + +\medskip +} +\def\ifunction#1#2#3#4#5{\function{#1\index{#1}}{#2}{#3}{#4}{#5}} + +\newcommand{\kfunction}[5]{ + \subsection{#1} + \noindent DESCRIPTION + \medskip + + \begin{tabular}[h]{p{11cm}} + #3 + \end{tabular} + + \medskip + \noindent SYNOPSIS + \medskip + + \begin{tabular}[h]{p{11cm}} + {\tt #2} + \end{tabular} + + %\item[] +\medskip +\noindent PARAMETERS +\medskip + + \begin{tabular}[h]{p{3cm}p{8cm}} + #4 + \end{tabular} + + %\item[] +\medskip +\noindent RETURNS +\medskip + + \begin{tabular}[h]{p{3cm}p{8cm}} + #5 + \end{tabular} + + %\end{itemize} + +\medskip +} +\def\kifunction#1#2#3#4#5{\kfunction{#1\index{#1}}{#2}{#3}{#4}{#5}} + + +%\usepackage{index} +%\makeindex + + +\begin{document} + +\input{title.tex} + +\cleardoublepage + +\pagenumbering{roman} +\pagestyle{fancyplain} + + +\tableofcontents +%\listoffigures +%\listoftables + +\cleardoublepage + +\pagenumbering{arabic} + +\renewcommand{\chaptermark}[1]{\markboth{\uppercase{#1}}{}} +\renewcommand{\sectionmark}[1]{\markright{\thesection.\ #1}{}} +\lhead[\fancyplain{}{\bfseries \thepage}]{\bfseries \rightmark} +\rhead[\fancyplain{}{\bfseries \leftmark}]{\bfseries \thepage} +\cfoot{\copyright 2001 convergence integrated media GmbH} + +\input{intro.tex} + +\input{devices.tex} + +\input{examples.tex} + +\cleardoublepage + +\appendix + +\cleardoublepage + +\thispagestyle{plain}\chaptermark{Bibliography} +\addcontentsline{toc}{chapter}{Bibliography} +\bibliographystyle{bibsec} +\bibliography{main} + +\cleardoublepage + +\thispagestyle{plain}\chaptermark{Subject Index} +\addcontentsline{toc}{chapter}{Subject Index} +%\printindex + +\cleardoublepage + +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/dvb-spec/dvbapi/dvbstb.fig b/dvb-spec/dvbapi/dvbstb.fig new file mode 100644 index 000000000..0a6bbadc3 --- /dev/null +++ b/dvb-spec/dvbapi/dvbstb.fig @@ -0,0 +1,59 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1620 360 2520 360 2520 900 1620 900 1620 360 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1260 1080 1620 630 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2520 630 2880 630 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2880 360 3780 360 3780 900 2880 900 2880 360 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4590 900 3330 1170 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4590 900 4590 1170 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4140 360 5040 360 5040 900 4140 900 4140 360 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3780 630 4140 630 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4140 1170 5040 1170 5040 1710 4140 1710 4140 1170 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2880 1170 3780 1170 3780 1710 2880 1710 2880 1170 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1620 1170 2520 1170 2520 1710 1620 1710 1620 1170 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1620 1440 1260 1080 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1350 225 5175 225 5175 1845 1350 1845 1350 225 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3240 1710 3960 2070 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4590 1710 3960 2070 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3510 2070 4410 2070 4410 2610 3510 2610 3510 2070 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 360 810 1260 810 1260 1350 360 1350 360 810 +4 0 0 50 0 0 12 0.0000 4 135 675 1755 675 Frontend\001 +4 0 0 50 0 0 12 0.0000 4 135 690 4275 675 Demuxer\001 +4 0 0 50 0 0 12 0.0000 4 135 450 4365 1485 Video\001 +4 0 0 50 0 0 12 0.0000 4 135 450 3105 1485 Audio\001 +4 0 0 50 0 0 12 0.0000 4 135 345 1890 1485 SEC\001 +4 0 0 50 0 0 12 0.0000 4 135 255 3195 675 CA\001 +4 0 0 50 0 0 12 0.0000 4 135 645 495 1125 Antenna\001 +4 0 0 50 0 0 12 0.0000 4 135 240 3870 2385 TV\001 diff --git a/dvb-spec/dvbapi/examples.tex b/dvb-spec/dvbapi/examples.tex new file mode 100644 index 000000000..d2786a6f6 --- /dev/null +++ b/dvb-spec/dvbapi/examples.tex @@ -0,0 +1,365 @@ +\chapter{Examples} +In this section we would like to present some examples for using the DVB API. + +\section{Tuning} +We will start with a generic tuning subroutine that uses the frontend +and SEC, as well as the demux devices. The example is given for QPSK +tuners, but can easily be adjusted for QAM. + +{\small +\begin{verbatim} +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> + +#include <ost/dmx.h> +#include <ost/frontend.h> +#include <ost/sec.h> +#include <sys/poll.h> + +#define DMX "/dev/ost/demux" +#define QPSK "/dev/ost/qpskfe" +#define SEC "/dev/ost/sec" + +/* routine for checking if we have a signal */ +int has_signal(int front) +{ + feStatus stat; + + if ( front < 0 ){ + if((front = open(QPSK,O_RDWR)) < 0){ + perror("FRONTEND DEVICE: "); + return -1; + } + } + + FEReadStatus(front, &stat); + if (stat & FE_HAS_SIGNAL) + return 0; + else { + printf("Tuning failed\n"); + return -1; + } +} + +/* tune qpsk */ +/* freq: frequency of transponder */ +/* vpid, apid, tpid: PIDs of video, audio and teletext TS packets */ +/* diseqc: DiSEqC address of the used LNB */ +/* pol: Polarisation */ +/* srate: Symbol Rate */ +/* fec. FEC */ +/* lnb_lof1: local frequency of lower LNB band */ +/* lnb_lof2: local frequency of upper LNB band */ +/* lnb_slof: switch frequency of LNB */ + +int set_qpsk_channel(int freq, int vpid, int apid, int tpid, + int diseqc, int pol, int srate, int fec, int lnb_lof1, + int lnb_lof2, int lnb_slof) +{ + struct secCommand scmd; + struct secCmdSequence scmds; + struct dmxPesFilterParams pesFilterParams; + struct qpskParameters qpsk; + struct pollfd pfd[1]; + struct qpskEvent event; + int front, sec, demux1, demux2, demux3; + + /* Open all the necessary the devices */ + + if((front = open(QPSK,O_RDWR)) < 0){ + perror("FRONTEND DEVICE: "); + return -1; + } + + if((sec = open(SEC,O_RDWR)) < 0){ + perror("SEC DEVICE: "); + return -1; + } + + if ((demux1 = open(DMX, O_RDWR|O_NONBLOCK)) < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + + if ((demux2 = open(DMX, O_RDWR|O_NONBLOCK)) < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + + if ((demux3 = open(DMX, O_RDWR|O_NONBLOCK)) < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + + /* Set the frequency of the transponder, taking into account the + local frequencies of the LNB */ + + if (freq < lnb_slof) { + qpsk.iFrequency = (freq - lnb_lof1); + scmds.continuousTone = SEC_TONE_OFF; + } else { + qpsk.iFrequency = (freq - lnb_lof2); + scmds.continuousTone = SEC_TONE_ON; + } + + /* Set the polarity of the transponder by setting the correct + voltage on the universal LNB */ + + if (pol) scmds.voltage = SEC_VOLTAGE_18; + else scmds.voltage = SEC_VOLTAGE_13; + + /* In case we have a DiSEqC, set it to the correct address */ + + scmd.type=0; + scmd.u.diseqc.addr=0x10; + scmd.u.diseqc.cmd=0x38; + scmd.u.diseqc.numParams=1; + scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) | + (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | + (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); + + scmds.miniCommand=SEC_MINI_NONE; + scmds.numCommands=1; + scmds.commands=&scmd; + + /* Send the data to the SEC device to prepare the LNB for tuning */ + if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ + perror("SEC SEND: "); + return -1; + } + + /* Set symbol rate and FEC */ + + qpsk.SymbolRate = srate; + qpsk.FEC_inner = fec; + + /* Now send it all to the frontend device */ + if (ioctl(front, QPSK_TUNE, &qpsk) < 0){ + perror("QPSK TUNE: "); + return -1; + } + + /* poll for QPSK event to check if tuning worked */ + pfd[0].fd = front; + pfd[0].events = POLLIN; + + if (poll(pfd,1,3000)){ + if (pfd[0].revents & POLLIN){ + printf("Getting QPSK event\n"); + if ( ioctl(front, QPSK_GET_EVENT, &event) + + == -EBUFFEROVERFLOW){ + perror("qpsk get event"); + return -1; + } + printf("Received "); + switch(event.type){ + case FE_UNEXPECTED_EV: + printf("unexpected event\n"); + return -1; + case FE_FAILURE_EV: + printf("failure event\n"); + return -1; + case FE_COMPLETION_EV: + printf("completion event\n"); + } + } + } + + + /* Set the filters for video, audio and teletext demuxing */ + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pesType = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_vpid"); + return -1; + } + + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pesType = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_apid"); + return -1; + } + + pesFilterParams.pid = tpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pesType = DMX_PES_TELETEXT; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_tpid"); + return -1; + } + + /* check if we have a signal */ + return has_signal(front); +} + +\end{verbatim} +} +The program assumes that you are using a universal LNB and a standard +DiSEqC switch with up to 4 addresses. Of course, you could build in +some more checking if tuning was successful and maybe try to repeat +the tuning process. Depending on the external hardware, i.e. LNB and +DiSEqC switch, and weather conditions this may be necessary. + + +\section{The DVR device} +The following program code shows how to use the DVR device for +recording. + +{\small +\begin{verbatim} +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> + +#include <ost/dmx.h> +#include <ost/video.h> +#include <sys/poll.h> +#define DVR "/dev/ost/dvr" +#define AUDIO "/dev/ost/audio" +#define VIDEO "/dev/ost/video" + +#define BUFFY (188*20) +#define MAX_LENGTH (1024*1024*5) /* record 5MB */ + + +/* switch the demuxes to recording, assuming the transponder is tuned */ + +/* demux1, demux2: file descriptor of video and audio filters */ +/* vpid, apid: PIDs of video and audio channels */ + +int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid) +{ + struct dmxPesFilterParams pesFilterParams; + + if (demux1 < 0){ + if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux2 < 0){ + if ((demux2=open(DMXdemuxs, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pesType = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pesType = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + return 0; +} + +/* start recording MAX_LENGTH , assuming the transponder is tuned */ + +/* demux1, demux2: file descriptor of video and audio filters */ +/* vpid, apid: PIDs of video and audio channels */ +int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid) +{ + int i; + int len; + int written; + uint8_t buf[BUFFY]; + uint64_t length; + struct pollfd pfd[1]; + int dvr, dvr_out; + + /* open dvr device */ + if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){ + perror("DVR DEVICE"); + return -1; + } + + /* switch video and audio demuxes to dvr */ + printf ("Switching dvr on\n"); + i = switch_to_record(demux1, demux2, vpid, apid); + printf("finished: "); + + printf("Recording %2.0f MB of test file in TS format\n", + MAX_LENGTH/(1024.0*1024.0)); + length = 0; + + /* open output file */ + if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT + |O_TRUNC, S_IRUSR|S_IWUSR + |S_IRGRP|S_IWGRP|S_IROTH| + S_IWOTH)) < 0){ + perror("Can't open file for dvr test"); + return -1; + } + + pfd[0].fd = dvr; + pfd[0].events = POLLIN; + + /* poll for dvr data and write to file */ + while (length < MAX_LENGTH ) { + if (poll(pfd,1,1)){ + if (pfd[0].revents & POLLIN){ + len = read(dvr, buf, BUFFY); + if (len < 0){ + perror("recording"); + return -1; + } + if (len > 0){ + written = 0; + while (written < len) + written += + write (dvr_out, + buf, len); + length += len; + printf("written %2.0f MB\r", + length/1024./1024.); + } + } + } + } + return 0; +} + +\end{verbatim} +} +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% TeX-master: t +%%% End: diff --git a/dvb-spec/dvbapi/fig2pstex b/dvb-spec/dvbapi/fig2pstex new file mode 100755 index 000000000..bf62eb7ec --- /dev/null +++ b/dvb-spec/dvbapi/fig2pstex @@ -0,0 +1,6 @@ +#!/bin/sh +f=`basename $1 .fig` +fig2dev -L pstex $f.fig $f.ps +fig2dev -L pstex_t -p $f.ps $f.fig $f.pst2 +./getbb $f.pst2 $f.ps > $f.pst +rm $f.pst2
\ No newline at end of file diff --git a/dvb-spec/dvbapi/getbb b/dvb-spec/dvbapi/getbb new file mode 100755 index 000000000..004714d3a --- /dev/null +++ b/dvb-spec/dvbapi/getbb @@ -0,0 +1,12 @@ +#!/bin/sh +f=`grep BoundingBox $2 | cut -d' ' -f2,3,4,5` +g=`\ +echo $2" llx=";(echo $f|cut -d' ' -f1 );\ +echo " lly=";(echo $f|cut -d' ' -f2 );\ +echo " urx=";(echo $f|cut -d' ' -f3 );\ +echo " ury=";(echo $f|cut -d' ' -f4 );\ +echo " rwi=";(echo $f|cut -d' ' -f3 );\ +echo "0" +` +h=`echo $g| sed "s/= /=/g" | sed "s/ 0/0/g"` +cat $1 | sed "s/psfile=$2/psfile=$h/" diff --git a/dvb-spec/dvbapi/intro.tex b/dvb-spec/dvbapi/intro.tex new file mode 100644 index 000000000..acb6b4b85 --- /dev/null +++ b/dvb-spec/dvbapi/intro.tex @@ -0,0 +1,192 @@ +\chapter{Introduction} +%\addcontentsline{toc}{part}{Introduction} +%\chaptermark{Introduction} +\section{What you need to know} +The reader of this document is required to have some knowledge in the +area of digital video broadcasting (DVB) and should be familiar with +part I of ISO/IEC 13818, i.e you should know what a +program/transport stream (PS/TS) is and what is meant by a packetized elementary +stream (PES) or an I-frame. + +It is also necessary to know how to access unix/linux devices and how +to use ioctl calls. This also includes the knowledge of C or C++. +\section{History} + +The first API for DVB cards we used at Convergence in late 1999 +was an extension of the Video4Linux API which was primarily +developed for frame grabber cards. +As such it was not really well suited to be used for DVB cards and +their new features like recording MPEG streams and filtering several +section and PES data streams at the same time. + +In early 2000, we were approached by Nokia with a proposal for a new +standard Linux DVB API. +As a commitment to the development of terminals based on open standards, +Nokia and Convergence made it available to all Linux developers and +published it on \texttt{http://www.linuxtv.org/} in September 2000. +Convergence is the maintainer of the Linux DVB API. +Together with the LinuxTV community (i.e. you, the reader of this document), +the Linux DVB API will be constantly reviewed and improved upon. +With the Linux driver for the Siemens/Hauppauge DVB PCI card Convergence +provides a first implementation of the Linux DVB API. + + +\section{Overview} + +\begin{figure}[htbp] + \begin{center} + \includegraphics{dvbstb.ps} + \caption{Components of a DVB card/STB} + \label{fig:dvbstb} + \end{center} +\end{figure} + + +A DVB PCI card or DVB set-top-box (STB) usually consists of the following +main hardware components: +\begin{itemize} +\item Frontend consisting of tuner and DVB demodulator + +Here the raw signal reaches the DVB hardware from a satellite dish or antenna +or directly from cable. The frontend down-converts and demodulates +this signal into an MPEG transport stream (TS). + +\item SEC for controlling external hardware like LNBs and antennas + +This part of the hardware can send signals back through the satellite +cable to control the polarization of the LNB, to switch between +different LNBs or even to control the movements of a dish rotor. + + +\item Conditional Access (CA) hardware like CI adapters and smartcard slots + +The complete TS is passed through the CA hardware. Programs to which +the user has access (controlled by the smart card) are decoded in real +time and re-inserted into the TS. + +\item Demultiplexer which filters the incoming DVB stream + +The demultiplexer splits the TS into its components like audio and video +streams. Besides usually several of such audio and video streams it also +contains data strams with information about the programs offered in this +or other streams of the same provider. + +\item MPEG2 audio and video decoder + +The main targets of the demultiplexer are the MPEG2 audio and video +decoders. After decoding the pass on the uncompressed audio +and video to the computer screen or (through a PAL/NTSC encoder) to +a TV set. +\end{itemize} +Figure \ref{fig:dvbstb} shows a crude schematic of the control and data flow +between those components. + +On a DVB PCI card not all of these have to be present since some +functionality can be provided by the main CPU of the PC (e.g. MPEG picture +and sound decoding) or is not needed (e.g. for data-only uses like +``internet over satellite''). +Also not every card or STB provides conditional access hardware. + +\section{Linux DVB Devices} + +The Linux DVB API lets you control these hardware components +through currently six Unix-style character devices for +video, audio, frontend, SEC, demux and CA. +The video and audio devices control the MPEG2 decoder hardware, +the frontend device the tuner and the DVB demodulator. +External hardware like DiSEqC switches and rotors can be controlled +through the SEC device. +The demux device gives you control over the PES and section filters +of the hardware. If the hardware does not support filtering these filters +can be implemented in software. +Finally, the CA device controls all the conditional access capabilities +of the hardware. It can depend on the individual security requirements +of the platform, if and how many of the CA functions are made available +to the application through this device. + +All devices can be found in the \texttt{/dev} tree under +\texttt{/dev/ost}, where OST stands for Open Standards Terminal. +The individual devices are called +\begin{itemize} +\item \texttt{/dev/ost/audio}, +\item \texttt{/dev/ost/video}, +\item \texttt{/dev/ost/qpskfe}, +\item \texttt{/dev/ost/qamfe}, +\item \texttt{/dev/ost/sec}, +\item \texttt{/dev/ost/demux}, +\item \texttt{/dev/ost/ca}, +\end{itemize} +but we will omit the ``\texttt{/dev/ost/}'' in the further dicussion of +these devices. + +%Thus, the \texttt{audio} and \texttt{video} devices directly control +%the MPEG2 decoder audio and video decoder, respectively. +%Depending on the kind of frontend present (satellite, cable or +%terrestrial), it will be controlled either through the +%\texttt{qpsk} or \texttt{qamfe} device. +%DiSEqC or other kinds of control signals can be sent to the +%antenna hardware through the \texttt{sec} device. + +If more than one card is present in the system the other cards +can be accessed through the corresponding devices with the +card's number appended. \texttt{/dev/ost/demux0} (which +is identical to \texttt{/dev/ost/demux}) would, e.g., control the +demultiplexer of the first card, while \texttt{/dev/ost/demux1} +would control the demultiplexer of the second card, and so on. + +More details about the data structures and function calls of +all the devices are described in the following chapters. + + +\section{DVB Devices with Devfs} + +Recent Linux kernel versions support a special file system called +\textsl{devfs} which is a replacement for the traditional +device directory. +With devfs a Linux DVB driver will only create those device file entries +which actually exist. +It also makes dealing with more complex DVB hardware much easier. +The device structure described above is not well suited to deal +with multiple DVB cards with more than one frontend or demultiplexer. +Consider, e.g., two DVB cards, one with two frontends and +one demultiplexer, the other with one frontend and two demultiplexers. +If we just assign them consecutive numbers, there would be a demultiplexer +and a frontend which do notbelong to the same card but have +the same number. + +With \textsl{devfs} we propose a different scheme for the device names. +The root directory for all DVB cards will be \texttt{/dev/dvb}. +Each card gets assigned a sub-directory with the name \texttt{/dev/card0}, +\texttt{/dev/card1}, etc. +The files created in these sub-directories will correspond directly to the +hardware actually present on the card. +Thus, if the first card has one QAM frontend, one demultiplexer +and otherwise no other hardware, +only \texttt{/dev/dvb/card0/qamfe0} and \texttt{/dev/dvb/card0/demux0} +will be created. +When a second DVB-S card with one frontend (including SEC) device, +two demultiplexers and an MPEG2 audio/video decoder is added, the +complete \texttt{/dev/dvb} tree will look like this: + +\begin{verbatim} +/dev/dvb/card0/qam0 + demux0 + +/dev/dvb/card1/video0 + audio0 + demux0 + demux1 + qpskfe0 + sec0 +\end{verbatim} + + +\section{Using the Devices} + +\dots + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/kdapi.tex b/dvb-spec/dvbapi/kdapi.tex new file mode 100644 index 000000000..6cee25c85 --- /dev/null +++ b/dvb-spec/dvbapi/kdapi.tex @@ -0,0 +1,1007 @@ +\devsec{Kernel Demux API} + +The kernel demux API + +\devsubsec{Kernel Demux Data Types} + +\devsubsubsec{dmx\_success\_t} +\label{dmxsuccesst} + +\begin{verbatim} +typedef enum { + DMX_OK = 0, /* Received Ok */ + DMX_LENGTH_ERROR, /* Incorrect length */ + DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ + DMX_CRC_ERROR, /* Incorrect CRC */ + DMX_FRAME_ERROR, /* Frame alignment error */ + DMX_FIFO_ERROR, /* Receiver FIFO overrun */ + DMX_MISSED_ERROR /* Receiver missed packet */ +} dmx_success_t; +\end{verbatim} + + +\devsubsubsec{TS filter types} +\label{tsfiltertypes} + +\begin{verbatim} +/*--------------------------------------------------------------------------*/ +/* TS packet reception */ +/*--------------------------------------------------------------------------*/ + +/* TS filter type for set_type() */ + +#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */ +#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS + payload (<=184 bytes per packet) to callback */ +#define TS_DECODER 4 /* send stream to built-in decoder (if present) */ +\end{verbatim} + + +\devsubsubsec{dmx\_ts\_pes\_t} +\label{dmxtspest} + +The structure +/\begin{verbatim} +typedef enum +{ + DMX_TS_PES_AUDIO, /* also send packets to audio decoder (if it exists) */ + DMX_TS_PES_VIDEO, /* ... */ + DMX_TS_PES_TELETEXT, + DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, + DMX_TS_PES_OTHER, +} dmx_ts_pes_t; +\end{verbatim} +describes the PES type for filters which write to +a built-in decoder. +The correspond (and should be kept identical) to the types in +the demux device. + +\begin{verbatim} +struct dmx_ts_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_ts_feed_s* feed, + __u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_ts_feed_s* feed); + int (*stop_filtering) (struct dmx_ts_feed_s* feed); + int (*set_type) (struct dmx_ts_feed_s* feed, + int type, + dmx_ts_pes_t pes_type); +}; + +typedef struct dmx_ts_feed_s dmx_ts_feed_t; +\end{verbatim} + +\begin{verbatim} +/*--------------------------------------------------------------------------*/ +/* PES packet reception (not supported yet) */ +/*--------------------------------------------------------------------------*/ + +typedef struct dmx_pes_filter_s { + struct dmx_pes_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_pes_filter_t; +\end{verbatim} + +\begin{verbatim} +typedef struct dmx_pes_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_pes_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_pes_feed_s* feed); + int (*stop_filtering) (struct dmx_pes_feed_s* feed); + int (*allocate_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t** filter); + int (*release_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t* filter); +} dmx_pes_feed_t; +\end{verbatim} + + +\begin{verbatim} +\label{sectionfilter} +typedef struct { + __u8 filter_value [DMX_MAX_FILTER_SIZE]; + __u8 filter_mask [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_section_filter_t; +\end{verbatim} + +\begin{verbatim} +struct dmx_section_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_section_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + int check_crc); + int (*allocate_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t** filter); + int (*release_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t* filter); + int (*start_filtering) (struct dmx_section_feed_s* feed); + int (*stop_filtering) (struct dmx_section_feed_s* feed); +}; +typedef struct dmx_section_feed_s dmx_section_feed_t; + +/*--------------------------------------------------------------------------*/ +/* Callback functions */ +/*--------------------------------------------------------------------------*/ + +typedef int (*dmx_ts_cb) ( __u8 * buffer1, + size_t buffer1_length, + __u8 * buffer2, + size_t buffer2_length, + dmx_ts_feed_t* source, + dmx_success_t success); + +typedef int (*dmx_section_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_section_filter_t * source, + dmx_success_t success); + +typedef int (*dmx_pes_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_pes_filter_t* source, + dmx_success_t success); + +/*--------------------------------------------------------------------------*/ +/* DVB Front-End */ +/*--------------------------------------------------------------------------*/ + +typedef enum { + DMX_OTHER_FE = 0, + DMX_SATELLITE_FE, + DMX_CABLE_FE, + DMX_TERRESTRIAL_FE, + DMX_LVDS_FE, + DMX_ASI_FE, /* DVB-ASI interface */ + DMX_MEMORY_FE +} dmx_frontend_source_t; + +typedef struct { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique front-end identifier */ + char* vendor; /* Name of the front-end vendor */ + char* model; /* Name of the front-end model */ + struct list_head connectivity_list; /* List of front-ends that can + be connected to a particular + demux */ + void* priv; /* Pointer to private data of the API client */ + dmx_frontend_source_t source; +} dmx_frontend_t; + +/*--------------------------------------------------------------------------*/ +/* MPEG-2 TS Demux */ +/*--------------------------------------------------------------------------*/ + +/* + * Flags OR'ed in the capabilites field of struct dmx_demux_s. + */ + +#define DMX_TS_FILTERING 1 +#define DMX_PES_FILTERING 2 +#define DMX_SECTION_FILTERING 4 +#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */ +#define DMX_CRC_CHECKING 16 +#define DMX_TS_DESCRAMBLING 32 +#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 +#define DMX_MAC_ADDRESS_DESCRAMBLING 128 +\end{verbatim} + +\devsubsubsec{demux\_demux\_t} +\label{demuxdemuxt} + +\begin{verbatim} +/* + * DMX_FE_ENTRY(): Casts elements in the list of registered + * front-ends from the generic type struct list_head + * to the type * dmx_frontend_t + *. +*/ + +#define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) + +struct dmx_demux_s { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique demux identifier */ + char* vendor; /* Name of the demux vendor */ + char* model; /* Name of the demux model */ + __u32 capabilities; /* Bitfield of capability flags */ + dmx_frontend_t* frontend; /* Front-end connected to the demux */ + struct list_head reg_list; /* List of registered demuxes */ + void* priv; /* Pointer to private data of the API client */ + int users; /* Number of users */ + int (*open) (struct dmx_demux_s* demux); + int (*close) (struct dmx_demux_s* demux); + int (*write) (struct dmx_demux_s* demux, const char* buf, size_t count); + int (*allocate_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t** feed, + dmx_ts_cb callback); + int (*release_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t* feed); + int (*allocate_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t** feed, + dmx_pes_cb callback); + int (*release_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t* feed); + int (*allocate_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t** feed, + dmx_section_cb callback); + int (*release_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t* feed); + int (*descramble_mac_address) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, + size_t buffer2_length, + __u16 pid); + int (*descramble_section_payload) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, size_t buffer2_length, + __u16 pid); + int (*add_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*remove_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + struct list_head* (*get_frontends) (struct dmx_demux_s* demux); + int (*connect_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*disconnect_frontend) (struct dmx_demux_s* demux); + + + /* added because js cannot keep track of these himself */ + int (*get_pes_pids) (struct dmx_demux_s* demux, __u16 *pids); +}; +typedef struct dmx_demux_s dmx_demux_t; +\end{verbatim} + + +\devsubsubsec{Demux directory} +\label{demuxdir} + +\begin{verbatim} +/* + * DMX_DIR_ENTRY(): Casts elements in the list of registered + * demuxes from the generic type struct list_head* to the type dmx_demux_t + *. + */ + +#define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) + +int dmx_register_demux (dmx_demux_t* demux); +int dmx_unregister_demux (dmx_demux_t* demux); +struct list_head* dmx_get_demuxes (void); +\end{verbatim} + +\clearpage + +\devsubsec{Demux Directory API} + +The demux directory is a Linux kernel-wide facility for registering and +accessing the MPEG-2 TS demuxes in the system. Run-time registering and +unregistering of demux drivers is possible using this API. + +All demux drivers in the directory implement the abstract interface dmx\_demux\_t. + +\kifunction{dmx\_register\_demux()}{ + int dmx\_register\_demux ( dmx\_demux\_t *demux ) + }{ + This function makes a demux driver interface available to the Linux kernel. + It is usually called by the init\_module() function of the kernel module that + contains the demux driver. The caller of this function is responsible for + allocating dynamic or static memory for the demux structure and for initializing + its fields before calling this function. + The memory allocated for the demux structure must not be freed before calling + dmx\_unregister\_demux(), + }{ + dmx\_demux\_t* demux & Pointer to the demux structure. + }{ + 0 & The function was completed without errors.\\ + -EEXIST & A demux with the same value of the id field + already stored in the directory.\\ + -ENOSPC & No space left in the directory. +} + +\kifunction{dmx\_unregister\_demux()}{ + int dmx\_unregister\_demux ( dmx\_demux\_t *demux ) + }{ + This function is called to indicate that the given demux interface is no longer + available. The caller of this function is responsible for freeing the memory of + the demux structure, if it was dynamically allocated before calling + dmx\_register\_demux(). + The cleanup\_module() function of the kernel module that contains the demux + driver should call this function. Note that this function fails if the demux + is currently in use, i.e., release\_demux() has not been called for the + interface. + }{ + dmx\_demux\_t* demux & Pointer to the demux structure which is to be unregistered. + }{ + 0 & The function was completed without errors.\\ + ENODEV & The specified demux is not registered in the demux directory.\\ + EBUSY & The specified demux is currently in use. +} + +\kifunction{dmx\_get\_demuxes()}{ + struct list\_head *dmx\_get\_demuxes () + }{ + Provides the caller with the list of registered demux interfaces, using the + standard list structure defined in the include file linux/list.h. + The include file demux.h defines the macro DMX\_DIR\_ENTRY() for converting an + element of the generic type struct list\_head* to the type dmx\_demux\_t*. + The caller must not free the memory of any of the elements obtained via this + function call. + }{ + none + }{ + struct list\_head * & + A list of demux interfaces, or NULL in the case of an empty list. +} + +\clearpage + +\devsubsec{Demux API} + +The demux API should be implemented for each demux in the system. It is used to +select the TS source of a demux and to manage the demux resources. When the +demux client allocates a resource via the demux API, it receives a pointer +to the API of that resource. + +Each demux receives its TS input from a DVB front-end or from memory, as +set via the demux API. In a system with more than one front-end, the API can +be used to select one of the DVB front-ends as a TS source for a demux, unless +this is fixed in the HW platform. The demux API only controls front-ends +regarding their connections with demuxes; the APIs used to set the other +front-end parameters, such as tuning, are not defined in this document. + +The functions that implement the abstract interface demux should be defined +static or module private and registered to the Demux Directory for external +access. It is not necessary to implement every function in the demux\_t struct, +however (for example, a demux interface might support Section filtering, but +not TS or PES filtering). The API client is expected to check the value of any +function pointer before calling the function: the value of NULL means ``function +not available''. + +Whenever the functions of the demux API modify shared data, the possibilities +of lost update and race condition problems should be addressed, e.g. by +protecting parts of code with mutexes. This is especially important on +multi-processor hosts. + +Note that functions called from a bottom half context must not sleep, at least +in the 2.2.x kernels. Even a simple memory allocation can result in a kernel +thread being put to sleep if swapping is needed. For example, the Linux kernel +calls the functions of a network device interface from a bottom half context. +Thus, if a demux API function is called from network device code, the function +must not sleep. + +\kfunction{open()}{ + int open ( demux\_t* demux ); + }{ + This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. + It should be possible for multiple clients to access the demux at the same time. + Thus, the function implementation should increment the demux usage count when + open() is called and decrement it when close() is called. + }{ + demux\_t* demux & Pointer to the demux API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EUSERS & Maximum usage count reached.\\ + -EINVAL & Bad parameter. +} + +\kfunction{close()}{ + int close(demux\_t* demux); + }{ + This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. + It should be possible for multiple clients to access the demux at the same time. + Thus, the function implementation should increment the demux usage count when + open() is called and decrement it when close() is called. + }{ + demux\_t* demux & Pointer to the demux API and instance data. + }{ + 0 & The function was completed without errors.\\ + -ENODEV & The demux was not in use.\\ + -EINVAL & Bad parameter. +} + +\kfunction{write()}{ + int write(demux\_t* demux, const char* buf, size\_t count); + }{ + This function provides the demux driver with a memory buffer containing TS + packets. Instead of receiving TS packets from the DVB front-end, the demux + driver software will read packets from memory. Any clients of this demux + with active TS, PES or Section filters will receive filtered data via the Demux + callback API (see 0). The function returns when all the data in the buffer has + been consumed by the demux. + Demux hardware typically cannot read TS from memory. If this is the case, + memory-based filtering has to be implemented entirely in software. + }{ + demux\_t* demux & Pointer to the demux API and instance data.\\ + const char* buf & Pointer to the TS data in kernel-space memory.\\ + size\_t length & Length of the TS data. + }{ + 0 & The function was completed without errors.\\ + -ENOSYS & The command is not implemented.\\ + -EINVAL & Bad parameter. +} + +\kifunction{allocate\_ts\_feed()}{ + int allocate\_ts\_feed(dmx\_demux\_t* demux, + dmx\_ts\_feed\_t** feed, dmx\_ts\_cb callback); + }{ + Allocates a new TS feed, which is used to filter the TS packets carrying a + certain PID. + The TS feed normally corresponds to a hardware PID filter on the demux chip. + }{ + demux\_t* demux & Pointer to the demux API and instance data.\\ + dmx\_ts\_feed\_t** feed & Pointer to the TS feed API and instance data.\\ + dmx\_ts\_cb callback & Pointer to the callback function for + passing received TS packet + }{ + 0 & The function was completed without errors.\\ + -EBUSY & No more TS feeds available.\\ + -ENOSYS & The command is not implemented.\\ + -EINVAL & Bad parameter. +} + +\kifunction{release\_ts\_feed()}{ + int release\_ts\_feed(dmx\_demux\_t* demux, dmx\_ts\_feed\_t* feed); + }{ + Releases the resources allocated with allocate\_ts\_feed(). Any filtering in progress + on the TS feed should be stopped before calling this function. + }{ + demux\_t* demux & Pointer to the demux API and instance data.\\ + dmx\_ts\_feed\_t* feed & Pointer to the TS feed API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\kifunction{allocate\_section\_feed()}{ + int allocate\_section\_feed(dmx\_demux\_t* demux, dmx\_section\_feed\_t **feed, + dmx\_section\_cb callback); + }{ + Allocates a new section feed, i.e. a demux resource for filtering and + receiving sections. + On platforms with hardware support for section filtering, a section feed is directly + mapped to the demux HW. On other platforms, TS packets are first PID filtered in + hardware and a hardware section filter then emulated in software. + The caller obtains an API pointer of type dmx\_section\_feed\_t as an out parameter. + Using this API the caller can set filtering parameters and start receiving sections. + }{ + demux\_t *demux & Pointer to the demux API and instance data.\\ + dmx\_section\_feed\_t **feed & Pointer to the section feed API and instance data.\\ + dmx\_section\_cb callback & Pointer to the callback function for + passing received sections. + }{ + 0 & The function was completed without errors.\\ + -EBUSY & No more section feeds available.\\ + -ENOSYS & The command is not implemented.\\ + -EINVAL & Bad parameter. +} + + +\kifunction{release\_section\_feed()}{ + int release\_section\_feed(dmx\_demux\_t* demux, dmx\_section\_feed\_t *feed); + }{ + Releases the resources allocated with allocate\_section\_feed(), including allocated + filters. + Any filtering in progress on the section feed should be stopped before calling + this function. + }{ + demux\_t *demux & Pointer to the demux API and instance data.\\ + dmx\_section\_feed\_t *feed & Pointer to the section feed API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\kifunction{descramble\_mac\_address()}{ + int descramble\_mac\_address(dmx\_demux\_t* demux, + \_\_u8 *buffer1, size\_t buffer1\_length, + \_\_u8 *buffer2, size\_t buffer2\_length, \_\_u16 pid); + }{ + This function runs a descrambling algorithm on the destination MAC address field of a + DVB Datagram Section, replacing the original address with its un-encrypted version. + Otherwise, the description on the function descramble\_section\_payload() applies + also to this function. + }{ + dmx\_demux\_t *demux & Pointer to the demux API and instance data.\\ + \_\_u8 *buffer1 & Pointer to the first byte of the section.\\ + size\_t buffer1\_length & Length of the section data, including headers and CRC, + in buffer1.\\ + \_\_u8* buffer2 & Pointer to the tail of the section data, or NULL. The pointer has a + non-NULL value if the section wraps + past the end of a circular buffer.\\ + size\_t buffer2\_length & Length of the section data, + including headers and CRC, in buffer2.\\ + \_\_u16 pid & The PID on which the section was received. Useful for obtaining the + descrambling key, e.g. from a DVB Common Access facility. + }{ + 0 & The function was completed without errors.\\ + -ENOSYS & No descrambling facility available.\\ + -EINVAL & Bad parameter. +} + +\kifunction{descramble\_section\_payload()}{ + int descramble\_section\_payload(dmx\_demux\_t* demux, + \_\_u8 *buffer1, size\_t buffer1\_length, \_\_u8 *buffer2, size\_t + buffer2\_length, \_\_u16 pid); + }{ + This function runs a descrambling algorithm on the payload of a DVB Datagram + Section, replacing the original payload with its un-encrypted version. + The function will + be called from the demux API implementation; the API client need + not call this function directly. + Section-level scrambling algorithms are currently standardized only for DVB-RCC + (return channel over 2-directional cable TV network) systems. For all other DVB + networks, encryption schemes are likely to be proprietary to each data broadcaster. + Thus, it is expected that this function pointer will have the value of NULL + (i.e., function not available) in most demux API implementations. + Nevertheless, it should be possible + to use the function pointer as a hook for dynamically adding a ``plug-in'' + descrambling facility to a demux driver.\\ + While this function is not needed with hardware-based section descrambling, the + descramble\_section\_payload function pointer can be used to override the default + hardware-based descrambling algorithm: if the function pointer has a non-NULL value, + the corresponding function should be used instead of any descrambling hardware. + }{ + dmx\_demux\_t *demux & Pointer to the demux API and instance data.\\ + \_\_u8 *buffer1 & Pointer to the first byte of the section.\\ + size\_t buffer1\_length & Length of the section data, including headers and CRC, in + buffer1.\\ + \_\_u8 *buffer2 & Pointer to the tail of the section data, or NULL. The pointer has a + non-NULL value if the section wraps + past the end of a circular buffer.\\ + size\_t buffer2\_length & Length of the section data, including headers and CRC, in + buffer2.\\ + \_\_u16 pid & The PID on which the section was received. Useful for obtaining the + descrambling key, e.g. from a DVB Common Access facility. + }{ + 0 & The function was completed without errors.\\ + -ENOSYS & No descrambling facility available.\\ + -EINVAL & Bad parameter. +} + +\kifunction{add\_frontend()}{ + int add\_frontend(dmx\_demux\_t *demux, dmx\_frontend\_t *frontend); + }{ + Registers a connectivity between a demux and a front-end, i.e., indicates that the + demux can be connected via a call to connect\_frontend() to use the given front-end + as a TS source. The client of this function has to allocate dynamic or static + memory for + the frontend structure and initialize its fields before calling this function. + This function is normally called during the driver initialization. + The caller must not free + the memory of the frontend struct before successfully calling remove\_frontend(). + }{ + dmx\_demux\_t* demux & Pointer to the demux API and instance data.\\ + dmx\_frontend\_t* frontend & Pointer to the front-end instance data. + }{ + 0 & The function was completed without errors.\\ + -EEXIST & A front-end with the same value of the id field already registered.\\ + -EINUSE & The demux is in use.\\ + -ENOMEM & No more front-ends can be added.\\ + -EINVAL & Bad parameter. +} + +\kifunction{remove\_frontend()}{ + int remove\_frontend(dmx\_demux\_t* demux, dmx\_frontend\_t* frontend); + }{ + Indicates that the given front-end, registered by a call to add\_frontend(), can no + longer be connected as a TS source by this demux. The function should be called + when a front-end driver or a demux driver is removed from the system. If the front-end + is in use, the function fails with the return value of -EBUSY. + After successfully calling this function, the caller can free the memory of + the frontend struct if it was dynamically allocated before the add\_frontend() + operation. + }{ + dmx\_demux\_t* demux & Pointer to the demux API and instance data.\\ + dmx\_frontend\_t* frontend & Pointer to the front-end instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter.\\ + -EBUSY & The front-end is in use, i.e. a call to + connect\_frontend() has not been followed by + a call to disconnect\_frontend(). +} + +\kifunction{get\_frontends()}{ + struct list\_head* get\_frontends(dmx\_demux\_t* demux); + }{ + Provides the APIs of the front-ends that have been registered for this demux. Any of + the front-ends obtained with this call can be used as a parameter for + connect\_frontend().\\ + The include file demux.h contains the macro DMX\_FE\_ENTRY() for converting an + element of the generic type struct list\_head* to the type dmx\_frontend\_t*. + The caller must not free the memory of any of the elements obtained via this function + call. + }{ + dmx\_demux\_t* demux & Pointer to the demux API and instance data. + }{ + dmx\_demux\_t* & A list of front-end interfaces, or NULL in the case of an empty list. +} + + +\kifunction{connect\_frontend()}{ + int connect\_frontend(dmx\_demux\_t* demux, dmx\_frontend\_t* frontend); + }{ + Connects the TS output of the front-end to the input of the demux. A demux can only + be connected to a front-end registered to the demux with the function + add\_frontend().\\ + It may or may not be possible to connect multiple demuxes to the same front-end, + depending on the capabilities of the HW platform. When not used, the front-end should + be released by calling disconnect\_frontend(). + }{ + dmx\_demux\_t* demux & Pointer to the demux API and instance data.\\ + dmx\_frontend\_t* frontend & Pointer to the front-end instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter.\\ + -EBUSY & The front-end is in use. +} + +\kifunction{disconnect\_frontend()}{ + int disconnect\_frontend(dmx\_demux\_t* demux); + }{ + Disconnects the demux and a front-end previously connected by a + connect\_frontend() call. + }{ + dmx\_demux\_t* demux & Pointer to the demux API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\clearpage + +\devsubsec{Demux Callback API} + +This kernel-space API comprises the callback functions that deliver filtered data to the +demux client. Unlike the other APIs, these API functions are provided by the client and +called from the demux code. + +The function pointers of this abstract interface are not packed into a structure +as in the +other demux APIs, because the callback functions are registered and used +independent of each other. As an example, it is possible for the API client to provide +several callback functions for receiving TS packets and no callbacks for PES packets +or sections. + +The functions that implement the callback API need not be re-entrant: when a demux +driver calls one of these functions, the driver is not allowed to call the +function again before the original call returns. +If a callback is triggered by a hardware interrupt, it is +recommended to use the Linux ``bottom half'' mechanism or start a tasklet instead of +making the callback function call directly from a hardware interrupt. + +\kifunction{dmx\_ts\_cb()}{ + int dmx\_ts\_cb(\_\_u8* buffer1, size\_t buffer1\_length, + \_\_u8* buffer2, size\_t buffer2\_length, + dmx\_ts\_feed\_t* source, dmx\_success\_t success); + }{ + This function, provided by the client of the demux API, is called from the + demux code. The function is only called when filtering on this TS feed has + been enabled using the start\_filtering() function. \\ + Any TS packets that match the filter settings are copied to a circular buffer. + The filtered TS packets are delivered to the client using this callback + function. The size of the circular buffer is controlled by the + circular\_buffer\_size parameter of the set() function in the TS Feed API. It is + expected that the buffer1 and buffer2 callback parameters point to addresses + within the circular buffer, but other implementations are also + possible. Note that the called party should not try to free the memory the + buffer1 and buffer2 parameters point to.\\ + When this function is called, the buffer1 parameter typically points to the + start of the first undelivered TS packet within a circular buffer. The buffer2 + buffer parameter is normally NULL, except when the received TS packets have + crossed the last address of the circular buffer and "wrapped" to the beginning + of the buffer. In the latter case the buffer1 parameter would contain an + address within the circular buffer, while the buffer2 parameter would contain + the first address of the circular buffer.\\ + The number of bytes delivered with this function (i.e. buffer1\_length + + buffer2\_length) is usually equal to the value of callback\_length parameter given + in the set() function, with one exception: if a timeout occurs before receiving + callback\_length bytes of TS data, any undelivered packets are immediately + delivered to the client by calling this function. The timeout duration is + controlled by the set() function in the TS Feed API.\\ + If a TS packet is received with errors that could not be fixed by the TS-level + forward error correction (FEC), the Transport\_error\_indicator flag of the TS + packet header should be set. The TS packet should not be discarded, as the + error can possibly be corrected by a higher layer protocol. + If the called party is slow in processing the callback, it is possible that + the circular buffer eventually fills up. If this happens, the demux driver + should discard any TS packets received while the buffer is full. The error + should be indicated to the client on the next callback by setting the success + parameter to the value of DMX\_OVERRUN\_ERROR.\\ + The type of data returned to the callback can be selected by the + new function int (*set\_type) (struct dmx\_ts\_feed\_s* feed, int type, + dmx\_ts\_pes\_t pes\_type) which is part of the dmx\_ts\_feed\_s struct + (also cf. to the include file ost/demux.h) + The type parameter decides if the raw TS packet (TS\_PACKET) or just the + payload (TS\_PACKET|TS\_PAYLOAD\_ONLY) should be returned. + If additionally the TS\_DECODER bit is set the stream will also be sent + to the hardware MPEG decoder. In this case, the second flag decides + as what kind of data the stream should be interpreted. + The possible choices are one of DMX\_TS\_PES\_AUDIO, DMX\_TS\_PES\_VIDEO, + DMX\_TS\_PES\_TELETEXT, DMX\_TS\_PES\_SUBTITLE, DMX\_TS\_PES\_PCR, or + DMX\_TS\_PES\_OTHER. + }{ + \_\_u8* buffer1 & Pointer to the start of the filtered TS packets.\\ + size\_t buffer1\_length & Length of the TS data in buffer1.\\ + \_\_u8* buffer2 & Pointer to the tail of the filtered TS packets, or NULL.\\ + size\_t buffer2\_length & Length of the TS data in buffer2.\\ + dmx\_ts\_feed\_t* source & Indicates which TS feed is the source of the callback.\\ + dmx\_success\_t success & Indicates if there was an error in TS reception. + }{ + 0 & Continue filtering.\\ + -1& Stop filtering - has the same effect as a call + to stop\_filtering() on the TS Feed API. +} + +\kifunction{dmx\_section\_cb()}{ + int dmx\_section\_cb(\_\_u8* buffer1, size\_t buffer1\_length, \_\_u8* buffer2, + size\_t buffer2\_length, dmx\_section\_filter\_t* source, + dmx\_success\_t success); + }{ + This function, provided by the client of the demux API, is called from the demux code. + The function is only called when filtering of sections has been enabled using the + function start\_filtering() of the section feed API. + When the demux driver has received a complete section that matches at least one + section filter, the client is notified via this callback function. Normally this function is + called for each received section; however, it is also possible to deliver multiple sections + with one callback, for example when the system load is high. + If an error occurs while receiving a section, this function should be called with the + corresponding error type set in the success field, whether or not there is data to + deliver. + The Section Feed implementation should maintain a circular buffer for received sections. + However, this is not necessary if the Section Feed API is implemented as a client of + the TS Feed API, because the TS Feed implementation then buffers the + received data. + The size of the circular buffer can be configured using the set() function in the + Section Feed API. If there is no room in the circular buffer when a new section is + received, the section must be discarded. If this happens, the value of the success + parameter should be DMX\_OVERRUN\_ERROR on the next callback. + }{ + \_\_u8* buffer1 & Pointer to the start of the filtered section, e.g. + within the circular buffer of the demux driver.\\ + size\_t buffer1\_length & Length of the filtered section data in buffer1, + including headers and CRC.\\ + \_\_u8* buffer2 & Pointer to the tail of the filtered section data, or + NULL. Useful to handle the wrapping of a circular + buffer.\\ + size\_t buffer2\_length & Length of the filtered section data in buffer2, + including headers and CRC.\\ + dmx\_section\_filter\_t* filter & Indicates the filter that triggered the callback.\\ + dmx\_success\_t success & Indicates if there was an error in section reception. + }{ + 0 & Continue filtering.\\ + -1& Stop filtering - has the same effect as a call + to stop\_filtering() on the Section Feed API. +} + +\clearpage + +\devsubsec{TS Feed API} + +A TS feed is typically mapped to a hardware PID filter on the demux chip. Using this +API, the client can set the filtering properties to start/stop filtering TS packets on a +particular TS feed. The API is defined as an abstract interface of the type +dmx\_ts\_feed\_t. + +The functions that implement the interface should be defined static or module +private. The client can get the handle of a TS feed API by calling the function +allocate\_ts\_feed() in the demux API. + +\kifunction{set()}{ + int set ( dmx\_ts\_feed\_t* feed, \_\_u16 pid, size\_t callback\_length, + size\_t circular\_buffer\_size, int descramble, struct timespec timeout); + }{ + This function sets the parameters of a TS feed. + Any filtering in progress on the TS feed + must be stopped before calling this function. + }{ + dmx\_ts\_feed\_t* feed & Pointer to the TS feed API and instance data.\\ + \_\_u16 pid & PID value to filter. Only the TS packets carrying the specified PID will + be passed to the API client.\\ + size\_t callback\_length & Number of bytes to deliver with each + call to the dmx\_ts\_cb() callback + function. The value of this + parameter should be a multiple of 188.\\ + size\_t circular\_buffer\_size & Size of the circular buffer for the filtered TS packets.\\ + int descramble & If non-zero, descramble the filtered TS packets.\\ + struct timespec timeout & Maximum time to wait before + delivering received TS packets to the client. + }{ + 0 & The function was completed without errors.\\ + -ENOMEM & Not enough memory for the requested buffer size.\\ + -ENOSYS & No descrambling facility available for TS.\\ + -EINVAL & Bad parameter. +} + + +\kifunction{start\_filtering()}{ + int start\_filtering(dmx\_ts\_feed\_t* feed); + }{ + Starts filtering TS packets on this TS feed, according to its settings. + The PID value to filter can be set by the API client. + All matching TS packets are delivered asynchronously to the client, + using the callback function registered with allocate\_ts\_feed(). + }{ + dmx\_ts\_feed\_t* feed & Pointer to the TS feed API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\kifunction{stop\_filtering()}{ + int stop\_filtering(dmx\_ts\_feed\_t* feed); + }{ + Stops filtering TS packets on this TS feed. + }{ + dmx\_ts\_feed\_t* feed & Pointer to the TS feed API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\clearpage + +\devsubsec{Section Feed API} + +A section feed is a resource consisting of a PID filter and a set of section filters. +Using this API, the client can set the properties of a section feed and to +start/stop filtering. +The API is defined as an abstract interface of the type dmx\_section\_feed\_t. +The functions that implement the interface should be defined static or module +private. The client can get the handle of a section feed API by calling the function +allocate\_section\_feed() in the demux API. + +On demux platforms that provide section filtering in hardware, the Section Feed API +implementation provides a software wrapper for the demux hardware. Other platforms +may support only PID filtering in hardware, requiring that TS packets are converted to +sections in software. In the latter case the Section Feed API implementation can be a +client of the TS Feed API. + + +\kifunction{set()}{ + int set(dmx\_section\_feed\_t* feed, \_\_u16 pid, size\_t circular\_buffer\_size, + int descramble, int check\_crc); + }{ + This function sets the parameters of a section feed. Any filtering in progress on the + section feed must be stopped before calling this function. + If descrambling is enabled, the payload\_scrambling\_control and + address\_scrambling\_control fields of received DVB datagram sections should be + observed. If either one is non-zero, the section should be descrambled either in + hardware or using the functions descramble\_mac\_address() and + descramble\_section\_payload() of the demux API. Note that according to the + MPEG-2 Systems specification, only the payloads of private sections can be + scrambled while the rest of the section data must be sent in the clear. + }{ + dmx\_section\_feed\_t* feed & Pointer to the section feed API and instance data.\\ + \_\_u16 pid & PID value to filter; only the TS packets + carrying the specified PID will be accepted.\\ + size\_t circular\_buffer\_size & Size of the circular buffer for filtered sections.\\ + int descramble & If non-zero, descramble any sections that are scrambled.\\ + int check\_crc & If non-zero, check the CRC values of filtered sections. + }{ + 0 & The function was completed without errors.\\ + -ENOMEM & Not enough memory for the requested buffer size.\\ + -ENOSYS & No descrambling facility available for sections.\\ + -EINVAL & Bad parameters. +} + +\kifunction{allocate\_filter()}{ + int allocate\_filter(dmx\_section\_feed\_t* feed, dmx\_section\_filter\_t** filter); + }{ + This function is used to allocate a section filter on the demux. + It should only be called when no filtering is in progress on this section feed. + If a filter cannot be allocated, the function fails with -ENOSPC. + See in section \ref{sectionfilter} for the format of the section filter. \\ + The bitfields filter\_mask and filter\_value should only be modified when no + filtering is in progress on this section feed. filter\_mask controls which bits of + filter\_value are compared with the section headers/payload. On a binary value of 1 + in filter\_mask, the corresponding bits are compared. The filter only accepts sections + that are equal to filter\_value in all the tested bit positions. Any changes to the + values of filter\_mask and filter\_value are guaranteed to take effect only when + the start\_filtering() function is called next time. The parent pointer in the struct + is initialized by the API implementation to the value of the feed parameter. The priv + pointer is not used by the API implementation, and can thus be freely utilized by the + caller of this function. Any data pointed to by the priv pointer is available to the + recipient of the dmx\_section\_cb() function call.\\ + While the maximum section filter length (DMX\_MAX\_FILTER\_SIZE) + is currently set at 16 bytes, hardware filters of that size are not + available on all platforms. Therefore, section filtering will often + take place first in hardware, followed by filtering in software for the + header bytes that were not covered by a hardware filter. + The filter\_mask field can be checked to determine how many bytes of + the section filter are actually used, and if the + hardware filter will suffice. Additionally, software-only section filters + can optionally be + allocated to clients when all hardware section filters are in use. + Note that on most demux hardware it is not possible to filter on the + section\_length field + of the section header -- thus this field is ignored, even though it is included in + filter\_value and filter\_mask fields. + }{ + dmx\_section\_feed\_t* feed & Pointer to the section feed API and instance data.\\ + dmx\_section\_filter\_t** filter & Pointer to the allocated filter. + }{ + 0 & The function was completed without errors.\\ + -ENOSPC & No filters of given type and length available.\\ + -EINVAL & Bad parameters. +} + +\kifunction{release\_filter()}{ + int release\_filter ( dmx\_section\_feed\_t* feed, dmx\_section\_filter\_t* filter); + }{ + This function releases all the resources of a previously allocated section filter. + The function should not be called while filtering is in progress on this section feed. + After calling this function, the caller should not try to dereference the + filter pointer. + }{ + dmx\_section\_feed\_t* feed & Pointer to the section feed API and instance data.\\ + dmx\_section\_filter\_t* filter & I/O Pointer to the instance data of a section filter. + }{ + 0 & The function was completed without errors.\\ + -ENODEV & No such filter allocated.\\ + -EINVAL & Bad parameter. +} + +\kifunction{start\_filtering()}{ + int start\_filtering ( dmx\_section\_feed\_t* feed ); + }{ + Starts filtering sections on this section feed, according to its settings. + Sections are first filtered based on their PID and then matched with the + section filters allocated for this feed. + If the section matches the PID filter and at least one section filter, it is delivered + to the API client. The section is delivered asynchronously using the callback function + registered with allocate\_section\_feed(). + }{ + dmx\_section\_feed\_t* feed & Pointer to the section feed API and instance data.\\ + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + +\kifunction{stop\_filtering()}{ + int stop\_filtering ( dmx\_section\_feed\_t* feed ); + }{ + Stops filtering sections on this section feed. Note that any changes to the + filtering parameters (filter\_value, filter\_mask, etc.) should only be made + when filtering is stopped. + }{ + dmx\_section\_feed\_t* feed & Pointer to the section feed API and instance data. + }{ + 0 & The function was completed without errors.\\ + -EINVAL & Bad parameter. +} + + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/sec.tex b/dvb-spec/dvbapi/sec.tex new file mode 100644 index 000000000..6ccd89481 --- /dev/null +++ b/dvb-spec/dvbapi/sec.tex @@ -0,0 +1,282 @@ +\devsec{DVB SEC API} + +The DVB SEC device controls the Satellite Equipment Control of +the DVB hardware, i.e. DiSEqC and V-SEC. +It is accessed through \texttt{/dev/ost/sec}. + +\devsubsec{SEC Data Types} + +\devsubsubsec{secDiseqcCmd} +\label{secdiseqccmd} + +\begin{verbatim} +struct secDiseqcCmd { + uint8_t addr; + uint8_t cmd; + uint8_t numParams; + uint8_t params[SEC_MAX_DISEQC_PARAMS]; +}; +\end{verbatim} + + +\devsubsubsec{secVoltage} +\label{secvoltage} + +\begin{verbatim} +typedef uint32_t secVoltage; +\end{verbatim} +\begin{verbatim} +enum { + SEC_VOLTAGE_OFF, + SEC_VOLTAGE_LT, + SEC_VOLTAGE_13, + SEC_VOLTAGE_13_5, + SEC_VOLTAGE_18, + SEC_VOLTAGE_18_5 +}; +\end{verbatim} + + +\devsubsubsec{secToneMode} +\label{sectonemode} + +\begin{verbatim} +typedef uint32_t secToneMode; +\end{verbatim} +\begin{verbatim} +typedef enum { + SEC_TONE_ON, + SEC_TONE_OFF +} secToneMode_t; +\end{verbatim} + + +\devsubsubsec{secMiniCmd} +\label{secminicmd} + +\begin{verbatim} +typedef uint32_t secMiniCmd; +\end{verbatim} +\begin{verbatim} +typedef enum { + SEC_MINI_NONE, + SEC_MINI_A, + SEC_MINI_B +} secMiniCmd_t; +\end{verbatim} +\begin{verbatim} +struct secStatus { + int32_t busMode; + secVoltage selVolt; + secToneMode contTone; +}; +\end{verbatim} + +\begin{verbatim} +enum { + SEC_BUS_IDLE, + SEC_BUS_BUSY, + SEC_BUS_OFF, + SEC_BUS_OVERLOAD +}; +\end{verbatim} + + +\devsubsubsec{secCommand} +\label{seccommand} + +\begin{verbatim} +struct secCommand { + int32_t type; + union { + struct secDiseqcCmd diseqc; + uint8_t vsec; + uint32_t pause; + } u; +}; +\end{verbatim} + + +\devsubsubsec{secCmdSequence} +\label{seccmdsequence} + +\begin{verbatim} +struct secCmdSequence { + secVoltage voltage; + secMiniCmd miniCommand; + secToneMode continuousTone; + + uint32_t numCommands; + struct secCommand* commands; +}; +\end{verbatim} + +\begin{verbatim} +enum { + SEC_CMDTYPE_DISEQC, + SEC_CMDTYPE_VSEC, + SEC_CMDTYPE_PAUSE +}; +\end{verbatim} + +\begin{verbatim} +typedef enum { + SEC_DISEQC_SENT, + SEC_VSEC_SENT, + SEC_PAUSE_COMPLETE, + SEC_CALLBACK_ERROR +} secCallback_t; +\end{verbatim} + +\clearpage + +\devsubsec{SEC Function Calls} + +\function{open()}{ + int open(const char *deviceName, int flags);}{ + This system call opens a named SEC device for subsequent use. + If the device is opened in read-only mode, only status and statistics + monitoring is allowed. If the device is opened in read/write mode, all + types of operations can be performed. + Any number of applications can have simultaneous access to the device. + }{ + const char *deviceName & Name of specific SEC device.\\ + int flags & A bit-wise OR of the following flags:\\ + & \hspace{1em} O\_RDONLY read-only access\\ + & \hspace{1em} O\_RDWR read/write access\\ + & The optional flag O\_NONBLOCK is not supported. If O\_NONBLOCK is set, + open() and most other subsequent calls to the device will return -1 and + set errno to EWOULDBLOCK. + The communication with the peripheral devices is sequential by nature, + so it is probably preferable to use the device in synchronous mode. + This is the motivation for not going through the extra effort of + implementing asynchronous operation of the device. + }{ + ENODEV & Device driver not loaded/available.\\ + EFAULT & deviceName does not refer to a valid memory area.\\ + EBUSY & Device or resource busy.\\ + EINVAL & Invalid argument.\\ +} + +\function{close()}{ + int close(int fd);}{ + This system call closes a previously opened SEC device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + }{ + EBADF & fd is not a valid open file descriptor.\\ +} + +\ifunction{SEC\_GET\_STATUS}{ + int ioctl(int fd, int request = SEC\_GET\_STATUS, struct secStatus* status);}{ + This call gets the status of the device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals SEC\_GET\_STATUS for this command.\\ + struct secStatus* status & The status of the device.\\ + }{ + ENODEV & Device driver not loaded/available.\\ + EFAULT & status is an invalid pointer.\\ + EBUSY & Device or resource busy.\\ + EINVAL & Invalid argument.\\ + EPERM & File not opened with read permissions.\\ + EINTERNAL & Internal error in the device driver.\\ +} + +\ifunction{SEC\_RESET\_OVERLOAD}{ + int ioctl(int fd, int request = SEC\_RESET\_OVERLOAD);}{ + If the bus has been automatically powered off due to power overload, this + ioctl call restores the power to the bus. The call requires read/write + access to the device. + This call has no effect if the device is manually powered off. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals SEC\_RESET\_OVERLOAD for this command.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EPERM & Permission denied (needs read/write access).\\ + EINTERNAL & Internal error in the device driver.\\ +} + +\ifunction{SEC\_RESET\_OVERLOAD}{ +int ioctl(int fd, int request = SEC\_SEND\_SEQUENCE, struct secCmdSequence *seq); +}{ +This ioctl call is used to send a sequence of DiSEqCTM and/or V-SEC +commands. The first version of the SEC device does not support V-SEC +signaling and it aborts the operation with an error code if a V-SEC +command is detected in the input data.\\ +\begin{itemize} +\item[$\bullet$] The call will fail with errno set to EBUSOVERLOAD if the bus is +overloaded. If the bus is overloaded, SEC\_RESET\_OVERLOAD can be +called and the operation can be retried. +\item[$\bullet$] If seq.numCommands equals 0 and seq.miniCommand equals SEC\_MINI\_NONE, +the bus voltage will be switched and the continuous 22kHz tone +generation enabled/disabled immediately. +\end{itemize}\\ +This operation is atomic. If several processes calls this ioctl +simultaneously, the operations will be serialized so a complete sequence +is sent at a time. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals SEC\_SEND\_SEQUENCE for this command.\\ + struct secCmdSequence *seq & Pointer to the command sequence to be transmitted.\\ + }{ + EBADF & fd is not a valid file descriptor.\\ + EFAULT & Seq points to an invalid address.\\ + EINVAL & The data structure referred to by seq is invalid in some way.\\ + EPERM & Permission denied (needs read/write access).\\ + EINTERNAL & Internal error in the device driver.\\ + EBUSMODE & The device is not prepared for transmission + (e.g. it might be manually powered off).\\ + EBUSOVERLOAD & Bus overload has occurred.\\ +} + + +\ifunction{SEC\_SET\_TONE}{ +int ioctl(int fd, int request = SEC\_SET\_TONE, secToneMode tone); +}{ +This call is used to set the generation of the continuous 22kHz tone. +The possibility to just change the tone mode is already provided by +ioctl SEC\_SEND\_SEQUENCE, but SEC\_SET\_TONE is an easier to use interface. +To keep the transmission of a command sequence as +an atomic operation, SEC\_SET\_TONE will block if a transmission is in +progress. This call requires read/write permissions. +}{ +int fd & File descriptor returned by a previous call to open().\\ +int request & Equals SEC\_SET\_TONE for this command.\\ +secToneMode tone & The requested tone generation mode (on/off).\\ +}{ +ENODEV & Device driver not loaded/available.\\ +EBUSY & Device or resource busy.\\ +EINVAL & Invalid argument.\\ +EPERM & File not opened with read permissions.\\ +EINTERNAL & Internal error in the device driver.\\ +} + + +\ifunction{SEC\_SET\_VOLTAGE}{ +int ioctl(int fd, int request = SEC\_SET\_VOLTAGE, secVoltage voltage); +}{ +This call is used to set the bus voltage. The possibility to just change +the bus voltage is already provided by ioctl SEC\_SEND\_SEQUENCE, but +SEC\_SET\_VOLTAGE is an easier to use interface. +To keep the transmission of a command sequence as +an atomic operation, SEC\_SET\_VOLTAGE will block if a transmission is in +progress. +This call requires read/write permissions. +}{ +int fd & File descriptor returned by a previous call to open().\\ +int request & Equals SEC\_SET\_VOLTAGE for this command.\\ +secVoltage voltage & The requested bus voltage.\\ +}{ +ENODEV & Device driver not loaded/available.\\ +EBUSY & Device or resource busy.\\ +EINVAL & Invalid argument.\\ +EPERM & File not opened with read permissions.\\ +EINTERNAL & Internal error in the device driver.\\ +} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: diff --git a/dvb-spec/dvbapi/title.tex b/dvb-spec/dvbapi/title.tex new file mode 100644 index 000000000..ce8b584c1 --- /dev/null +++ b/dvb-spec/dvbapi/title.tex @@ -0,0 +1,24 @@ +\pagenumbering{arabic} +\pagestyle{empty} +\title{\huge\textbf{LINUX DVB API}} + +\author{ +\includegraphics{cimlogo.psi}\\ + Convergence integrated media GmbH\\\\ + Dr. Ralph J.K. Metzler\\ + \texttt{<rjkm@convergence.de>}\\\\ + Dr. Marcus O.C. Metzler\\ + \texttt{<mocm@convergence.de>} +% Rosenthalerstr. 51\\ +% 10178 Berlin\\Germany +} +\date{09/15/2001\\V 0.9.4} +\maketitle + +\newpage + +%\end{titlepage} +% Local Variables: +% mode: latex +% TeX-master: "dvbapi" +% End:
\ No newline at end of file diff --git a/dvb-spec/dvbapi/video.tex b/dvb-spec/dvbapi/video.tex new file mode 100644 index 000000000..67abb9586 --- /dev/null +++ b/dvb-spec/dvbapi/video.tex @@ -0,0 +1,684 @@ +\devsec{DVB Video Device} + +The DVB video device controls the MPEG2 video decoder of the DVB hardware. +It can be accessed through \texttt{/dev/ost/video}. +The include file \texttt{ost/video.h} defines the data types and lists all I/O calls. + + +\devsubsec{Video Data Types} + +\devsubsubsec{videoFormat\_t} +\label{videoformat} + +The \texttt{videoFormat\_t} data type defined by +\begin{verbatim} +typedef enum { + VIDEO_FORMAT_4_3, + VIDEO_FORMAT_16_9 +} videoFormat_t; +\end{verbatim} +is used in the VIDEO\_SET\_FORMAT function (\ref{videosetformat}) to +tell the driver which aspect ratio the output hardware (e.g. TV) has. +It is also used in the data structures videoStatus (\ref{videostatus}) +returned by VIDEO\_GET\_STATUS (\ref{videogetstatus}) and +videoEvent (\ref{videoevent}) returned by VIDEO\_GET\_EVENT (\ref{videogetevent}) +which report about the display format of the current video stream. + +\devsubsubsec{videoDisplayFormat\_t} +\label{videodispformat} + +In case the display format of the video stream and of the +display hardware differ the application has to specify how to handle +the cropping of the picture. +This can be done using the VIDEO\_SET\_DISPLAY\_FORMAT call +(\ref{videosetdisplayformat}) which accepts +\begin{verbatim} +typedef enum { + VIDEO_PAN_SCAN, + VIDEO_LETTER_BOX, + VIDEO_CENTER_CUT_OUT +} videoDisplayFormat_t; +\end{verbatim} +as argument. + + +\devsubsubsec{video stream source} +\label{videostreamsource} +The video stream source is set through the VIDEO\_SELECT\_SOURCE +call and can take the following values, depending on whether we are +replaying from an internal (demuxer) or external (user write) source. +\begin{verbatim} +typedef enum { + VIDEO_SOURCE_DEMUX, + VIDEO_SOURCE_MEMORY +} videoStreamSource_t; +\end{verbatim} +VIDEO\_SOURCE\_DEMUX selects the demultiplexer (fed +either by the frontend or the DVR device) as the source of +the video stream. +If VIDEO\_SOURCE\_MEMORY is selected the stream +comes from the application through the \texttt{write()} +system call. + +\devsubsubsec{video play state} +\label{videoplaystate} +The following values can be returned by the VIDEO\_GET\_STATUS call +representing the state of video playback. +\begin{verbatim} +typedef enum { + VIDEO_STOPPED, + VIDEO_PLAYING, + VIDEO_FREEZED +} videoPlayState_t; +\end{verbatim} + + +\devsubsubsec{video event} +\label{videoevent} +The following is the structure of a video event as it is returned by +the VIDEO\_GET\_EVENT call. +\begin{verbatim} +struct videoEvent { + int32_t type; + time_t timestamp; + union { + videoFormat_t videoFormat; + } u; +}; +\end{verbatim} + +\devsubsubsec{video status} +\label{videostatus} +The VIDEO\_GET\_STATUS call returns the following structure informing +about various states of the playback operation. +\begin{verbatim} +struct videoStatus { + boolean videoBlank; + videoPlayState_t playState; + videoStreamSource_t streamSource; + videoFormat_t videoFormat; + videoDisplayFormat_t displayFormat; +}; +\end{verbatim} +If videoBlank is set video will be blanked out if the channel is changed or +if playback is stopped. Otherwise, the last picture will be displayed. +playState indicates if the video is currently frozen, stopped, or +being played back. The streamSource corresponds to the seleted source +for the video stream. It can come either from the demultiplexer or from memory. +The videoFormat indicates the aspect ratio (one of 4:3 or 16:9) +of the currently played video stream. +Finally, displayFormat corresponds to the selected cropping mode in case the +source video format is not the same as the format of the output device. + + +\devsubsubsec{video display still picture} +\label{videostill} +An I-frame displayed via the VIDEO\_STILLPICTURE call is passed on +within the following structure. +\begin{verbatim} +/* pointer to and size of a single iframe in memory */ +struct videoDisplayStillPicture { + char *iFrame; + int32_t size; +}; +\end{verbatim} + +\devsubsubsec{video capabilities} +\label{videocaps} +A call to VIDEO\_GET\_CAPABILITIES returns an unsigned integer with +the following bits set according to the hardwares capabilities. +\begin{verbatim} +/* bit definitions for capabilities: */ +/* can the hardware decode MPEG1 and/or MPEG2? */ +#define VIDEO_CAP_MPEG1 1 +#define VIDEO_CAP_MPEG2 2 +/* can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) */ +#define VIDEO_CAP_SYS 4 +#define VIDEO_CAP_PROG 8 +/* can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) */ +#define VIDEO_CAP_SPU 16 +#define VIDEO_CAP_NAVI 32 +#define VIDEO_CAP_CSS 64 +\end{verbatim} + + +\devsubsubsec{video system} +\label{videosys} +A call to VIDEO\_SET\_SYSTEM sets the desired video system for TV +output. The following system types can be set: + +\begin{verbatim} +typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 +} videoSystem_t; +\end{verbatim} + + + +\devsubsubsec{video highlights} +\label{vhilite} +Calling the ioctl VIDEO\_SET\_HIGHLIGHTS posts the SPU highlight +information. The call expects the following format for that information: + +\begin{verbatim} +typedef +struct videoHighlight { + boolean active; /* 1=show highlight, 0=hide highlight */ + uint8_t contrast1; /* 7- 4 Pattern pixel contrast */ + /* 3- 0 Background pixel contrast */ + uint8_t contrast2; /* 7- 4 Emphasis pixel-2 contrast */ + /* 3- 0 Emphasis pixel-1 contrast */ + uint8_t color1; /* 7- 4 Pattern pixel color */ + /* 3- 0 Background pixel color */ + uint8_t color2; /* 7- 4 Emphasis pixel-2 color */ + /* 3- 0 Emphasis pixel-1 color */ + uint32_t ypos; /* 23-22 auto action mode */ + /* 21-12 start y */ + /* 9- 0 end y */ + uint32_t xpos; /* 23-22 button color number */ + /* 21-12 start x */ + /* 9- 0 end x */ +} videoHighlight_t; +\end{verbatim} + + +\devsubsubsec{video SPU} +\label{videospu} +Calling VIDEO\_SET\_SPU deactivates or activates SPU decoding, +according to the following format: +\begin{verbatim} +typedef +struct videoSPU { + boolean active; + int streamID; +} videoSPU_t; +\end{verbatim} + + +\devsubsubsec{video SPU palette} +\label{vspupal} +The following structure is used to set the SPU palette by calling VIDEO\_SPU\_PALETTE: +\begin{verbatim} +typedef +struct videoSPUPalette{ /* SPU Palette information */ + int length; + uint8_t *palette; +} videoSPUPalette_t; +\end{verbatim} + +\devsubsubsec{video NAVI pack} +\label{videonavi} +In order to get the navigational data the following structure has to +be passed to the ioctl VIDEO\_GET\_NAVI: +\begin{verbatim} +typedef +struct videoNaviPack{ + int length; /* 0 ... 1024 */ + uint8_t data[1024]; +} videoNaviPack_t; +\end{verbatim} + + +\devsubsubsec{video attributes} +\label{vattrib} +The following attributes can be set by a call to VIDEO\_SET\_ATTRIBUTES: +\begin{verbatim} +typedef uint16_t videoAttributes_t; +/* bits: descr. */ +/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ +/* 13-12 TV system (0=525/60, 1=625/50) */ +/* 11-10 Aspect ratio (0=4:3, 3=16:9) */ +/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */ +/* 7 line 21-1 data present in GOP (1=yes, 0=no) */ +/* 6 line 21-2 data present in GOP (1=yes, 0=no) */ +/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */ +/* 2 source letterboxed (1=yes, 0=no) */ +/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */ +\end{verbatim} + + +\clearpage + +\devsubsec{Video Function Calls} + +\function{open()}{ + int open(const char *deviceName, int flags);}{ + This system call opens a named video device (e.g. /dev/ost/video) + for subsequent use. + + When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in + the documentation for functions where there is a difference. + It does not affect the semantics of the open() call itself. + A device opened in blocking mode can later be put into non-blocking mode + (and vice versa) using the F\_SETFL command of the fcntl system + call. + This is a standard system call, documented in the Linux manual + page for fcntl. + Only one user can open the Video Device in O\_RDWR mode. All other attempts to + open the device in this mode will fail, and an error-code will be returned. + If the Video Device is opened in O\_RDONLY mode, the only ioctl call that can + be used is VIDEO\_GET\_STATUS. All other call will return an error code. + }{ + const char *deviceName & Name of specific video device.\\ + int flags & A bit-wise OR of the following flags:\\ + & \hspace{1em} O\_RDONLY read-only access\\ + & \hspace{1em} O\_RDWR read/write access\\ + & \hspace{1em} O\_NONBLOCK open in non-blocking mode \\ + & \hspace{1em} (blocking mode is the default)\\ + }{ + ENODEV & Device driver not loaded/available.\\ + EINTERNAL & Internal error.\\ + EBUSY & Device or resource busy.\\ + EINVAL & Invalid argument.\\ +} + +\function{close()}{ + int close(int fd);}{ + This system call closes a previously opened video device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + }{ + EBADF & fd is not a valid open file descriptor.\\ +} + +\function{write()}{ + size\_t write(int fd, const void *buf, size\_t count);}{ + This system call can only be used if VIDEO\_SOURCE\_MEMORY is selected in the + ioctl call VIDEO\_SELECT\_SOURCE. The data provided shall be in PES + format, unless the capability allows other formats. + If O\_NONBLOCK is not specified the function will block until buffer space is + available. The amount of data to be transferred is implied by count. + }{ + int fd & File descriptor returned by a previous call to open().\\ + void *buf & Pointer to the buffer containing the PES data.\\ + size\_t count& Size of buf.\\ + }{ + EPERM& Mode VIDEO\_SOURCE\_MEMORY not selected.\\ + ENOMEM& Attempted to write more data than the internal buffer can hold.\\ + EBADF& fd is not a valid open file descriptor.\\ +} + + +\ifunction{VIDEO\_STOP}{ + int ioctl(fd, int request = VIDEO\_STOP, boolean mode);}{ + This ioctl call asks the Video Device to stop playing the current stream. + Depending on the input parameter, the screen can be blanked out or + displaying the last decoded frame. +}{ +int fd & File descriptor returned by a previous call to open(). \\ +int request & Equals VIDEO\_STOP for this command. \\ +Boolean mode & Indicates how the screen shall be handled. \\ +& TRUE: Blank screen when stop. \\ +& FALSE: Show last decoded frame.\\ +}{ +EBADF& fd is not a valid open file descriptor \\ +EINTERNAL & Internal error, possibly in the communication with + the DVB subsystem.\\ +} + +\ifunction{VIDEO\_PLAY}{ + int ioctl(fd, int request = VIDEO\_PLAY);}{ + This ioctl call asks the Video Device to start playing a video stream + from the selected source. +}{ +int fd & File descriptor returned by a previous call to open(). \\ +int request & Equals VIDEO\_PLAY for this command. \\ +}{ +EBADF& fd is not a valid open file descriptor \\ +EINTERNAL & Internal error, possibly in the communication with + the DVB subsystem.\\ +} + + +\ifunction{VIDEO\_FREEZE}{ + int ioctl(fd, int request = VIDEO\_FREEZE);}{ + This ioctl call suspends the live video stream being played. + Decoding and playing are frozen. It is then possible to restart + the decoding and playing process of the video stream using the + VIDEO\_CONTINUE command. If VIDEO\_SOURCE\_MEMORY is selected in the + ioctl call VIDEO\_SELECT\_SOURCE, the DVB subsystem will not decode + any more data until the ioctl call VIDEO\_CONTINUE or VIDEO\_PLAY is + performed. +}{ +int fd & File descriptor returned by a previous call to open(). \\ +int request & Equals VIDEO\_FREEZE for this command. \\ +}{ +EBADF& fd is not a valid open file descriptor \\ +EINTERNAL & Internal error, possibly in the communication with + the DVB subsystem.\\ +} + +\ifunction{VIDEO\_CONTINUE}{ + int ioctl(fd, int request = VIDEO\_CONTINUE);}{ + This ioctl call restarts decoding and playing processes of the video + stream which was played before a call to VIDEO\_FREEZE was made. + }{ + int fd & File descriptor returned by a previous call to open(). \\ + int request & Equals VIDEO\_CONTINUE for this command. \\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error, possibly in the communication with + the DVB subsystem.\\ + } + + +\ifunction{VIDEO\_SELECT\_SOURCE}{ + int ioctl(fd, int request = VIDEO\_SELECT\_SOURCE, videoStreamSource\_t source);}{ + This ioctl call informs the video device which source shall be used + for the input data. The possible sources are demux or memory. If + memory is selected, the data is fed to the video device through + the write command. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals VIDEO\_SELECT\_SOURCE for this command. \\ + videoStreamSource\_t source&Indicates which source shall be used for the Video stream.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error, possibly in the communication with the DVB subsystem.\\ +} + +\ifunction{VIDEO\_SET\_BLANK}{ + int ioctl(fd, int request = VIDEO\_SET\_BLANK, boolean mode);}{ + This ioctl call asks the Video Device to blank out the picture. +}{ +int fd & File descriptor returned by a previous call to open().\\ +int request& Equals VIDEO\_SET\_BLANK for this command. \\ +boolean mode&TRUE: Blank screen when stop.\\ + &FALSE: Show last decoded frame.\\ +}{ +EBADF& fd is not a valid open file descriptor \\ +EINTERNAL & Internal error, possibly in the communication with the DVB subsystem.\\ +EINVAL & Illegal input parameter\\ +} + +\ifunction{VIDEO\_GET\_STATUS}{ +\label{videogetstatus} + int ioctl(fd, int request = VIDEO\_GET\_STATUS, struct videoStatus *status);}{ + This ioctl call asks the Video Device to return the current status of the device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals VIDEO\_GET\_STATUS for this command.\\ + struct videoStatus *status & Returns the current status of the Video Device.\\ +}{ +EBADF& fd is not a valid open file descriptor \\ +EINTERNAL & Internal error, possibly in the communication with the DVB subsystem.\\ +EFAULT & status points to invalid address\\ +} + +\ifunction{VIDEO\_GET\_EVENT}{ +\label{videogetevent} + int ioctl(fd, int request = VIDEO\_GET\_EVENT, struct videoEvent *ev);}{ + This ioctl call returns an event of type videoEvent if available. + If an event is not available, the behavior depends on whether the device is in + blocking or non-blocking mode. In the latter case, the call fails immediately + with errno set to EWOULDBLOCK. In the former case, the call blocks until an + event becomes available. + The standard Linux poll() and/or select() system calls can be used with the + device file descriptor to watch for new events. For select(), the file + descriptor should be included in the exceptfds argument, and for poll(), + POLLPRI should be specified as the wake-up condition. + Read-only permissions are sufficient for this ioctl call. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request& Equals VIDEO\_GET\_EVENT for this command.\\ + struct videoEvent *ev & Points to the location where the event, if any, is + to be stored.\\ +}{ +EBADF & fd is not a valid open file descriptor \\ +EFAULT & ev points to invalid address \\ +EWOULDBLOCK & There is no event pending, and the device is in non-blocking mode.\\ +EBUFFEROVERFLOW & \\ +&Overflow in event queue - one or more events were lost.\\ +} + +\ifunction{VIDEO\_SET\_DISPLAY\_FORMAT}{ +\label{videosetdisplayformat} + int ioctl(fd, int request = VIDEO\_SET\_DISPLAY\_FORMAT, videoDisplayFormat\_t format);}{ + This ioctl call asks the Video Device to select the video format to be applied + by the MPEG chip on the video. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_DISPLAY\_FORMAT for this command.\\ + videoDisplayFormat\_t format & Selects the video format to be used.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error.\\ + EINVAL & Illegal parameter format.\\ +} + +\ifunction{VIDEO\_STILLPICTURE}{ + int ioctl(fd, int request = VIDEO\_STILLPICTURE, struct videoDisplayStillPicture *sp);}{ + This ioctl call asks the Video Device to display a still picture (I-frame). + The input data shall contain an I-frame. If the pointer is NULL, then the + current displayed still picture is blanked. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_STILLPICTURE for this command.\\ + struct videoDisplayStillPicture *sp& + Pointer to a location where an I-frame and size is stored.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error.\\ + EFAULT & sp points to an invalid iframe.\\ +} + +\ifunction{VIDEO\_FAST\_FORWARD}{ + int ioctl(fd, int request = VIDEO\_FAST\_FORWARD, int nFrames);}{ + This ioctl call asks the Video Device to skip decoding of N number of I-frames. + This call can only be used if VIDEO\_SOURCE\_MEMORY is selected. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_FAST\_FORWARD for this command.\\ + int nFrames & The number of frames to skip.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error.\\ + EPERM & Mode VIDEO\_SOURCE\_MEMORY not selected.\\ + EINVAL & Illegal parameter format.\\ +} + +\ifunction{VIDEO\_SLOWMOTION}{ + int ioctl(fd, int request = VIDEO\_SLOWMOTION, int nFrames);}{ + This ioctl call asks the video device to repeat decoding frames N + number of times. + This call can only be used if VIDEO\_SOURCE\_MEMORY is selected. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SLOWMOTION for this command.\\ + int nFrames & The number of times to repeat each frame.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINTERNAL & Internal error.\\ + EPERM & Mode VIDEO\_SOURCE\_MEMORY not selected.\\ + EINVAL & Illegal parameter format.\\ +} + +\ifunction{VIDEO\_GET\_CAPABILITIES}{ + int ioctl(fd, int request = VIDEO\_GET\_CAPABILITIES, unsigned int *cap);}{ + This ioctl call asks the video device about its decoding capabilities. + On success it returns and integer which has bits set according to the + defines in section \ref{videocaps}. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_GET\_CAPABILITIES for this command.\\ + unsigned int *cap & Pointer to a location where to store the + capability information.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EFAULT & cap points to an invalid iframe.\\ +} + +\ifunction{VIDEO\_SET\_ID}{ + int ioctl(int fd, int request = VIDEO\_SET\_ID, int id);}{ + This ioctl selects which sub-stream is to be decoded if a program or + system stream is sent to the video device. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_ID for this command.\\ + int id& video sub-stream id + }{ + EBADF& fd is not a valid open file descriptor.\\ + EINTERNAL & Internal error.\\ + EINVAL & Invalid sub-stream id. +} + +\ifunction{VIDEO\_CLEAR\_BUFFER}{ + int ioctl(fd, int request = VIDEO\_CLEAR\_BUFFER);}{ + This ioctl call clears all video buffers in the driver and + in the decoder hardware. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_CLEAR\_BUFFER for this command.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ +} + +\ifunction{VIDEO\_SET\_STREAMTYPE}{ + int ioctl(fd, int request = VIDEO\_SET\_STREAMTYPE, int type);}{ + This ioctl tells the driver which kind of stream to expect + being written to it. If this call is not used the default of video PES + is used. Some drivers might not support this call and always expect PES. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_STREAMTYPE for this command.\\ + int type & stream type\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& type is not a valid or supported stream type.\\ +} + +\ifunction{VIDEO\_SET\_FORMAT}{ +\label{videosetformat} + int ioctl(fd, int request = VIDEO\_SET\_FORMAT, videoFormat\_t format); +}{ + This ioctl sets the screen format (aspect ratio) of the connected + output device (TV) so that the output of the decoder can + be adjusted accordingly. + }{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_FORMAT for this command.\\ + videoFormat\_t format& video format of TV as defined in section \ref{videoformat}.\\ + }{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& format is not a valid video format.\\ +} + +\ifunction{VIDEO\_SET\_SYSTEM}{ +\label{videosetsystem} + int ioctl(fd, int request = VIDEO\_SET\_SYSTEM , videoSystem\_t system); +}{ + This ioctl sets the television output format. The format (see section + \ref{videosys}) may vary from the color format of the displayed MPEG + stream. If the hardware is not able to display the requested format + the call will return an error. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_FORMAT for this command.\\ + videoSystem\_t system& video system of TV output.\\ +}{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& system is not a valid or supported video system.\\ +} + +\ifunction{VIDEO\_SET\_HIGHLIGHT}{ +\label{videosethighlight} + int ioctl(fd, int request = VIDEO\_SET\_HIGHLIGHT ,videoHighlight\_t *vhilite) +}{ + This ioctl sets the SPU highlight information for the menu access of + a DVD. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_HIGHLIGHT for this command.\\ + videoHighlight\_t *vhilite& SPU Highlight information according to + section \ref{vhilite}.\\ +}{ + EBADF& fd is not a valid open file descriptor. \\ + EINVAL& input is not a valid highlight setting.\\ +} + + +\ifunction{VIDEO\_SET\_SPU}{ +\label{videosetspu} + int ioctl(fd, int request = VIDEO\_SET\_SPU , videoSPU\_t *spu) +}{ + This ioctl activates or deactivates SPU decoding in a DVD input + stream. It can only be used, if the driver is able to handle a DVD + stream. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_SPU for this command.\\ + videoSPU\_t *spu& SPU decoding (de)activation and subid setting + according to section \ref{videospu}.\\ +}{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& input is not a valid spu setting or driver cannot handle SPU.\\ +} + + +\ifunction{VIDEO\_SET\_SPU\_PALETTE}{ +\label{videosetspupalette} + int ioctl(fd, int request = VIDEO\_SET\_SPU\_PALETTE ,videoSPUPalette\_t *palette ) +}{ + This ioctl sets the SPU color palette. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_SPU\_PALETTE for this command.\\ + videoSPUPalette\_t *palette& SPU palette according to section \ref{vspupal}.\\ +}{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& input is not a valid palette or driver doesn't handle SPU.\\ +} + + + +\ifunction{VIDEO\_GET\_NAVI}{ +\label{videosetnavi} + int ioctl(fd, int request = VIDEO\_GET\_NAVI , videoNaviPack\_t *navipack) +}{ + This ioctl returns navigational information from the DVD stream. This is + especially needed if an encoded stream has to be decoded by the hardware. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_GET\_NAVI for this command.\\ + videoNaviPack\_t *navipack& PCI or DSI pack (private stream 2) + according to section \ref{videonavi}.\\ +}{ + EBADF& fd is not a valid open file descriptor \\ + EFAULT& driver is not able to return navigational information\\ +} + + +\ifunction{VIDEO\_SET\_ATTRIBUTES}{ +\label{videosetattributes} + int ioctl(fd, int request = VIDEO\_SET\_ATTRIBUTE ,videoAttributes\_t + vattr) +}{ + This ioctl is intended for DVD playback and allows you to set + certain information about the stream. Some hardware may not need + this information, but the call also tells the hardware to prepare + for DVD playback. +}{ + int fd & File descriptor returned by a previous call to open().\\ + int request & Equals VIDEO\_SET\_ATTRIBUTE for this command.\\ + videoAttributes\_t vattr& video attributes according to section \ref{vattrib}.\\ +}{ + EBADF& fd is not a valid open file descriptor \\ + EINVAL& input is not a valid attribute setting.\\ +} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "dvbapi" +%%% End: |