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/dvbapi/kdapi.tex | |
parent | c2ca96fee8c574074c67c9da023e4165f2f9b2e3 (diff) | |
download | mediapointer-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.tex | 1007 |
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: |