summaryrefslogtreecommitdiff
path: root/dvb-spec/dvbapi/kdapi.tex
diff options
context:
space:
mode:
authorrjkm <devnull@localhost>2001-09-16 22:27:03 -0300
committerrjkm <devnull@localhost>2001-09-16 22:27:03 -0300
commit9034551a3bbc76b79a152806c781b1b8e8ea3a9a (patch)
tree31fe111120a3102afe9ea193836907a2c3a63fc7 /dvb-spec/dvbapi/kdapi.tex
parentc2ca96fee8c574074c67c9da023e4165f2f9b2e3 (diff)
downloadmediapointer-dvb-s2-9034551a3bbc76b79a152806c781b1b8e8ea3a9a.tar.gz
mediapointer-dvb-s2-9034551a3bbc76b79a152806c781b1b8e8ea3a9a.tar.bz2
new API docs
Diffstat (limited to 'dvb-spec/dvbapi/kdapi.tex')
-rw-r--r--dvb-spec/dvbapi/kdapi.tex1007
1 files changed, 1007 insertions, 0 deletions
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: