mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2023-10-10 13:37:43 +02:00
adapt dvb-core, includes and affected files to mainline 4.14-rc2
This commit is contained in:
parent
f84d196a1e
commit
1c22a07eaa
@ -1254,7 +1254,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type)
|
||||
struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
|
||||
struct stv6110x_config *tunerconf = (input->nr & 1) ?
|
||||
&stv6110b : &stv6110a;
|
||||
struct stv6110x_devctl *ctl;
|
||||
const struct stv6110x_devctl *ctl;
|
||||
|
||||
ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c);
|
||||
if (!ctl) {
|
||||
@ -2081,13 +2081,13 @@ static int ddb_port_attach(struct ddb_port *port)
|
||||
ret = dvb_register_device(port->dvb[0].adap,
|
||||
&port->dvb[0].dev,
|
||||
&dvbdev_ci, (void *)port->output,
|
||||
DVB_DEVICE_CI);
|
||||
DVB_DEVICE_CI, 1);
|
||||
break;
|
||||
case DDB_PORT_MOD:
|
||||
ret = dvb_register_device(port->dvb[0].adap,
|
||||
&port->dvb[0].dev,
|
||||
&dvbdev_mod, (void *)port->output,
|
||||
DVB_DEVICE_MOD);
|
||||
DVB_DEVICE_MOD, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2937,7 +2937,7 @@ static int ddb_nsd_attach(struct ddb *dev)
|
||||
ret = dvb_register_device(&dev->adap[0],
|
||||
&dev->nsd_dev,
|
||||
&dvbdev_nsd, (void *)dev,
|
||||
DVB_DEVICE_NSD);
|
||||
DVB_DEVICE_NSD, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify dit under the terms of the GNU General Public License
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 only, as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
|
@ -407,7 +407,7 @@ struct ddb_ns {
|
||||
struct ddb_lnb {
|
||||
struct mutex lock; /* lock lnb access */
|
||||
u32 tone;
|
||||
fe_sec_voltage_t oldvoltage[4];
|
||||
enum fe_sec_voltage oldvoltage[4];
|
||||
u32 voltage[4];
|
||||
u32 voltages;
|
||||
u32 fmode;
|
||||
|
@ -5,7 +5,7 @@
|
||||
config DVB_MAX_ADAPTERS
|
||||
int "maximum number of DVB/ATSC adapters"
|
||||
depends on DVB_CORE
|
||||
default 8
|
||||
default 16
|
||||
range 1 255
|
||||
help
|
||||
Maximum number of DVB/ATSC adapters. Increasing this number
|
||||
@ -13,7 +13,7 @@ config DVB_MAX_ADAPTERS
|
||||
if a much lower number of DVB/ATSC adapters is present.
|
||||
Only values in the range 4-32 are tested.
|
||||
|
||||
If you are unsure about this, use the default value 8
|
||||
If you are unsure about this, use the default value 16
|
||||
|
||||
config DVB_DYNAMIC_MINORS
|
||||
bool "Dynamic DVB minor allocation"
|
||||
@ -27,3 +27,16 @@ config DVB_DYNAMIC_MINORS
|
||||
will be required to manage the device nodes.
|
||||
|
||||
If you are unsure about this, say N here.
|
||||
|
||||
config DVB_DEMUX_SECTION_LOSS_LOG
|
||||
bool "Enable DVB demux section packet loss log"
|
||||
depends on DVB_CORE
|
||||
default n
|
||||
help
|
||||
Enable extra log messages meant to detect packet loss
|
||||
inside the Kernel.
|
||||
|
||||
Should not be enabled on normal cases, as logs can
|
||||
be very verbose.
|
||||
|
||||
If you are unsure about this, say N here.
|
||||
|
522
dvb-core/demux.h
522
dvb-core/demux.h
@ -1,6 +1,10 @@
|
||||
/*
|
||||
* demux.h
|
||||
*
|
||||
* The Kernel Digital TV Demux kABI defines a driver-internal interface for
|
||||
* registering low-level, hardware specific driver to a hardware independent
|
||||
* demux layer.
|
||||
*
|
||||
* Copyright (c) 2002 Convergence GmbH
|
||||
*
|
||||
* based on code:
|
||||
@ -17,10 +21,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DEMUX_H
|
||||
@ -32,9 +32,9 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Common definitions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Common definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
|
||||
@ -45,7 +45,8 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
|
||||
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed
|
||||
* filter.
|
||||
*/
|
||||
|
||||
#ifndef DMX_MAX_SECTION_SIZE
|
||||
@ -55,52 +56,76 @@
|
||||
#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* enum dmx_success: Success codes for the Demux Callback API.
|
||||
* TS packet reception
|
||||
*/
|
||||
|
||||
enum dmx_success {
|
||||
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 */
|
||||
/**
|
||||
* enum ts_filter_type - filter type bitmap for dmx_ts_feed.set\(\)
|
||||
*
|
||||
* @TS_PACKET: Send TS packets (188 bytes) to callback (default).
|
||||
* @TS_PAYLOAD_ONLY: In case TS_PACKET is set, only send the TS payload
|
||||
* (<=184 bytes per packet) to callback
|
||||
* @TS_DECODER: Send stream to built-in decoder (if present).
|
||||
* @TS_DEMUX: In case TS_PACKET is set, send the TS to the demux
|
||||
* device, not to the dvr device
|
||||
*/
|
||||
enum ts_filter_type {
|
||||
TS_PACKET = 1,
|
||||
TS_PAYLOAD_ONLY = 2,
|
||||
TS_DECODER = 4,
|
||||
TS_DEMUX = 8,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* TS packet reception */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* TS filter type for set() */
|
||||
|
||||
#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) */
|
||||
#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
|
||||
the demux device, not to the dvr device */
|
||||
|
||||
/**
|
||||
* struct dmx_ts_feed - Structure that contains a TS feed filter
|
||||
*
|
||||
* @is_filtering: Set to non-zero when filtering in progress
|
||||
* @parent: pointer to struct dmx_demux
|
||||
* @priv: pointer to private data of the API client
|
||||
* @set: sets the TS filter
|
||||
* @start_filtering: starts TS filtering
|
||||
* @stop_filtering: stops TS filtering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
struct dmx_ts_feed {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
struct dmx_demux *parent; /* Back-pointer */
|
||||
void *priv; /* Pointer to private data of the API client */
|
||||
int is_filtering;
|
||||
struct dmx_demux *parent;
|
||||
void *priv;
|
||||
int (*set)(struct dmx_ts_feed *feed,
|
||||
u16 pid,
|
||||
int type,
|
||||
enum dmx_ts_pes pes_type,
|
||||
size_t circular_buffer_size,
|
||||
struct timespec timeout);
|
||||
ktime_t timeout);
|
||||
int (*start_filtering)(struct dmx_ts_feed *feed);
|
||||
int (*stop_filtering)(struct dmx_ts_feed *feed);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Section reception */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Section reception
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct dmx_section_filter - Structure that describes a section filter
|
||||
*
|
||||
* @filter_value: Contains up to 16 bytes (128 bits) of the TS section header
|
||||
* that will be matched by the section filter
|
||||
* @filter_mask: Contains a 16 bytes (128 bits) filter mask with the bits
|
||||
* specified by @filter_value that will be used on the filter
|
||||
* match logic.
|
||||
* @filter_mode: Contains a 16 bytes (128 bits) filter mode.
|
||||
* @parent: Pointer to struct dmx_section_feed.
|
||||
* @priv: Pointer to private data of the API client.
|
||||
*
|
||||
*
|
||||
* The @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.
|
||||
*/
|
||||
struct dmx_section_filter {
|
||||
u8 filter_value[DMX_MAX_FILTER_SIZE];
|
||||
u8 filter_mask[DMX_MAX_FILTER_SIZE];
|
||||
@ -109,21 +134,48 @@ struct dmx_section_filter {
|
||||
void *priv; /* Pointer to private data of the API client */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmx_section_feed - Structure that contains a section feed filter
|
||||
*
|
||||
* @is_filtering: Set to non-zero when filtering in progress
|
||||
* @parent: pointer to struct dmx_demux
|
||||
* @priv: pointer to private data of the API client
|
||||
* @check_crc: If non-zero, check the CRC values of filtered sections.
|
||||
* @set: sets the section filter
|
||||
* @allocate_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.
|
||||
* @release_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.
|
||||
* @start_filtering: starts section filtering
|
||||
* @stop_filtering: stops section filtering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
struct dmx_section_feed {
|
||||
int is_filtering; /* Set to non-zero when filtering in progress */
|
||||
struct dmx_demux* parent; /* Back-pointer */
|
||||
void* priv; /* Pointer to private data of the API client */
|
||||
int is_filtering;
|
||||
struct dmx_demux *parent;
|
||||
void *priv;
|
||||
|
||||
int check_crc;
|
||||
|
||||
/* private: Used internally at dvb_demux.c */
|
||||
u32 crc_val;
|
||||
|
||||
u8 *secbuf;
|
||||
u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
|
||||
u16 secbufp, seclen, tsfeedp;
|
||||
|
||||
/* public: */
|
||||
int (*set)(struct dmx_section_feed *feed,
|
||||
u16 pid,
|
||||
size_t circular_buffer_size,
|
||||
int check_crc);
|
||||
int (*allocate_filter)(struct dmx_section_feed *feed,
|
||||
struct dmx_section_filter **filter);
|
||||
@ -133,82 +185,375 @@ struct dmx_section_feed {
|
||||
int (*stop_filtering)(struct dmx_section_feed *feed);
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Callback functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* typedef dmx_ts_cb - DVB demux TS filter callback function prototype
|
||||
*
|
||||
* @buffer1: Pointer to the start of the filtered TS packets.
|
||||
* @buffer1_length: Length of the TS data in buffer1.
|
||||
* @buffer2: Pointer to the tail of the filtered TS packets, or NULL.
|
||||
* @buffer2_length: Length of the TS data in buffer2.
|
||||
* @source: Indicates which TS feed is the source of the callback.
|
||||
*
|
||||
* This function callback prototype, provided by the client of the demux API,
|
||||
* is called from the demux code. The function is only called when filtering
|
||||
* on a TS feed has been enabled using the start_filtering\(\) function at
|
||||
* the &dmx_demux.
|
||||
* 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.
|
||||
* 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 and return -EOVERFLOW.
|
||||
*
|
||||
* The type of data returned to the callback can be selected by the
|
||||
* &dmx_ts_feed.@set function. 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.
|
||||
*
|
||||
* Return:
|
||||
*
|
||||
* - 0, on success;
|
||||
*
|
||||
* - -EOVERFLOW, on buffer overflow.
|
||||
*/
|
||||
typedef int (*dmx_ts_cb)(const u8 *buffer1,
|
||||
size_t buffer1_length,
|
||||
const u8 *buffer2,
|
||||
size_t buffer2_length,
|
||||
struct dmx_ts_feed* source,
|
||||
enum dmx_success success);
|
||||
struct dmx_ts_feed *source);
|
||||
|
||||
/**
|
||||
* typedef dmx_section_cb - DVB demux TS filter callback function prototype
|
||||
*
|
||||
* @buffer1: Pointer to the start of the filtered section, e.g.
|
||||
* within the circular buffer of the demux driver.
|
||||
* @buffer1_len: Length of the filtered section data in @buffer1,
|
||||
* including headers and CRC.
|
||||
* @buffer2: Pointer to the tail of the filtered section data,
|
||||
* or NULL. Useful to handle the wrapping of a
|
||||
* circular buffer.
|
||||
* @buffer2_len: Length of the filtered section data in @buffer2,
|
||||
* including headers and CRC.
|
||||
* @source: Indicates which section feed is the source of the
|
||||
* callback.
|
||||
*
|
||||
* This function callback prototype, 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
|
||||
* &dmx_ts_feed.@start_filtering. 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 &dmx_ts_feed.@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.
|
||||
*/
|
||||
typedef int (*dmx_section_cb)(const u8 *buffer1,
|
||||
size_t buffer1_len,
|
||||
const u8 *buffer2,
|
||||
size_t buffer2_len,
|
||||
struct dmx_section_filter * source,
|
||||
enum dmx_success success);
|
||||
struct dmx_section_filter *source);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DVB Front-End */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* DVB Front-End
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum dmx_frontend_source - Used to identify the type of frontend
|
||||
*
|
||||
* @DMX_MEMORY_FE: The source of the demux is memory. It means that
|
||||
* the MPEG-TS to be filtered comes from userspace,
|
||||
* via write() syscall.
|
||||
*
|
||||
* @DMX_FRONTEND_0: The source of the demux is a frontend connected
|
||||
* to the demux.
|
||||
*/
|
||||
enum dmx_frontend_source {
|
||||
DMX_MEMORY_FE,
|
||||
DMX_FRONTEND_0,
|
||||
DMX_FRONTEND_1,
|
||||
DMX_FRONTEND_2,
|
||||
DMX_FRONTEND_3,
|
||||
DMX_STREAM_0, /* external stream input, e.g. LVDS */
|
||||
DMX_STREAM_1,
|
||||
DMX_STREAM_2,
|
||||
DMX_STREAM_3
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmx_frontend - Structure that lists the frontends associated with
|
||||
* a demux
|
||||
*
|
||||
* @connectivity_list: List of front-ends that can be connected to a
|
||||
* particular demux;
|
||||
* @source: Type of the frontend.
|
||||
*
|
||||
* FIXME: this structure should likely be replaced soon by some
|
||||
* media-controller based logic.
|
||||
*/
|
||||
struct dmx_frontend {
|
||||
struct list_head connectivity_list; /* List of front-ends that can
|
||||
be connected to a particular
|
||||
demux */
|
||||
struct list_head connectivity_list;
|
||||
enum dmx_frontend_source source;
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MPEG-2 TS Demux */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Flags OR'ed in the capabilities field of struct dmx_demux.
|
||||
* MPEG-2 TS Demux
|
||||
*/
|
||||
|
||||
#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
|
||||
/**
|
||||
* enum dmx_demux_caps - MPEG-2 TS Demux capabilities bitmap
|
||||
*
|
||||
* @DMX_TS_FILTERING: set if TS filtering is supported;
|
||||
* @DMX_SECTION_FILTERING: set if section filtering is supported;
|
||||
* @DMX_MEMORY_BASED_FILTERING: set if write() available.
|
||||
*
|
||||
* Those flags are OR'ed in the &dmx_demux.capabilities field
|
||||
*/
|
||||
enum dmx_demux_caps {
|
||||
DMX_TS_FILTERING = 1,
|
||||
DMX_SECTION_FILTERING = 4,
|
||||
DMX_MEMORY_BASED_FILTERING = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
* Demux resource type identifier.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DMX_FE_ENTRY(): Casts elements in the list of registered
|
||||
/**
|
||||
* DMX_FE_ENTRY - Casts elements in the list of registered
|
||||
* front-ends from the generic type struct list_head
|
||||
* to the type * struct dmx_frontend
|
||||
*.
|
||||
*
|
||||
* @list: list of struct dmx_frontend
|
||||
*/
|
||||
#define DMX_FE_ENTRY(list) \
|
||||
list_entry(list, struct dmx_frontend, connectivity_list)
|
||||
|
||||
#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
|
||||
|
||||
/**
|
||||
* struct dmx_demux - Structure that contains the demux capabilities and
|
||||
* callbacks.
|
||||
*
|
||||
* @capabilities: Bitfield of capability flags.
|
||||
*
|
||||
* @frontend: Front-end connected to the demux
|
||||
*
|
||||
* @priv: Pointer to private data of the API client
|
||||
*
|
||||
* @open: 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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EUSERS, if maximum usage count was reached;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @close: 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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -ENODEV, if demux was not in use (e. g. no users);
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @write: 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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @buf function parameter contains a pointer to the TS data in
|
||||
* kernel-space memory.
|
||||
* The @count function parameter contains the length of the TS data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -ERESTARTSYS, if mutex lock was interrupted;
|
||||
* -EINTR, if a signal handling is pending;
|
||||
* -ENODEV, if demux was removed;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @allocate_ts_feed: 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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @feed function parameter contains a pointer to the TS feed API and
|
||||
* instance data.
|
||||
* The @callback function parameter contains a pointer to the callback
|
||||
* function for passing received TS packet.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -ERESTARTSYS, if mutex lock was interrupted;
|
||||
* -EBUSY, if no more TS feeds is available;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @release_ts_feed: Releases the resources allocated with @allocate_ts_feed.
|
||||
* Any filtering in progress on the TS feed should be stopped before
|
||||
* calling this function.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @feed function parameter contains a pointer to the TS feed API and
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL on bad parameter.
|
||||
*
|
||||
* @allocate_section_feed: 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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @feed function parameter contains a pointer to the TS feed API and
|
||||
* instance data.
|
||||
* The @callback function parameter contains a pointer to the callback
|
||||
* function for passing received TS packet.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EBUSY, if no more TS feeds is available;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @release_section_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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @feed function parameter contains a pointer to the TS feed API and
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @add_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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @frontend function parameter contains a pointer to the front-end
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @remove_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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @frontend function parameter contains a pointer to the front-end
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -ENODEV, if the front-end was not found,
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @get_frontends: 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
|
||||
* struct &dmx_frontend *. The caller must not free the memory of any of
|
||||
* the elements obtained via this function call.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* It returns a struct list_head pointer to the list of front-end
|
||||
* interfaces, or NULL in the case of an empty list.
|
||||
*
|
||||
* @connect_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.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @frontend function parameter contains a pointer to the front-end
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL, on bad parameter.
|
||||
*
|
||||
* @disconnect_frontend: Disconnects the demux and a front-end previously
|
||||
* connected by a @connect_frontend call.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL on bad parameter.
|
||||
*
|
||||
* @get_pes_pids: Get the PIDs for DMX_PES_AUDIO0, DMX_PES_VIDEO0,
|
||||
* DMX_PES_TELETEXT0, DMX_PES_SUBTITLE0 and DMX_PES_PCR0.
|
||||
* The @demux function parameter contains a pointer to the demux API and
|
||||
* instance data.
|
||||
* The @pids function parameter contains an array with five u16 elements
|
||||
* where the PIDs will be stored.
|
||||
* It returns:
|
||||
* 0 on success;
|
||||
* -EINVAL on bad parameter.
|
||||
*/
|
||||
struct dmx_demux {
|
||||
u32 capabilities; /* Bitfield of capability flags */
|
||||
struct dmx_frontend* frontend; /* Front-end connected to the demux */
|
||||
void* priv; /* Pointer to private data of the API client */
|
||||
enum dmx_demux_caps capabilities;
|
||||
struct dmx_frontend *frontend;
|
||||
void *priv;
|
||||
int (*open)(struct dmx_demux *demux);
|
||||
int (*close)(struct dmx_demux *demux);
|
||||
int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
|
||||
int (*write)(struct dmx_demux *demux, const char __user *buf,
|
||||
size_t count);
|
||||
int (*allocate_ts_feed)(struct dmx_demux *demux,
|
||||
struct dmx_ts_feed **feed,
|
||||
dmx_ts_cb callback);
|
||||
@ -230,10 +575,13 @@ struct dmx_demux {
|
||||
|
||||
int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids);
|
||||
|
||||
int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
|
||||
|
||||
int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
|
||||
/* private: */
|
||||
|
||||
/*
|
||||
* Only used at av7110, to read some data from firmware.
|
||||
* As this was never documented, we have no clue about what's
|
||||
* there, and its usage on other drivers aren't encouraged.
|
||||
*/
|
||||
int (*get_stc)(struct dmx_demux *demux, unsigned int num,
|
||||
u64 *stc, unsigned int *base);
|
||||
};
|
||||
|
@ -14,12 +14,10 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dmxdev: " fmt
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
@ -28,7 +26,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "dmxdev.h"
|
||||
|
||||
static int debug;
|
||||
@ -36,7 +34,11 @@ static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define dprintk if (debug) printk
|
||||
#define dprintk(fmt, arg...) do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
|
||||
__func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
|
||||
const u8 *src, size_t len)
|
||||
@ -50,7 +52,7 @@ static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
|
||||
|
||||
free = dvb_ringbuffer_free(buf);
|
||||
if (len > free) {
|
||||
dprintk("dmxdev: buffer overflow\n");
|
||||
dprintk("buffer overflow\n");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
@ -126,7 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
||||
struct dmxdev *dmxdev = dvbdev->priv;
|
||||
struct dmx_frontend *front;
|
||||
|
||||
dprintk("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
@ -145,6 +147,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
void *mem;
|
||||
|
||||
if (!dvbdev->readers) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -EBUSY;
|
||||
@ -196,6 +199,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
||||
dvbdev->readers++;
|
||||
if (dmxdev->dvr_buffer.data) {
|
||||
void *mem = dmxdev->dvr_buffer.data;
|
||||
/*memory barrier*/
|
||||
mb();
|
||||
spin_lock_irq(&dmxdev->lock);
|
||||
dmxdev->dvr_buffer.data = NULL;
|
||||
@ -206,8 +210,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
||||
/* TODO */
|
||||
dvbdev->users--;
|
||||
if (dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else
|
||||
@ -260,7 +262,7 @@ static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
|
||||
void *newmem;
|
||||
void *oldmem;
|
||||
|
||||
dprintk("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (buf->size == size)
|
||||
return 0;
|
||||
@ -354,8 +356,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
||||
|
||||
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
const u8 *buffer2, size_t buffer2_len,
|
||||
struct dmx_section_filter *filter,
|
||||
enum dmx_success success)
|
||||
struct dmx_section_filter *filter)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = filter->priv;
|
||||
int ret;
|
||||
@ -370,7 +371,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
return 0;
|
||||
}
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
|
||||
dprintk("section callback %*ph\n", 6, buffer1);
|
||||
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
|
||||
buffer1_len);
|
||||
if (ret == buffer1_len) {
|
||||
@ -388,8 +389,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
|
||||
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
const u8 *buffer2, size_t buffer2_len,
|
||||
struct dmx_ts_feed *feed,
|
||||
enum dmx_success success)
|
||||
struct dmx_ts_feed *feed)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||
struct dvb_ringbuffer *buffer;
|
||||
@ -560,14 +560,15 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
||||
struct dmxdev_filter *filter,
|
||||
struct dmxdev_feed *feed)
|
||||
{
|
||||
struct timespec timeout = { 0 };
|
||||
ktime_t timeout;
|
||||
struct dmx_pes_filter_params *para = &filter->params.pes;
|
||||
dmx_output_t otype;
|
||||
enum dmx_output otype;
|
||||
int ret;
|
||||
int ts_type;
|
||||
enum dmx_ts_pes ts_pes;
|
||||
struct dmx_ts_feed *tsfeed;
|
||||
|
||||
timeout = ktime_set(0, 0);
|
||||
feed->ts = NULL;
|
||||
otype = para->output;
|
||||
|
||||
@ -593,7 +594,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
||||
tsfeed = feed->ts;
|
||||
tsfeed->priv = filter;
|
||||
|
||||
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
|
||||
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout);
|
||||
if (ret < 0) {
|
||||
dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
|
||||
return ret;
|
||||
@ -659,15 +660,15 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
|
||||
secfeed,
|
||||
dvb_dmxdev_section_callback);
|
||||
if (ret < 0) {
|
||||
printk("DVB (%s): could not alloc feed\n",
|
||||
pr_err("DVB (%s): could not alloc feed\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (*secfeed)->set(*secfeed, para->pid, 32768,
|
||||
ret = (*secfeed)->set(*secfeed, para->pid,
|
||||
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
|
||||
if (ret < 0) {
|
||||
printk("DVB (%s): could not set feed\n",
|
||||
pr_err("DVB (%s): could not set feed\n",
|
||||
__func__);
|
||||
dvb_dmxdev_feed_restart(filter);
|
||||
return ret;
|
||||
@ -787,7 +788,7 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void invert_mode(dmx_filter_t *filter)
|
||||
static inline void invert_mode(struct dmx_filter *filter)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -848,7 +849,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
|
||||
struct dmxdev_filter *dmxdevfilter,
|
||||
struct dmx_sct_filter_params *params)
|
||||
{
|
||||
dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
|
||||
dprintk("%s: PID=0x%04x, flags=%02x, timeout=%d\n",
|
||||
__func__, params->pid, params->flags, params->timeout);
|
||||
|
||||
dvb_dmxdev_filter_stop(dmxdevfilter);
|
||||
@ -874,7 +875,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
|
||||
dvb_dmxdev_filter_stop(dmxdevfilter);
|
||||
dvb_dmxdev_filter_reset(dmxdevfilter);
|
||||
|
||||
if ((unsigned)params->pes_type > DMX_PES_OTHER)
|
||||
if ((unsigned int)params->pes_type > DMX_PES_OTHER)
|
||||
return -EINVAL;
|
||||
|
||||
dmxdevfilter->type = DMXDEV_TYPE_PES;
|
||||
@ -1025,22 +1026,6 @@ static int dvb_demux_do_ioctl(struct file *file,
|
||||
dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_GET_CAPS:
|
||||
if (!dmxdev->demux->get_caps) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_SET_SOURCE:
|
||||
if (!dmxdev->demux->set_source) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = dmxdev->demux->set_source(dmxdev->demux, parg);
|
||||
break;
|
||||
|
||||
case DMX_GET_STC:
|
||||
if (!dmxdev->demux->get_stc) {
|
||||
ret = -EINVAL;
|
||||
@ -1089,8 +1074,8 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
|
||||
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (!dmxdevfilter)
|
||||
return -EINVAL;
|
||||
if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
|
||||
return POLLERR;
|
||||
|
||||
poll_wait(file, &dmxdevfilter->buffer.queue, wait);
|
||||
|
||||
@ -1120,8 +1105,6 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
|
||||
mutex_lock(&dmxdev->mutex);
|
||||
dmxdev->dvbdev->users--;
|
||||
if (dmxdev->dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
wake_up(&dmxdev->dvbdev->wait_queue);
|
||||
} else
|
||||
@ -1140,10 +1123,13 @@ static const struct file_operations dvb_demux_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static struct dvb_device dvbdev_demux = {
|
||||
static const struct dvb_device dvbdev_demux = {
|
||||
.priv = NULL,
|
||||
.users = 1,
|
||||
.writers = 1,
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
.name = "dvb-demux",
|
||||
#endif
|
||||
.fops = &dvb_demux_fops
|
||||
};
|
||||
|
||||
@ -1183,7 +1169,10 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
|
||||
struct dmxdev *dmxdev = dvbdev->priv;
|
||||
unsigned int mask = 0;
|
||||
|
||||
dprintk("function : %s\n", __func__);
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (dmxdev->exit)
|
||||
return POLLERR;
|
||||
|
||||
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
|
||||
|
||||
@ -1210,13 +1199,15 @@ static const struct file_operations dvb_dvr_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static struct dvb_device dvbdev_dvr = {
|
||||
static const struct dvb_device dvbdev_dvr = {
|
||||
.priv = NULL,
|
||||
.readers = 1,
|
||||
.users = 1,
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
.name = "dvb-dvr",
|
||||
#endif
|
||||
.fops = &dvb_dvr_fops
|
||||
};
|
||||
|
||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||
{
|
||||
int i;
|
||||
@ -1238,9 +1229,9 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||
}
|
||||
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||
DVB_DEVICE_DEMUX);
|
||||
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||
dmxdev, DVB_DEVICE_DVR);
|
||||
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
||||
|
||||
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
||||
|
||||
|
@ -14,10 +14,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DMXDEV_H_
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,10 +12,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_CA_EN50221_H_
|
||||
@ -37,104 +33,110 @@
|
||||
#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0
|
||||
#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1
|
||||
|
||||
|
||||
|
||||
/* Structure describing a CA interface */
|
||||
struct dvb_ca_en50221 {
|
||||
|
||||
/* the module owning this structure */
|
||||
struct module* owner;
|
||||
|
||||
/* NOTE: the read_*, write_* and poll_slot_status functions will be
|
||||
/**
|
||||
* struct dvb_ca_en50221- Structure describing a CA interface
|
||||
*
|
||||
* @owner: the module owning this structure
|
||||
* @read_attribute_mem: function for reading attribute memory on the CAM
|
||||
* @write_attribute_mem: function for writing attribute memory on the CAM
|
||||
* @read_cam_control: function for reading the control interface on the CAM
|
||||
* @write_cam_control: function for reading the control interface on the CAM
|
||||
* @read_data: function for reading data (block mode)
|
||||
* @write_data: function for writing data (block mode)
|
||||
* @slot_reset: function to reset the CAM slot
|
||||
* @slot_shutdown: function to shutdown a CAM slot
|
||||
* @slot_ts_enable: function to enable the Transport Stream on a CAM slot
|
||||
* @poll_slot_status: function to poll slot status. Only necessary if
|
||||
* DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set.
|
||||
* @data: private data, used by caller.
|
||||
* @private: Opaque data used by the dvb_ca core. Do not modify!
|
||||
*
|
||||
* NOTE: the read_*, write_* and poll_slot_status functions will be
|
||||
* called for different slots concurrently and need to use locks where
|
||||
* and if appropriate. There will be no concurrent access to one slot.
|
||||
*/
|
||||
struct dvb_ca_en50221 {
|
||||
struct module *owner;
|
||||
|
||||
/* functions for accessing attribute memory on the CAM */
|
||||
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
|
||||
int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
|
||||
int (*read_attribute_mem)(struct dvb_ca_en50221 *ca,
|
||||
int slot, int address);
|
||||
int (*write_attribute_mem)(struct dvb_ca_en50221 *ca,
|
||||
int slot, int address, u8 value);
|
||||
|
||||
/* functions for accessing the control interface on the CAM */
|
||||
int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
|
||||
int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
|
||||
int (*read_cam_control)(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 address);
|
||||
int (*write_cam_control)(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 address, u8 value);
|
||||
|
||||
/* functions for readin/writing data */
|
||||
int (*read_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
|
||||
int (*write_data)(struct dvb_ca_en50221* ca, int slot, u8 *ebuf, int ecount);
|
||||
int (*read_data)(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 *ebuf, int ecount);
|
||||
int (*write_data)(struct dvb_ca_en50221 *ca,
|
||||
int slot, u8 *ebuf, int ecount);
|
||||
|
||||
/* Functions for controlling slots */
|
||||
int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot);
|
||||
int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot);
|
||||
int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot);
|
||||
|
||||
/*
|
||||
* Poll slot status.
|
||||
* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
|
||||
*/
|
||||
int (*poll_slot_status)(struct dvb_ca_en50221 *ca, int slot, int open);
|
||||
|
||||
/* private data, used by caller */
|
||||
void *data;
|
||||
|
||||
/* Opaque data used by the dvb_ca core. Do not modify! */
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* ******************************************************************************** */
|
||||
/* Functions for reporting IRQ events */
|
||||
|
||||
/**
|
||||
* A CAMCHANGE IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
* @param change_type One of the DVB_CA_CAMCHANGE_* values
|
||||
/*
|
||||
* Functions for reporting IRQ events
|
||||
*/
|
||||
void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
|
||||
|
||||
/**
|
||||
* A CAMREADY IRQ has occurred.
|
||||
* dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
* @pubca: CA instance.
|
||||
* @slot: Slot concerned.
|
||||
* @change_type: One of the DVB_CA_CAMCHANGE_* values
|
||||
*/
|
||||
void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot,
|
||||
int change_type);
|
||||
|
||||
/**
|
||||
* dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred.
|
||||
*
|
||||
* @pubca: CA instance.
|
||||
* @slot: Slot concerned.
|
||||
*/
|
||||
void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot);
|
||||
|
||||
/**
|
||||
* An FR or a DA IRQ has occurred.
|
||||
* dvb_ca_en50221_frda_irq - An FR or a DA IRQ has occurred.
|
||||
*
|
||||
* @param ca CA instance.
|
||||
* @param slot Slot concerned.
|
||||
* @ca: CA instance.
|
||||
* @slot: Slot concerned.
|
||||
*/
|
||||
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *ca, int slot);
|
||||
|
||||
|
||||
|
||||
/* ******************************************************************************** */
|
||||
/* Initialisation/shutdown functions */
|
||||
/*
|
||||
* Initialisation/shutdown functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise a new DVB CA device.
|
||||
* dvb_ca_en50221_init - Initialise a new DVB CA device.
|
||||
*
|
||||
* @param dvb_adapter DVB adapter to attach the new CA device to.
|
||||
* @param ca The dvb_ca instance.
|
||||
* @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
|
||||
* @param slot_count Number of slots supported.
|
||||
* @dvb_adapter: DVB adapter to attach the new CA device to.
|
||||
* @ca: The dvb_ca instance.
|
||||
* @flags: Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
|
||||
* @slot_count: Number of slots supported.
|
||||
*
|
||||
* @return 0 on success, nonzero on failure
|
||||
*/
|
||||
extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
|
||||
int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
||||
struct dvb_ca_en50221 *ca, int flags,
|
||||
int slot_count);
|
||||
|
||||
/**
|
||||
* Release a DVB CA device.
|
||||
* dvb_ca_en50221_release - Release a DVB CA device.
|
||||
*
|
||||
* @param ca The associated dvb_ca instance.
|
||||
* @ca: The associated dvb_ca instance.
|
||||
*/
|
||||
extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
|
||||
|
||||
|
||||
void dvb_ca_en50221_release(struct dvb_ca_en50221 *ca);
|
||||
|
||||
#endif
|
||||
|
@ -15,12 +15,10 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dvb_demux: " fmt
|
||||
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
#include <linux/sched/signal.h>
|
||||
@ -34,16 +32,18 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_demux.h"
|
||||
|
||||
#define NOBUFS
|
||||
/*
|
||||
** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
|
||||
*/
|
||||
// #define DVB_DEMUX_SECTION_LOSS_LOG
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
|
||||
static inline s64 ktime_ms_delta(const ktime_t later, const ktime_t earlier)
|
||||
{
|
||||
return ktime_to_ms(ktime_sub(later, earlier));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dvb_demux_tscheck;
|
||||
module_param(dvb_demux_tscheck, int, 0644);
|
||||
@ -60,9 +60,12 @@ module_param(dvb_demux_feed_err_pkts, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
|
||||
"when set to 0, drop packets with the TEI bit set (1 by default)");
|
||||
|
||||
#define dprintk(fmt, arg...) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
|
||||
|
||||
#define dprintk_tscheck(x...) do { \
|
||||
if (dvb_demux_tscheck && printk_ratelimit()) \
|
||||
printk(x); \
|
||||
dprintk(x); \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************
|
||||
@ -114,28 +117,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
|
||||
{
|
||||
int count = payload(buf);
|
||||
int p;
|
||||
//int ccok;
|
||||
//u8 cc;
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
int ccok;
|
||||
u8 cc;
|
||||
#endif
|
||||
|
||||
if (count == 0)
|
||||
return -1;
|
||||
|
||||
p = 188 - count;
|
||||
|
||||
/*
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
if (!ccok)
|
||||
printk("missed packet!\n");
|
||||
*/
|
||||
dprintk("missed packet!\n");
|
||||
#endif
|
||||
|
||||
if (buf[1] & 0x40) // PUSI ?
|
||||
feed->peslen = 0xfffa;
|
||||
|
||||
feed->peslen += count;
|
||||
|
||||
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
|
||||
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
|
||||
}
|
||||
|
||||
static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
|
||||
@ -157,7 +162,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
|
||||
return 0;
|
||||
|
||||
return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
|
||||
NULL, 0, &f->filter, DMX_OK);
|
||||
NULL, 0, &f->filter);
|
||||
}
|
||||
|
||||
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
|
||||
@ -194,7 +199,7 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
|
||||
{
|
||||
struct dmx_section_feed *sec = &feed->feed.sec;
|
||||
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
if (sec->secbufp < sec->tsfeedp) {
|
||||
int i, n = sec->tsfeedp - sec->secbufp;
|
||||
|
||||
@ -204,12 +209,12 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
|
||||
* but just first and last.
|
||||
*/
|
||||
if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
|
||||
printk("dvb_demux.c section ts padding loss: %d/%d\n",
|
||||
dprintk("dvb_demux.c section ts padding loss: %d/%d\n",
|
||||
n, sec->tsfeedp);
|
||||
printk("dvb_demux.c pad data:");
|
||||
dprintk("dvb_demux.c pad data:");
|
||||
for (i = 0; i < n; i++)
|
||||
printk(" %02x", sec->secbuf[i]);
|
||||
printk("\n");
|
||||
pr_cont(" %02x", sec->secbuf[i]);
|
||||
pr_cont("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -247,8 +252,8 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
|
||||
return 0;
|
||||
|
||||
if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
printk("dvb_demux.c section buffer full loss: %d/%d\n",
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
dprintk("dvb_demux.c section buffer full loss: %d/%d\n",
|
||||
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
|
||||
DMX_MAX_SECFEED_SIZE);
|
||||
#endif
|
||||
@ -281,9 +286,9 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
|
||||
/* dump [secbuf .. secbuf+seclen) */
|
||||
if (feed->pusi_seen)
|
||||
dvb_dmx_swfilter_section_feed(feed);
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
else
|
||||
printk("dvb_demux.c pusi not seen, discarding section data\n");
|
||||
dprintk("dvb_demux.c pusi not seen, discarding section data\n");
|
||||
#endif
|
||||
sec->secbufp += seclen; /* secbufp and secbuf moving together is */
|
||||
sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
|
||||
@ -317,8 +322,8 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
}
|
||||
|
||||
if (!ccok || dc_i) {
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
printk("dvb_demux.c discontinuity detected %d bytes lost\n",
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
dprintk("dvb_demux.c discontinuity detected %d bytes lost\n",
|
||||
count);
|
||||
/*
|
||||
* those bytes under sume circumstances will again be reported
|
||||
@ -349,9 +354,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
dvb_dmx_swfilter_section_copy_dump(feed, after,
|
||||
after_len);
|
||||
}
|
||||
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
|
||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
|
||||
else if (count > 0)
|
||||
printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
|
||||
dprintk("dvb_demux.c PUSI=1 but %d bytes lost\n",
|
||||
count);
|
||||
#endif
|
||||
} else {
|
||||
/* PUSI=0 (is not set), no section boundary */
|
||||
@ -372,8 +378,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
|
||||
if (feed->ts_type & TS_PAYLOAD_ONLY)
|
||||
dvb_dmx_swfilter_payload(feed, buf);
|
||||
else
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
|
||||
DMX_OK);
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
|
||||
}
|
||||
if (feed->ts_type & TS_DECODER)
|
||||
if (feed->demux->write_to_decoder)
|
||||
@ -404,29 +409,24 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
int dvr_done = 0;
|
||||
|
||||
if (dvb_demux_speedcheck) {
|
||||
struct timespec cur_time, delta_time;
|
||||
ktime_t cur_time;
|
||||
u64 speed_bytes, speed_timedelta;
|
||||
|
||||
demux->speed_pkts_cnt++;
|
||||
|
||||
/* show speed every SPEED_PKTS_INTERVAL packets */
|
||||
if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) {
|
||||
cur_time = current_kernel_time();
|
||||
cur_time = ktime_get();
|
||||
|
||||
if (demux->speed_last_time.tv_sec != 0 &&
|
||||
demux->speed_last_time.tv_nsec != 0) {
|
||||
delta_time = timespec_sub(cur_time,
|
||||
demux->speed_last_time);
|
||||
if (ktime_to_ns(demux->speed_last_time) != 0) {
|
||||
speed_bytes = (u64)demux->speed_pkts_cnt
|
||||
* 188 * 8;
|
||||
/* convert to 1024 basis */
|
||||
speed_bytes = 1000 * div64_u64(speed_bytes,
|
||||
1024);
|
||||
speed_timedelta =
|
||||
(u64)timespec_to_ns(&delta_time);
|
||||
speed_timedelta = div64_u64(speed_timedelta,
|
||||
1000000); /* nsec -> usec */
|
||||
printk(KERN_INFO "TS speed %llu Kbits/sec \n",
|
||||
speed_timedelta = ktime_ms_delta(cur_time,
|
||||
demux->speed_last_time);
|
||||
dprintk("TS speed %llu Kbits/sec \n",
|
||||
div64_u64(speed_bytes,
|
||||
speed_timedelta));
|
||||
}
|
||||
@ -437,10 +437,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
}
|
||||
|
||||
if (buf[1] & 0x80) {
|
||||
dprintk_tscheck("TEI detected. "
|
||||
"PID=0x%x data1=0x%x\n",
|
||||
dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
|
||||
pid, buf[1]);
|
||||
/* data in this packet cant be trusted - drop it unless
|
||||
/* data in this packet can't be trusted - drop it unless
|
||||
* module option dvb_demux_feed_err_pkts is set */
|
||||
if (!dvb_demux_feed_err_pkts)
|
||||
return;
|
||||
@ -474,14 +473,16 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
if (feed->pid == pid)
|
||||
dvb_dmx_swfilter_packet_type(feed, buf);
|
||||
else if (feed->pid == 0x2000)
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
|
||||
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
|
||||
}
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
while (count--) {
|
||||
if (buf[0] == 0x47)
|
||||
@ -489,7 +490,7 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
buf += 188;
|
||||
}
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
@ -524,8 +525,9 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
{
|
||||
int p = 0, i, j;
|
||||
const u8 *q;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
|
||||
i = demux->tsbufp;
|
||||
@ -569,7 +571,7 @@ static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
@ -586,11 +588,13 @@ EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
||||
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
|
||||
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
|
||||
|
||||
@ -641,7 +645,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
|
||||
{
|
||||
spin_lock_irq(&feed->demux->lock);
|
||||
if (dvb_demux_feed_find(feed)) {
|
||||
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
|
||||
pr_err("%s: feed already in list (type=%x state=%x pid=%x)\n",
|
||||
__func__, feed->type, feed->state, feed->pid);
|
||||
goto out;
|
||||
}
|
||||
@ -655,7 +659,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
|
||||
{
|
||||
spin_lock_irq(&feed->demux->lock);
|
||||
if (!(dvb_demux_feed_find(feed))) {
|
||||
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
|
||||
pr_err("%s: feed not in list (type=%x state=%x pid=%x)\n",
|
||||
__func__, feed->type, feed->state, feed->pid);
|
||||
goto out;
|
||||
}
|
||||
@ -666,8 +670,7 @@ out:
|
||||
}
|
||||
|
||||
static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
|
||||
enum dmx_ts_pes pes_type,
|
||||
size_t circular_buffer_size, struct timespec timeout)
|
||||
enum dmx_ts_pes pes_type, ktime_t timeout)
|
||||
{
|
||||
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
|
||||
struct dvb_demux *demux = feed->demux;
|
||||
@ -697,23 +700,10 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
|
||||
dvb_demux_feed_add(feed);
|
||||
|
||||
feed->pid = pid;
|
||||
feed->buffer_size = circular_buffer_size;
|
||||
feed->timeout = timeout;
|
||||
feed->ts_type = ts_type;
|
||||
feed->pes_type = pes_type;
|
||||
|
||||
if (feed->buffer_size) {
|
||||
#ifdef NOBUFS
|
||||
feed->buffer = NULL;
|
||||
#else
|
||||
feed->buffer = vmalloc(feed->buffer_size);
|
||||
if (!feed->buffer) {
|
||||
mutex_unlock(&demux->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
feed->state = DMX_STATE_READY;
|
||||
mutex_unlock(&demux->mutex);
|
||||
|
||||
@ -802,7 +792,6 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
|
||||
feed->demux = demux;
|
||||
feed->pid = 0xffff;
|
||||
feed->peslen = 0xfffa;
|
||||
feed->buffer = NULL;
|
||||
|
||||
(*ts_feed) = &feed->feed.ts;
|
||||
(*ts_feed)->parent = dmx;
|
||||
@ -839,10 +828,6 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
|
||||
mutex_unlock(&demux->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
#ifndef NOBUFS
|
||||
vfree(feed->buffer);
|
||||
feed->buffer = NULL;
|
||||
#endif
|
||||
|
||||
feed->state = DMX_STATE_FREE;
|
||||
feed->filter->state = DMX_STATE_FREE;
|
||||
@ -894,8 +879,7 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
|
||||
}
|
||||
|
||||
static int dmx_section_feed_set(struct dmx_section_feed *feed,
|
||||
u16 pid, size_t circular_buffer_size,
|
||||
int check_crc)
|
||||
u16 pid, int check_crc)
|
||||
{
|
||||
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
|
||||
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
|
||||
@ -909,19 +893,8 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed,
|
||||
dvb_demux_feed_add(dvbdmxfeed);
|
||||
|
||||
dvbdmxfeed->pid = pid;
|
||||
dvbdmxfeed->buffer_size = circular_buffer_size;
|
||||
dvbdmxfeed->feed.sec.check_crc = check_crc;
|
||||
|
||||
#ifdef NOBUFS
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
#else
|
||||
dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
|
||||
if (!dvbdmxfeed->buffer) {
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
dvbdmxfeed->state = DMX_STATE_READY;
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return 0;
|
||||
@ -1032,8 +1005,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (feed->is_filtering)
|
||||
if (feed->is_filtering) {
|
||||
/* release dvbdmx->mutex as far as it is
|
||||
acquired by stop_filtering() itself */
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
feed->stop_filtering(feed);
|
||||
mutex_lock(&dvbdmx->mutex);
|
||||
}
|
||||
|
||||
spin_lock_irq(&dvbdmx->lock);
|
||||
f = dvbdmxfeed->filter;
|
||||
@ -1075,7 +1053,6 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
|
||||
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
|
||||
dvbdmxfeed->feed.sec.tsfeedp = 0;
|
||||
dvbdmxfeed->filter = NULL;
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
|
||||
(*feed) = &dvbdmxfeed->feed.sec;
|
||||
(*feed)->is_filtering = 0;
|
||||
@ -1104,10 +1081,6 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
|
||||
mutex_unlock(&dvbdmx->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
#ifndef NOBUFS
|
||||
vfree(dvbdmxfeed->buffer);
|
||||
dvbdmxfeed->buffer = NULL;
|
||||
#endif
|
||||
dvbdmxfeed->state = DMX_STATE_FREE;
|
||||
|
||||
dvb_demux_feed_del(dvbdmxfeed);
|
||||
@ -1269,7 +1242,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
|
||||
|
||||
dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
|
||||
if (!dvbdemux->cnt_storage)
|
||||
printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
|
||||
pr_warn("Couldn't allocate memory for TS/TEI check. Disabling it\n");
|
||||
|
||||
INIT_LIST_HEAD(&dvbdemux->frontend_list);
|
||||
|
||||
|
@ -14,10 +14,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DVB_DEMUX_H_
|
||||
@ -80,10 +76,8 @@ struct dvb_demux_feed {
|
||||
int type;
|
||||
int state;
|
||||
u16 pid;
|
||||
u8 *buffer;
|
||||
int buffer_size;
|
||||
|
||||
struct timespec timeout;
|
||||
ktime_t timeout;
|
||||
struct dvb_demux_filter *filter;
|
||||
|
||||
int ts_type;
|
||||
@ -134,7 +128,7 @@ struct dvb_demux {
|
||||
|
||||
uint8_t *cnt_storage; /* for TS continuity check */
|
||||
|
||||
struct timespec speed_last_time; /* for TS speed check */
|
||||
ktime_t speed_last_time; /* for TS speed check */
|
||||
uint32_t speed_pkts_cnt; /* for TS speed check */
|
||||
};
|
||||
|
||||
|
@ -18,19 +18,23 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
* To obtain the license, point your browser to
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/* Enables DVBv3 compatibility bits at the headers */
|
||||
#define __DVB_CORE__
|
||||
|
||||
#define pr_fmt(fmt) "dvb_frontend: " fmt
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
#include <linux/sched/signal.h>
|
||||
#else
|
||||
#include <linux/sched.h>
|
||||
#endif
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
@ -40,6 +44,7 @@
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
@ -66,6 +71,9 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt
|
||||
module_param(dvb_mfe_wait_time, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
|
||||
|
||||
#define dprintk(fmt, arg...) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
|
||||
|
||||
#define FESTATE_IDLE 1
|
||||
#define FESTATE_RETUNE 2
|
||||
#define FESTATE_TUNING_FAST 4
|
||||
@ -80,7 +88,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
|
||||
#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
|
||||
#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
|
||||
|
||||
#define FE_ALGO_HW 1
|
||||
/*
|
||||
* FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
|
||||
* FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
|
||||
@ -96,14 +103,9 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
|
||||
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
|
||||
*/
|
||||
|
||||
#define DVB_FE_NO_EXIT 0
|
||||
#define DVB_FE_NORMAL_EXIT 1
|
||||
#define DVB_FE_DEVICE_REMOVED 2
|
||||
|
||||
static DEFINE_MUTEX(frontend_mutex);
|
||||
|
||||
struct dvb_frontend_private {
|
||||
|
||||
/* thread/frontend values */
|
||||
struct dvb_device *dvbdev;
|
||||
struct dvb_frontend_parameters parameters_out;
|
||||
@ -113,9 +115,8 @@ struct dvb_frontend_private {
|
||||
wait_queue_head_t wait_queue;
|
||||
struct task_struct *thread;
|
||||
unsigned long release_jiffies;
|
||||
unsigned int exit;
|
||||
unsigned int wakeup;
|
||||
fe_status_t status;
|
||||
enum fe_status status;
|
||||
unsigned long tune_mode_flags;
|
||||
unsigned int delay;
|
||||
unsigned int reinitialise;
|
||||
@ -136,12 +137,45 @@ struct dvb_frontend_private {
|
||||
int quality;
|
||||
unsigned int check_wrapped;
|
||||
enum dvbfe_search algo_status;
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
struct media_pipeline pipe;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
|
||||
void (*release)(struct dvb_frontend *fe));
|
||||
|
||||
static void dvb_frontend_free(struct kref *ref)
|
||||
{
|
||||
struct dvb_frontend *fe =
|
||||
container_of(ref, struct dvb_frontend, refcount);
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
|
||||
dvb_free_device(fepriv->dvbdev);
|
||||
|
||||
dvb_frontend_invoke_release(fe, fe->ops.release);
|
||||
|
||||
kfree(fepriv);
|
||||
}
|
||||
|
||||
static void dvb_frontend_put(struct dvb_frontend *fe)
|
||||
{
|
||||
kref_put(&fe->refcount, dvb_frontend_free);
|
||||
}
|
||||
|
||||
static void dvb_frontend_get(struct dvb_frontend *fe)
|
||||
{
|
||||
kref_get(&fe->refcount);
|
||||
}
|
||||
|
||||
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
|
||||
static int dtv_get_frontend(struct dvb_frontend *fe,
|
||||
struct dtv_frontend_properties *c,
|
||||
struct dvb_frontend_parameters *p_out);
|
||||
static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
|
||||
static int
|
||||
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
|
||||
const struct dtv_frontend_properties *c,
|
||||
struct dvb_frontend_parameters *p);
|
||||
|
||||
static bool has_get_frontend(struct dvb_frontend *fe)
|
||||
@ -198,9 +232,11 @@ static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
|
||||
}
|
||||
}
|
||||
|
||||
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
||||
static void dvb_frontend_add_event(struct dvb_frontend *fe,
|
||||
enum fe_status status)
|
||||
{
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_fe_events *events = &fepriv->events;
|
||||
struct dvb_frontend_event *e;
|
||||
int wp;
|
||||
@ -208,7 +244,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
|
||||
dtv_get_frontend(fe, &fepriv->parameters_out);
|
||||
dtv_get_frontend(fe, c, &fepriv->parameters_out);
|
||||
|
||||
mutex_lock(&events->mtx);
|
||||
|
||||
@ -429,7 +465,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
|
||||
|
||||
static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
||||
{
|
||||
fe_status_t s = 0;
|
||||
enum fe_status s = FE_NONE;
|
||||
int retval = 0;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
|
||||
@ -565,7 +601,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT)
|
||||
if (fe->exit != DVB_FE_NO_EXIT)
|
||||
return 1;
|
||||
|
||||
if (fepriv->dvbdev->writers == 1)
|
||||
@ -598,10 +634,10 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
|
||||
static int dvb_frontend_thread(void *data)
|
||||
{
|
||||
struct dvb_frontend *fe = data;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
fe_status_t s;
|
||||
enum fe_status s = FE_NONE;
|
||||
enum dvbfe_algo algo;
|
||||
|
||||
bool re_tune = false;
|
||||
bool semheld = false;
|
||||
|
||||
@ -629,7 +665,7 @@ restart:
|
||||
/* got signal or quitting */
|
||||
if (!down_interruptible(&fepriv->sem))
|
||||
semheld = true;
|
||||
fepriv->exit = DVB_FE_NORMAL_EXIT;
|
||||
fe->exit = DVB_FE_NORMAL_EXIT;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -701,7 +737,7 @@ restart:
|
||||
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
|
||||
fepriv->delay = HZ / 2;
|
||||
}
|
||||
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
|
||||
dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out);
|
||||
fe->ops.read_status(fe, &s);
|
||||
if (s != fepriv->status) {
|
||||
dvb_frontend_add_event(fe, s); /* update event list */
|
||||
@ -739,9 +775,9 @@ restart:
|
||||
|
||||
fepriv->thread = NULL;
|
||||
if (kthread_should_stop())
|
||||
fepriv->exit = DVB_FE_DEVICE_REMOVED;
|
||||
fe->exit = DVB_FE_DEVICE_REMOVED;
|
||||
else
|
||||
fepriv->exit = DVB_FE_NO_EXIT;
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
mb();
|
||||
|
||||
if (semheld)
|
||||
@ -756,7 +792,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
fepriv->exit = DVB_FE_NORMAL_EXIT;
|
||||
if (fe->exit != DVB_FE_DEVICE_REMOVED)
|
||||
fe->exit = DVB_FE_NORMAL_EXIT;
|
||||
mb();
|
||||
|
||||
if (!fepriv->thread)
|
||||
@ -774,43 +811,22 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
||||
fepriv->thread);
|
||||
}
|
||||
|
||||
s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
|
||||
{
|
||||
return ((curtime.tv_usec < lasttime.tv_usec) ?
|
||||
1000000 - lasttime.tv_usec + curtime.tv_usec :
|
||||
curtime.tv_usec - lasttime.tv_usec);
|
||||
}
|
||||
EXPORT_SYMBOL(timeval_usec_diff);
|
||||
|
||||
static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
|
||||
{
|
||||
curtime->tv_usec += add_usec;
|
||||
if (curtime->tv_usec >= 1000000) {
|
||||
curtime->tv_usec -= 1000000;
|
||||
curtime->tv_sec++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep until gettimeofday() > waketime + add_usec
|
||||
* This needs to be as precise as possible, but as the delay is
|
||||
* usually between 2ms and 32ms, it is done using a scheduled msleep
|
||||
* followed by usleep (normally a busy-wait loop) for the remainder
|
||||
* Sleep for the amount of time given by add_usec parameter
|
||||
*
|
||||
* This needs to be as precise as possible, as it affects the detection of
|
||||
* the dish tone command at the satellite subsystem. The precision is improved
|
||||
* by using a scheduled msleep followed by udelay for the remainder.
|
||||
*/
|
||||
void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
|
||||
void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec)
|
||||
{
|
||||
struct timeval lasttime;
|
||||
s32 delta, newdelta;
|
||||
s32 delta;
|
||||
|
||||
timeval_usec_add(waketime, add_usec);
|
||||
|
||||
do_gettimeofday(&lasttime);
|
||||
delta = timeval_usec_diff(lasttime, *waketime);
|
||||
*waketime = ktime_add_us(*waketime, add_usec);
|
||||
delta = ktime_us_delta(ktime_get_boottime(), *waketime);
|
||||
if (delta > 2500) {
|
||||
msleep((delta - 1500) / 1000);
|
||||
do_gettimeofday(&lasttime);
|
||||
newdelta = timeval_usec_diff(lasttime, *waketime);
|
||||
delta = (newdelta > delta) ? 0 : newdelta;
|
||||
delta = ktime_us_delta(ktime_get_boottime(), *waketime);
|
||||
}
|
||||
if (delta > 0)
|
||||
udelay(delta);
|
||||
@ -826,7 +842,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if (fepriv->thread) {
|
||||
if (fepriv->exit == DVB_FE_NO_EXIT)
|
||||
if (fe->exit == DVB_FE_NO_EXIT)
|
||||
return 0;
|
||||
else
|
||||
dvb_frontend_stop (fe);
|
||||
@ -838,7 +854,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
||||
return -EINTR;
|
||||
|
||||
fepriv->state = FESTATE_IDLE;
|
||||
fepriv->exit = DVB_FE_NO_EXIT;
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
fepriv->thread = NULL;
|
||||
mb();
|
||||
|
||||
@ -967,6 +983,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
|
||||
case SYS_ATSC:
|
||||
c->modulation = VSB_8;
|
||||
break;
|
||||
case SYS_ISDBS:
|
||||
c->symbol_rate = 28860000;
|
||||
c->rolloff = ROLLOFF_35;
|
||||
c->bandwidth_hz = c->symbol_rate / 100 * 135;
|
||||
break;
|
||||
default:
|
||||
c->modulation = QAM_AUTO;
|
||||
break;
|
||||
@ -985,6 +1006,17 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
|
||||
.buffer = b \
|
||||
}
|
||||
|
||||
struct dtv_cmds_h {
|
||||
char *name; /* A display name for debugging purposes */
|
||||
|
||||
__u32 cmd; /* A unique ID */
|
||||
|
||||
/* Flags */
|
||||
__u32 set:1; /* Either a set or get property */
|
||||
__u32 buffer:1; /* Does this property use the buffer? */
|
||||
__u32 reserved:30; /* Align */
|
||||
};
|
||||
|
||||
static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
|
||||
_DTV_CMD(DTV_TUNE, 1, 0),
|
||||
_DTV_CMD(DTV_CLEAR, 1, 0),
|
||||
@ -1068,18 +1100,24 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
|
||||
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
|
||||
};
|
||||
|
||||
static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
|
||||
static void dtv_property_dump(struct dvb_frontend *fe,
|
||||
bool is_set,
|
||||
struct dtv_property *tvp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
|
||||
dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n",
|
||||
__func__, tvp->cmd);
|
||||
dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n",
|
||||
__func__,
|
||||
is_set ? "SET" : "GET",
|
||||
tvp->cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__,
|
||||
tvp->cmd, dtv_cmds[tvp->cmd].name);
|
||||
dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__,
|
||||
is_set ? "SET" : "GET",
|
||||
tvp->cmd,
|
||||
dtv_cmds[tvp->cmd].name);
|
||||
|
||||
if (dtv_cmds[tvp->cmd].buffer) {
|
||||
dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n",
|
||||
@ -1174,11 +1212,11 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
|
||||
/* Ensure the cached values are set correctly in the frontend
|
||||
* legacy tuning structures, for the advanced tuning API.
|
||||
*/
|
||||
static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
|
||||
static int
|
||||
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
|
||||
const struct dtv_frontend_properties *c,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
|
||||
p->frequency = c->frequency;
|
||||
p->inversion = c->inversion;
|
||||
|
||||
@ -1250,16 +1288,17 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
|
||||
* If p_out is not null, it will update the DVBv3 params pointed by it.
|
||||
*/
|
||||
static int dtv_get_frontend(struct dvb_frontend *fe,
|
||||
struct dtv_frontend_properties *c,
|
||||
struct dvb_frontend_parameters *p_out)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (fe->ops.get_frontend) {
|
||||
r = fe->ops.get_frontend(fe);
|
||||
r = fe->ops.get_frontend(fe, c);
|
||||
if (unlikely(r < 0))
|
||||
return r;
|
||||
if (p_out)
|
||||
dtv_property_legacy_params_sync(fe, p_out);
|
||||
dtv_property_legacy_params_sync(fe, c, p_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1282,7 +1321,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
||||
switch(tvp->cmd) {
|
||||
case DTV_ENUM_DELSYS:
|
||||
ncaps = 0;
|
||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
|
||||
tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
|
||||
ncaps++;
|
||||
}
|
||||
@ -1507,7 +1546,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
||||
return r;
|
||||
}
|
||||
|
||||
dtv_property_dump(fe, tvp);
|
||||
dtv_property_dump(fe, false, tvp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1516,12 +1555,8 @@ static int dtv_set_frontend(struct dvb_frontend *fe);
|
||||
|
||||
static bool is_dvbv3_delsys(u32 delsys)
|
||||
{
|
||||
bool status;
|
||||
|
||||
status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
|
||||
return (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
|
||||
(delsys == SYS_DVBS) || (delsys == SYS_ATSC);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1611,7 +1646,7 @@ static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
|
||||
* supported
|
||||
*/
|
||||
ncaps = 0;
|
||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
|
||||
if (fe->ops.delsys[ncaps] == desired_system) {
|
||||
c->delivery_system = desired_system;
|
||||
dev_dbg(fe->dvb->device,
|
||||
@ -1643,7 +1678,7 @@ static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
|
||||
* of the desired system
|
||||
*/
|
||||
ncaps = 0;
|
||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
|
||||
if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
|
||||
delsys = fe->ops.delsys[ncaps];
|
||||
ncaps++;
|
||||
@ -1718,7 +1753,7 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
|
||||
* DVBv3 standard
|
||||
*/
|
||||
ncaps = 0;
|
||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
|
||||
if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
|
||||
delsys = fe->ops.delsys[ncaps];
|
||||
break;
|
||||
@ -1748,6 +1783,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
||||
return r;
|
||||
}
|
||||
|
||||
dtv_property_dump(fe, true, tvp);
|
||||
|
||||
switch(tvp->cmd) {
|
||||
case DTV_CLEAR:
|
||||
/*
|
||||
@ -1931,7 +1968,7 @@ static int dvb_frontend_ioctl(struct file *file,
|
||||
if (down_interruptible(&fepriv->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT) {
|
||||
if (fe->exit != DVB_FE_NO_EXIT) {
|
||||
up(&fepriv->sem);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1963,15 +2000,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int err = 0;
|
||||
|
||||
struct dtv_properties *tvps = NULL;
|
||||
struct dtv_properties *tvps = parg;
|
||||
struct dtv_property *tvp = NULL;
|
||||
int i;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if (cmd == FE_SET_PROPERTY) {
|
||||
tvps = (struct dtv_properties __user *)parg;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
|
||||
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
|
||||
|
||||
@ -1980,16 +2015,9 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
|
||||
if (!tvp) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
for (i = 0; i < tvps->num; i++) {
|
||||
err = dtv_property_process_set(fe, tvp + i, file);
|
||||
@ -2001,9 +2029,8 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
if (c->state == DTV_TUNE)
|
||||
dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
|
||||
|
||||
} else
|
||||
if(cmd == FE_GET_PROPERTY) {
|
||||
tvps = (struct dtv_properties __user *)parg;
|
||||
} else if (cmd == FE_GET_PROPERTY) {
|
||||
struct dtv_frontend_properties getp = fe->dtv_property_cache;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
|
||||
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
|
||||
@ -2013,35 +2040,30 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
||||
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
|
||||
if (!tvp) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
/*
|
||||
* Fills the cache out struct with the cache contents, plus
|
||||
* the data retrieved from get_frontend, if the frontend
|
||||
* is not idle. Otherwise, returns the cached content
|
||||
* Let's use our own copy of property cache, in order to
|
||||
* avoid mangling with DTV zigzag logic, as drivers might
|
||||
* return crap, if they don't check if the data is available
|
||||
* before updating the properties cache.
|
||||
*/
|
||||
if (fepriv->state != FESTATE_IDLE) {
|
||||
err = dtv_get_frontend(fe, NULL);
|
||||
err = dtv_get_frontend(fe, &getp, NULL);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < tvps->num; i++) {
|
||||
err = dtv_property_process_get(fe, c, tvp + i, file);
|
||||
err = dtv_property_process_get(fe, &getp, tvp + i, file);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
(tvp + i)->result = err;
|
||||
}
|
||||
|
||||
if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
|
||||
if (copy_to_user((void __user *)tvps->props, tvp,
|
||||
tvps->num * sizeof(struct dtv_property))) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@ -2069,7 +2091,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
|
||||
* the user. FE_SET_FRONTEND triggers an initial frontend event
|
||||
* with status = 0, which copies output parameters to userspace.
|
||||
*/
|
||||
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
|
||||
dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out);
|
||||
|
||||
/*
|
||||
* Be sure that the bandwidth will be filled for all
|
||||
@ -2101,11 +2123,29 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
|
||||
case SYS_DVBC_ANNEX_C:
|
||||
rolloff = 113;
|
||||
break;
|
||||
case SYS_DVBS:
|
||||
case SYS_TURBO:
|
||||
case SYS_ISDBS:
|
||||
rolloff = 135;
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
switch (c->rolloff) {
|
||||
case ROLLOFF_20:
|
||||
rolloff = 120;
|
||||
break;
|
||||
case ROLLOFF_25:
|
||||
rolloff = 125;
|
||||
break;
|
||||
default:
|
||||
case ROLLOFF_35:
|
||||
rolloff = 135;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (rolloff)
|
||||
c->bandwidth_hz = (c->symbol_rate * rolloff) / 100;
|
||||
c->bandwidth_hz = mult_frac(c->symbol_rate, rolloff, 100);
|
||||
|
||||
/* force auto frequency inversion if requested */
|
||||
if (dvb_force_auto_inversion)
|
||||
@ -2222,15 +2262,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
|
||||
__func__, c->delivery_system, fe->ops.info.type);
|
||||
|
||||
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
|
||||
* do it, it is done for it. */
|
||||
/* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */
|
||||
if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT))
|
||||
info->caps |= FE_CAN_INVERSION_AUTO;
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case FE_READ_STATUS: {
|
||||
fe_status_t* status = parg;
|
||||
enum fe_status *status = parg;
|
||||
|
||||
/* if retune was requested but hasn't occurred yet, prevent
|
||||
* that user get signal state from previous tuning */
|
||||
@ -2292,7 +2332,13 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
case FE_DISEQC_SEND_MASTER_CMD:
|
||||
if (fe->ops.diseqc_send_master_cmd) {
|
||||
err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
|
||||
struct dvb_diseqc_master_cmd *cmd = parg;
|
||||
|
||||
if (cmd->msg_len > sizeof(cmd->msg)) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
err = fe->ops.diseqc_send_master_cmd(fe, cmd);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -2300,7 +2346,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
case FE_DISEQC_SEND_BURST:
|
||||
if (fe->ops.diseqc_send_burst) {
|
||||
err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
|
||||
err = fe->ops.diseqc_send_burst(fe,
|
||||
(enum fe_sec_mini_cmd)parg);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -2308,8 +2355,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
case FE_SET_TONE:
|
||||
if (fe->ops.set_tone) {
|
||||
err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
|
||||
fepriv->tone = (fe_sec_tone_mode_t) parg;
|
||||
err = fe->ops.set_tone(fe,
|
||||
(enum fe_sec_tone_mode)parg);
|
||||
fepriv->tone = (enum fe_sec_tone_mode)parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -2317,8 +2365,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
case FE_SET_VOLTAGE:
|
||||
if (fe->ops.set_voltage) {
|
||||
err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
|
||||
fepriv->voltage = (fe_sec_voltage_t) parg;
|
||||
err = fe->ops.set_voltage(fe,
|
||||
(enum fe_sec_voltage)parg);
|
||||
fepriv->voltage = (enum fe_sec_voltage)parg;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
}
|
||||
@ -2326,7 +2375,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
case FE_DISHNETWORK_SEND_LEGACY_CMD:
|
||||
if (fe->ops.dishnetwork_send_legacy_command) {
|
||||
err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
|
||||
err = fe->ops.dishnetwork_send_legacy_command(fe,
|
||||
(unsigned long)parg);
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
fepriv->status = 0;
|
||||
} else if (fe->ops.set_voltage) {
|
||||
@ -2347,13 +2397,14 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
* include the initialization or start bit
|
||||
*/
|
||||
unsigned long swcmd = ((unsigned long) parg) << 1;
|
||||
struct timeval nexttime;
|
||||
struct timeval tv[10];
|
||||
ktime_t nexttime;
|
||||
ktime_t tv[10];
|
||||
int i;
|
||||
u8 last = 1;
|
||||
if (dvb_frontend_debug)
|
||||
printk("%s switch command: 0x%04lx\n", __func__, swcmd);
|
||||
do_gettimeofday(&nexttime);
|
||||
dprintk("%s switch command: 0x%04lx\n",
|
||||
__func__, swcmd);
|
||||
nexttime = ktime_get_boottime();
|
||||
if (dvb_frontend_debug)
|
||||
tv[0] = nexttime;
|
||||
/* before sending a command, initialize by sending
|
||||
@ -2364,7 +2415,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (dvb_frontend_debug)
|
||||
do_gettimeofday(&tv[i + 1]);
|
||||
tv[i+1] = ktime_get_boottime();
|
||||
if ((swcmd & 0x01) != last) {
|
||||
/* set voltage to (last ? 13V : 18V) */
|
||||
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
|
||||
@ -2375,10 +2426,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
dvb_frontend_sleep_until(&nexttime, 8000);
|
||||
}
|
||||
if (dvb_frontend_debug) {
|
||||
printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
|
||||
dprintk("%s(%d): switch delay (should be 32k followed by all 8k)\n",
|
||||
__func__, fe->dvb->num);
|
||||
for (i = 1; i < 10; i++)
|
||||
printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
|
||||
pr_info("%d: %d\n", i,
|
||||
(int) ktime_us_delta(tv[i], tv[i-1]));
|
||||
}
|
||||
err = 0;
|
||||
fepriv->state = FESTATE_DISEQC;
|
||||
@ -2410,10 +2462,18 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
err = dvb_frontend_get_event (fe, parg, file->f_flags);
|
||||
break;
|
||||
|
||||
case FE_GET_FRONTEND:
|
||||
err = dtv_get_frontend(fe, parg);
|
||||
break;
|
||||
case FE_GET_FRONTEND: {
|
||||
struct dtv_frontend_properties getp = fe->dtv_property_cache;
|
||||
|
||||
/*
|
||||
* Let's use our own copy of property cache, in order to
|
||||
* avoid mangling with DTV zigzag logic, as drivers might
|
||||
* return crap, if they don't check if the data is available
|
||||
* before updating the properties cache.
|
||||
*/
|
||||
err = dtv_get_frontend(fe, &getp, parg);
|
||||
break;
|
||||
}
|
||||
case FE_SET_FRONTEND_TUNE_MODE:
|
||||
fepriv->tune_mode_flags = (unsigned long) parg;
|
||||
err = 0;
|
||||
@ -2430,7 +2490,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
|
||||
struct dvb_frontend *fe = dvbdev->priv;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
|
||||
//dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__);
|
||||
dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
poll_wait (file, &fepriv->events.wait_queue, wait);
|
||||
|
||||
@ -2449,7 +2509,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
int ret;
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
|
||||
if (fe->exit == DVB_FE_DEVICE_REMOVED)
|
||||
return -ENODEV;
|
||||
|
||||
if (adapter->mfe_shared) {
|
||||
@ -2513,19 +2573,45 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
fepriv->tone = -1;
|
||||
fepriv->voltage = -1;
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
if (fe->dvb->mdev) {
|
||||
mutex_lock(&fe->dvb->mdev->graph_mutex);
|
||||
if (fe->dvb->mdev->enable_source)
|
||||
ret = fe->dvb->mdev->enable_source(
|
||||
dvbdev->entity,
|
||||
&fepriv->pipe);
|
||||
mutex_unlock(&fe->dvb->mdev->graph_mutex);
|
||||
if (ret) {
|
||||
dev_err(fe->dvb->device,
|
||||
"Tuner is busy. Error %d\n", ret);
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ret = dvb_frontend_start (fe);
|
||||
if (ret)
|
||||
goto err2;
|
||||
goto err3;
|
||||
|
||||
/* empty event queue */
|
||||
fepriv->events.eventr = fepriv->events.eventw = 0;
|
||||
}
|
||||
|
||||
dvb_frontend_get(fe);
|
||||
|
||||
if (adapter->mfe_shared)
|
||||
mutex_unlock (&adapter->mfe_lock);
|
||||
return ret;
|
||||
|
||||
err3:
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
if (fe->dvb->mdev) {
|
||||
mutex_lock(&fe->dvb->mdev->graph_mutex);
|
||||
if (fe->dvb->mdev->disable_source)
|
||||
fe->dvb->mdev->disable_source(dvbdev->entity);
|
||||
mutex_unlock(&fe->dvb->mdev->graph_mutex);
|
||||
}
|
||||
err2:
|
||||
#endif
|
||||
dvb_generic_release(inode, file);
|
||||
err1:
|
||||
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
|
||||
@ -2554,12 +2640,22 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
||||
|
||||
if (dvbdev->users == -1) {
|
||||
wake_up(&fepriv->wait_queue);
|
||||
if (fepriv->exit != DVB_FE_NO_EXIT)
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
if (fe->dvb->mdev) {
|
||||
mutex_lock(&fe->dvb->mdev->graph_mutex);
|
||||
if (fe->dvb->mdev->disable_source)
|
||||
fe->dvb->mdev->disable_source(dvbdev->entity);
|
||||
mutex_unlock(&fe->dvb->mdev->graph_mutex);
|
||||
}
|
||||
#endif
|
||||
if (fe->exit != DVB_FE_NO_EXIT)
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
if (fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
dvb_frontend_put(fe);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2579,7 +2675,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
|
||||
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
|
||||
fe->id);
|
||||
|
||||
if (fe->ops.tuner_ops.sleep)
|
||||
if (fe->ops.tuner_ops.suspend)
|
||||
ret = fe->ops.tuner_ops.suspend(fe);
|
||||
else if (fe->ops.tuner_ops.sleep)
|
||||
ret = fe->ops.tuner_ops.sleep(fe);
|
||||
|
||||
if (fe->ops.sleep)
|
||||
@ -2597,12 +2695,21 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
|
||||
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
|
||||
fe->id);
|
||||
|
||||
fe->exit = DVB_FE_DEVICE_RESUME;
|
||||
if (fe->ops.init)
|
||||
ret = fe->ops.init(fe);
|
||||
|
||||
if (fe->ops.tuner_ops.init)
|
||||
if (fe->ops.tuner_ops.resume)
|
||||
ret = fe->ops.tuner_ops.resume(fe);
|
||||
else if (fe->ops.tuner_ops.init)
|
||||
ret = fe->ops.tuner_ops.init(fe);
|
||||
|
||||
if (fe->ops.set_tone && fepriv->tone != -1)
|
||||
fe->ops.set_tone(fe, fepriv->tone);
|
||||
if (fe->ops.set_voltage && fepriv->voltage != -1)
|
||||
fe->ops.set_voltage(fe, fepriv->voltage);
|
||||
|
||||
fe->exit = DVB_FE_NO_EXIT;
|
||||
fepriv->state = FESTATE_RETUNE;
|
||||
dvb_frontend_wakeup(fe);
|
||||
|
||||
@ -2614,11 +2721,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
||||
struct dvb_frontend* fe)
|
||||
{
|
||||
struct dvb_frontend_private *fepriv;
|
||||
static const struct dvb_device dvbdev_template = {
|
||||
const struct dvb_device dvbdev_template = {
|
||||
.users = ~0,
|
||||
.writers = 1,
|
||||
.readers = (~0)-1,
|
||||
.fops = &dvb_frontend_fops,
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
.name = fe->ops.info.name,
|
||||
#endif
|
||||
.kernel_ioctl = dvb_frontend_ioctl
|
||||
};
|
||||
|
||||
@ -2634,6 +2744,15 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
||||
}
|
||||
fepriv = fe->frontend_priv;
|
||||
|
||||
kref_init(&fe->refcount);
|
||||
|
||||
/*
|
||||
* After initialization, there need to be two references: one
|
||||
* for dvb_unregister_frontend(), and another one for
|
||||
* dvb_frontend_detach().
|
||||
*/
|
||||
dvb_frontend_get(fe);
|
||||
|
||||
sema_init(&fepriv->sem, 1);
|
||||
init_waitqueue_head (&fepriv->wait_queue);
|
||||
init_waitqueue_head (&fepriv->events.wait_queue);
|
||||
@ -2642,7 +2761,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
||||
fepriv->inversion = INVERSION_OFF;
|
||||
|
||||
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
|
||||
fe, DVB_DEVICE_FRONTEND);
|
||||
fe, DVB_DEVICE_FRONTEND, 0);
|
||||
|
||||
dev_info(fe->dvb->device,
|
||||
"DVB: registering adapter %i frontend %i (%s)...\n",
|
||||
@ -2668,56 +2787,32 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
|
||||
|
||||
mutex_lock(&frontend_mutex);
|
||||
dvb_frontend_stop(fe);
|
||||
mutex_unlock(&frontend_mutex);
|
||||
|
||||
if (fepriv->dvbdev->users < -1)
|
||||
wait_event(fepriv->dvbdev->wait_queue,
|
||||
fepriv->dvbdev->users==-1);
|
||||
|
||||
mutex_lock(&frontend_mutex);
|
||||
dvb_unregister_device (fepriv->dvbdev);
|
||||
dvb_remove_device(fepriv->dvbdev);
|
||||
|
||||
/* fe is invalid now */
|
||||
kfree(fepriv);
|
||||
mutex_unlock(&frontend_mutex);
|
||||
dvb_frontend_put(fe);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_frontend);
|
||||
|
||||
static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
|
||||
void (*release)(struct dvb_frontend *fe))
|
||||
{
|
||||
if (release) {
|
||||
release(fe);
|
||||
#ifdef CONFIG_MEDIA_ATTACH
|
||||
void dvb_frontend_detach(struct dvb_frontend* fe)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (fe->ops.release_sec) {
|
||||
fe->ops.release_sec(fe);
|
||||
symbol_put_addr(fe->ops.release_sec);
|
||||
}
|
||||
if (fe->ops.tuner_ops.release) {
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
symbol_put_addr(fe->ops.tuner_ops.release);
|
||||
}
|
||||
if (fe->ops.analog_ops.release) {
|
||||
fe->ops.analog_ops.release(fe);
|
||||
symbol_put_addr(fe->ops.analog_ops.release);
|
||||
}
|
||||
ptr = (void*)fe->ops.release;
|
||||
if (ptr) {
|
||||
fe->ops.release(fe);
|
||||
symbol_put_addr(ptr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void dvb_frontend_detach(struct dvb_frontend* fe)
|
||||
{
|
||||
if (fe->ops.release_sec)
|
||||
fe->ops.release_sec(fe);
|
||||
if (fe->ops.tuner_ops.release)
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
if (fe->ops.analog_ops.release)
|
||||
fe->ops.analog_ops.release(fe);
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
}
|
||||
dvb_detach(release);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void dvb_frontend_detach(struct dvb_frontend* fe)
|
||||
{
|
||||
dvb_frontend_invoke_release(fe, fe->ops.release_sec);
|
||||
dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
|
||||
dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
|
||||
dvb_frontend_invoke_release(fe, fe->ops.detach);
|
||||
dvb_frontend_put(fe);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_frontend_detach);
|
||||
|
@ -1,6 +1,10 @@
|
||||
/*
|
||||
* dvb_frontend.h
|
||||
*
|
||||
* The Digital TV Frontend kABI defines a driver-internal interface for
|
||||
* registering low-level, hardware specific driver to a hardware independent
|
||||
* frontend layer.
|
||||
*
|
||||
* Copyright (C) 2001 convergence integrated media GmbH
|
||||
* Copyright (C) 2004 convergence GmbH
|
||||
*
|
||||
@ -53,6 +57,15 @@
|
||||
*/
|
||||
#define MAX_DELSYS 8
|
||||
|
||||
/**
|
||||
* struct dvb_frontend_tune_settings - parameters to adjust frontend tuning
|
||||
*
|
||||
* @min_delay_ms: minimum delay for tuning, in ms
|
||||
* @step_size: step size between two consecutive frequencies
|
||||
* @max_drift: maximum drift
|
||||
*
|
||||
* NOTE: step_size is in Hz, for terrestrial/cable or kHz for satellite
|
||||
*/
|
||||
struct dvb_frontend_tune_settings {
|
||||
int min_delay_ms;
|
||||
int step_size;
|
||||
@ -61,6 +74,20 @@ struct dvb_frontend_tune_settings {
|
||||
|
||||
struct dvb_frontend;
|
||||
|
||||
/**
|
||||
* struct dvb_tuner_info - Frontend name and min/max ranges/bandwidths
|
||||
*
|
||||
* @name: name of the Frontend
|
||||
* @frequency_min: minimal frequency supported
|
||||
* @frequency_max: maximum frequency supported
|
||||
* @frequency_step: frequency step
|
||||
* @bandwidth_min: minimal frontend bandwidth supported
|
||||
* @bandwidth_max: maximum frontend bandwidth supported
|
||||
* @bandwidth_step: frontend bandwidth step
|
||||
*
|
||||
* NOTE: frequency parameters are in Hz, for terrestrial/cable or kHz for
|
||||
* satellite.
|
||||
*/
|
||||
struct dvb_tuner_info {
|
||||
char name[128];
|
||||
|
||||
@ -73,6 +100,20 @@ struct dvb_tuner_info {
|
||||
u32 bandwidth_step;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct analog_parameters - Parameters to tune into an analog/radio channel
|
||||
*
|
||||
* @frequency: Frequency used by analog TV tuner (either in 62.5 kHz step,
|
||||
* for TV, or 62.5 Hz for radio)
|
||||
* @mode: Tuner mode, as defined on enum v4l2_tuner_type
|
||||
* @audmode: Audio mode as defined for the rxsubchans field at videodev2.h,
|
||||
* e. g. V4L2_TUNER_MODE_*
|
||||
* @std: TV standard bitmap as defined at videodev2.h, e. g. V4L2_STD_*
|
||||
*
|
||||
* Hybrid tuners should be supported by both V4L2 and DVB APIs. This
|
||||
* struct contains the data that are used by the V4L2 side. To avoid
|
||||
* dependencies from V4L2 headers, all enums here are declared as integers.
|
||||
*/
|
||||
struct analog_parameters {
|
||||
unsigned int frequency;
|
||||
unsigned int mode;
|
||||
@ -80,66 +121,19 @@ struct analog_parameters {
|
||||
u64 std;
|
||||
};
|
||||
|
||||
enum dvbfe_modcod {
|
||||
DVBFE_MODCOD_DUMMY_PLFRAME = 0,
|
||||
DVBFE_MODCOD_QPSK_1_4,
|
||||
DVBFE_MODCOD_QPSK_1_3,
|
||||
DVBFE_MODCOD_QPSK_2_5,
|
||||
DVBFE_MODCOD_QPSK_1_2,
|
||||
DVBFE_MODCOD_QPSK_3_5,
|
||||
DVBFE_MODCOD_QPSK_2_3,
|
||||
DVBFE_MODCOD_QPSK_3_4,
|
||||
DVBFE_MODCOD_QPSK_4_5,
|
||||
DVBFE_MODCOD_QPSK_5_6,
|
||||
DVBFE_MODCOD_QPSK_8_9,
|
||||
DVBFE_MODCOD_QPSK_9_10,
|
||||
DVBFE_MODCOD_8PSK_3_5,
|
||||
DVBFE_MODCOD_8PSK_2_3,
|
||||
DVBFE_MODCOD_8PSK_3_4,
|
||||
DVBFE_MODCOD_8PSK_5_6,
|
||||
DVBFE_MODCOD_8PSK_8_9,
|
||||
DVBFE_MODCOD_8PSK_9_10,
|
||||
DVBFE_MODCOD_16APSK_2_3,
|
||||
DVBFE_MODCOD_16APSK_3_4,
|
||||
DVBFE_MODCOD_16APSK_4_5,
|
||||
DVBFE_MODCOD_16APSK_5_6,
|
||||
DVBFE_MODCOD_16APSK_8_9,
|
||||
DVBFE_MODCOD_16APSK_9_10,
|
||||
DVBFE_MODCOD_32APSK_3_4,
|
||||
DVBFE_MODCOD_32APSK_4_5,
|
||||
DVBFE_MODCOD_32APSK_5_6,
|
||||
DVBFE_MODCOD_32APSK_8_9,
|
||||
DVBFE_MODCOD_32APSK_9_10,
|
||||
DVBFE_MODCOD_RESERVED_1,
|
||||
DVBFE_MODCOD_BPSK_1_3,
|
||||
DVBFE_MODCOD_BPSK_1_4,
|
||||
DVBFE_MODCOD_RESERVED_2
|
||||
};
|
||||
|
||||
enum tuner_param {
|
||||
DVBFE_TUNER_FREQUENCY = (1 << 0),
|
||||
DVBFE_TUNER_TUNERSTEP = (1 << 1),
|
||||
DVBFE_TUNER_IFFREQ = (1 << 2),
|
||||
DVBFE_TUNER_BANDWIDTH = (1 << 3),
|
||||
DVBFE_TUNER_REFCLOCK = (1 << 4),
|
||||
DVBFE_TUNER_IQSENSE = (1 << 5),
|
||||
DVBFE_TUNER_DUMMY = (1 << 31)
|
||||
};
|
||||
|
||||
/*
|
||||
* ALGO_HW: (Hardware Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
/**
|
||||
* enum dvbfe_algo - defines the algorithm used to tune into a channel
|
||||
*
|
||||
* @DVBFE_ALGO_HW: Hardware Algorithm -
|
||||
* Devices that support this algorithm do everything in hardware
|
||||
* and no software support is needed to handle them.
|
||||
* Requesting these devices to LOCK is the only thing required,
|
||||
* device is supposed to do everything in the hardware.
|
||||
*
|
||||
* ALGO_SW: (Software Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* @DVBFE_ALGO_SW: Software Algorithm -
|
||||
* These are dumb devices, that require software to do everything
|
||||
*
|
||||
* ALGO_CUSTOM: (Customizable Agorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* @DVBFE_ALGO_CUSTOM: Customizable Agorithm -
|
||||
* Devices having this algorithm can be customized to have specific
|
||||
* algorithms in the frontend driver, rather than simply doing a
|
||||
* software zig-zag. In this case the zigzag maybe hardware assisted
|
||||
@ -147,8 +141,7 @@ enum tuner_param {
|
||||
* this algorithm, in conjunction with the search and track
|
||||
* callbacks, utilizes the driver specific algorithm.
|
||||
*
|
||||
* ALGO_RECOVERY: (Recovery Algorithm)
|
||||
* ----------------------------------------------------------------
|
||||
* @DVBFE_ALGO_RECOVERY: Recovery Algorithm -
|
||||
* These devices have AUTO recovery capabilities from LOCK failure
|
||||
*/
|
||||
enum dvbfe_algo {
|
||||
@ -158,35 +151,26 @@ enum dvbfe_algo {
|
||||
DVBFE_ALGO_RECOVERY = (1 << 31)
|
||||
};
|
||||
|
||||
struct tuner_state {
|
||||
u32 frequency;
|
||||
u32 tunerstep;
|
||||
u32 ifreq;
|
||||
u32 bandwidth;
|
||||
u32 iqsense;
|
||||
u32 refclock;
|
||||
};
|
||||
|
||||
/*
|
||||
* search callback possible return status
|
||||
/**
|
||||
* enum dvbfe_search - search callback possible return status
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_SUCCESS
|
||||
* @DVBFE_ALGO_SEARCH_SUCCESS:
|
||||
* The frontend search algorithm completed and returned successfully
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_ASLEEP
|
||||
* @DVBFE_ALGO_SEARCH_ASLEEP:
|
||||
* The frontend search algorithm is sleeping
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_FAILED
|
||||
* @DVBFE_ALGO_SEARCH_FAILED:
|
||||
* The frontend search for a signal failed
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_INVALID
|
||||
* @DVBFE_ALGO_SEARCH_INVALID:
|
||||
* The frontend search algorith was probably supplied with invalid
|
||||
* parameters and the search is an invalid one
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_ERROR
|
||||
* @DVBFE_ALGO_SEARCH_ERROR:
|
||||
* The frontend search algorithm failed due to some error
|
||||
*
|
||||
* DVBFE_ALGO_SEARCH_AGAIN
|
||||
* @DVBFE_ALGO_SEARCH_AGAIN:
|
||||
* The frontend search algorithm was requested to search again
|
||||
*/
|
||||
enum dvbfe_search {
|
||||
@ -198,23 +182,64 @@ enum dvbfe_search {
|
||||
DVBFE_ALGO_SEARCH_ERROR = (1 << 31),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct dvb_tuner_ops - Tuner information and callbacks
|
||||
*
|
||||
* @info: embedded struct dvb_tuner_info with tuner properties
|
||||
* @release: callback function called when frontend is dettached.
|
||||
* drivers should free any allocated memory.
|
||||
* @init: callback function used to initialize the tuner device.
|
||||
* @sleep: callback function used to put the tuner to sleep.
|
||||
* @suspend: callback function used to inform that the Kernel will
|
||||
* suspend.
|
||||
* @resume: callback function used to inform that the Kernel is
|
||||
* resuming from suspend.
|
||||
* @set_params: callback function used to inform the tuner to tune
|
||||
* into a digital TV channel. The properties to be used
|
||||
* are stored at @dvb_frontend.dtv_property_cache;. The
|
||||
* tuner demod can change the parameters to reflect the
|
||||
* changes needed for the channel to be tuned, and
|
||||
* update statistics. This is the recommended way to set
|
||||
* the tuner parameters and should be used on newer
|
||||
* drivers.
|
||||
* @set_analog_params: callback function used to tune into an analog TV
|
||||
* channel on hybrid tuners. It passes @analog_parameters;
|
||||
* to the driver.
|
||||
* @set_config: callback function used to send some tuner-specific
|
||||
* parameters.
|
||||
* @get_frequency: get the actual tuned frequency
|
||||
* @get_bandwidth: get the bandwitdh used by the low pass filters
|
||||
* @get_if_frequency: get the Intermediate Frequency, in Hz. For baseband,
|
||||
* should return 0.
|
||||
* @get_status: returns the frontend lock status
|
||||
* @get_rf_strength: returns the RF signal strengh. Used mostly to support
|
||||
* analog TV and radio. Digital TV should report, instead,
|
||||
* via DVBv5 API (@dvb_frontend.dtv_property_cache;).
|
||||
* @get_afc: Used only by analog TV core. Reports the frequency
|
||||
* drift due to AFC.
|
||||
* @calc_regs: callback function used to pass register data settings
|
||||
* for simple tuners. Shouldn't be used on newer drivers.
|
||||
* @set_frequency: Set a new frequency. Shouldn't be used on newer drivers.
|
||||
* @set_bandwidth: Set a new frequency. Shouldn't be used on newer drivers.
|
||||
*
|
||||
* NOTE: frequencies used on get_frequency and set_frequency are in Hz for
|
||||
* terrestrial/cable or kHz for satellite.
|
||||
*
|
||||
*/
|
||||
struct dvb_tuner_ops {
|
||||
|
||||
struct dvb_tuner_info info;
|
||||
|
||||
int (*release)(struct dvb_frontend *fe);
|
||||
void (*release)(struct dvb_frontend *fe);
|
||||
int (*init)(struct dvb_frontend *fe);
|
||||
int (*sleep)(struct dvb_frontend *fe);
|
||||
int (*suspend)(struct dvb_frontend *fe);
|
||||
int (*resume)(struct dvb_frontend *fe);
|
||||
|
||||
/** This is for simple PLLs - set all parameters in one go. */
|
||||
/* This is the recomended way to set the tuner */
|
||||
int (*set_params)(struct dvb_frontend *fe);
|
||||
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
|
||||
|
||||
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
|
||||
int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
|
||||
|
||||
/** This is to allow setting tuner-specific configs */
|
||||
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
|
||||
|
||||
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
|
||||
@ -227,23 +252,56 @@ struct dvb_tuner_ops {
|
||||
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
|
||||
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
|
||||
|
||||
/** These are provided separately from set_params in order to facilitate silicon
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
|
||||
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
|
||||
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
|
||||
/*
|
||||
* This is support for demods like the mt352 - fills out the supplied
|
||||
* buffer with what to write.
|
||||
*
|
||||
* Don't use on newer drivers.
|
||||
*/
|
||||
int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
|
||||
|
||||
/*
|
||||
* These are provided separately from set_params in order to facilitate silicon
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter separately.
|
||||
* These are provided separately from set_params in order to
|
||||
* facilitate silicon tuners which require sophisticated tuning loops,
|
||||
* controlling each parameter separately.
|
||||
*
|
||||
* Don't use on newer drivers.
|
||||
*/
|
||||
int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
|
||||
int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
|
||||
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
|
||||
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct analog_demod_info - Information struct for analog TV part of the demod
|
||||
*
|
||||
* @name: Name of the analog TV demodulator
|
||||
*/
|
||||
struct analog_demod_info {
|
||||
char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct analog_demod_ops - Demodulation information and callbacks for
|
||||
* analog TV and radio
|
||||
*
|
||||
* @info: pointer to struct analog_demod_info
|
||||
* @set_params: callback function used to inform the demod to set the
|
||||
* demodulator parameters needed to decode an analog or
|
||||
* radio channel. The properties are passed via
|
||||
* struct @analog_params;.
|
||||
* @has_signal: returns 0xffff if has signal, or 0 if it doesn't.
|
||||
* @get_afc: Used only by analog TV core. Reports the frequency
|
||||
* drift due to AFC.
|
||||
* @tuner_status: callback function that returns tuner status bits, e. g.
|
||||
* TUNER_STATUS_LOCKED and TUNER_STATUS_STEREO.
|
||||
* @standby: set the tuner to standby mode.
|
||||
* @release: callback function called when frontend is dettached.
|
||||
* drivers should free any allocated memory.
|
||||
* @i2c_gate_ctrl: controls the I2C gate. Newer drivers should use I2C
|
||||
* mux support instead.
|
||||
* @set_config: callback function used to send some tuner-specific
|
||||
* parameters.
|
||||
*/
|
||||
struct analog_demod_ops {
|
||||
|
||||
struct analog_demod_info info;
|
||||
@ -263,12 +321,103 @@ struct analog_demod_ops {
|
||||
|
||||
struct dtv_frontend_properties;
|
||||
|
||||
|
||||
/**
|
||||
* struct dvb_frontend_ops - Demodulation information and callbacks for
|
||||
* ditialt TV
|
||||
*
|
||||
* @info: embedded struct dvb_tuner_info with tuner properties
|
||||
* @delsys: Delivery systems supported by the frontend
|
||||
* @detach: callback function called when frontend is detached.
|
||||
* drivers should clean up, but not yet free the struct
|
||||
* dvb_frontend allocation.
|
||||
* @release: callback function called when frontend is ready to be
|
||||
* freed.
|
||||
* drivers should free any allocated memory.
|
||||
* @release_sec: callback function requesting that the Satelite Equipment
|
||||
* Control (SEC) driver to release and free any memory
|
||||
* allocated by the driver.
|
||||
* @init: callback function used to initialize the tuner device.
|
||||
* @sleep: callback function used to put the tuner to sleep.
|
||||
* @write: callback function used by some demod legacy drivers to
|
||||
* allow other drivers to write data into their registers.
|
||||
* Should not be used on new drivers.
|
||||
* @tune: callback function used by demod drivers that use
|
||||
* @DVBFE_ALGO_HW; to tune into a frequency.
|
||||
* @get_frontend_algo: returns the desired hardware algorithm.
|
||||
* @set_frontend: callback function used to inform the demod to set the
|
||||
* parameters for demodulating a digital TV channel.
|
||||
* The properties to be used are stored at
|
||||
* @dvb_frontend.dtv_property_cache;. The demod can change
|
||||
* the parameters to reflect the changes needed for the
|
||||
* channel to be decoded, and update statistics.
|
||||
* @get_tune_settings: callback function
|
||||
* @get_frontend: callback function used to inform the parameters
|
||||
* actuall in use. The properties to be used are stored at
|
||||
* @dvb_frontend.dtv_property_cache; and update
|
||||
* statistics. Please notice that it should not return
|
||||
* an error code if the statistics are not available
|
||||
* because the demog is not locked.
|
||||
* @read_status: returns the locking status of the frontend.
|
||||
* @read_ber: legacy callback function to return the bit error rate.
|
||||
* Newer drivers should provide such info via DVBv5 API,
|
||||
* e. g. @set_frontend;/@get_frontend;, implementing this
|
||||
* callback only if DVBv3 API compatibility is wanted.
|
||||
* @read_signal_strength: legacy callback function to return the signal
|
||||
* strength. Newer drivers should provide such info via
|
||||
* DVBv5 API, e. g. @set_frontend;/@get_frontend;,
|
||||
* implementing this callback only if DVBv3 API
|
||||
* compatibility is wanted.
|
||||
* @read_snr: legacy callback function to return the Signal/Noise
|
||||
* rate. Newer drivers should provide such info via
|
||||
* DVBv5 API, e. g. @set_frontend;/@get_frontend;,
|
||||
* implementing this callback only if DVBv3 API
|
||||
* compatibility is wanted.
|
||||
* @read_ucblocks: legacy callback function to return the Uncorrected Error
|
||||
* Blocks. Newer drivers should provide such info via
|
||||
* DVBv5 API, e. g. @set_frontend;/@get_frontend;,
|
||||
* implementing this callback only if DVBv3 API
|
||||
* compatibility is wanted.
|
||||
* @diseqc_reset_overload: callback function to implement the
|
||||
* FE_DISEQC_RESET_OVERLOAD ioctl (only Satellite)
|
||||
* @diseqc_send_master_cmd: callback function to implement the
|
||||
* FE_DISEQC_SEND_MASTER_CMD ioctl (only Satellite).
|
||||
* @diseqc_recv_slave_reply: callback function to implement the
|
||||
* FE_DISEQC_RECV_SLAVE_REPLY ioctl (only Satellite)
|
||||
* @diseqc_send_burst: callback function to implement the
|
||||
* FE_DISEQC_SEND_BURST ioctl (only Satellite).
|
||||
* @set_tone: callback function to implement the
|
||||
* FE_SET_TONE ioctl (only Satellite).
|
||||
* @set_voltage: callback function to implement the
|
||||
* FE_SET_VOLTAGE ioctl (only Satellite).
|
||||
* @enable_high_lnb_voltage: callback function to implement the
|
||||
* FE_ENABLE_HIGH_LNB_VOLTAGE ioctl (only Satellite).
|
||||
* @dishnetwork_send_legacy_command: callback function to implement the
|
||||
* FE_DISHNETWORK_SEND_LEGACY_CMD ioctl (only Satellite).
|
||||
* Drivers should not use this, except when the DVB
|
||||
* core emulation fails to provide proper support (e.g.
|
||||
* if @set_voltage takes more than 8ms to work), and
|
||||
* when backward compatibility with this legacy API is
|
||||
* required.
|
||||
* @i2c_gate_ctrl: controls the I2C gate. Newer drivers should use I2C
|
||||
* mux support instead.
|
||||
* @ts_bus_ctrl: callback function used to take control of the TS bus.
|
||||
* @set_lna: callback function to power on/off/auto the LNA.
|
||||
* @search: callback function used on some custom algo search algos.
|
||||
* @tuner_ops: pointer to struct dvb_tuner_ops
|
||||
* @analog_ops: pointer to struct analog_demod_ops
|
||||
* @set_property: callback function to allow the frontend to validade
|
||||
* incoming properties. Should not be used on new drivers.
|
||||
* @get_property: callback function to allow the frontend to override
|
||||
* outcoming properties. Should not be used on new drivers.
|
||||
*/
|
||||
struct dvb_frontend_ops {
|
||||
|
||||
struct dvb_frontend_info info;
|
||||
|
||||
u8 delsys[MAX_DELSYS];
|
||||
|
||||
void (*detach)(struct dvb_frontend *fe);
|
||||
void (*release)(struct dvb_frontend* fe);
|
||||
void (*release_sec)(struct dvb_frontend* fe);
|
||||
|
||||
@ -282,7 +431,8 @@ struct dvb_frontend_ops {
|
||||
bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay,
|
||||
fe_status_t *status);
|
||||
enum fe_status *status);
|
||||
|
||||
/* get frontend tuning algorithm from the module */
|
||||
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
|
||||
|
||||
@ -290,9 +440,10 @@ struct dvb_frontend_ops {
|
||||
int (*set_frontend)(struct dvb_frontend *fe);
|
||||
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
|
||||
|
||||
int (*get_frontend)(struct dvb_frontend *fe);
|
||||
int (*get_frontend)(struct dvb_frontend *fe,
|
||||
struct dtv_frontend_properties *props);
|
||||
|
||||
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
|
||||
int (*read_status)(struct dvb_frontend *fe, enum fe_status *status);
|
||||
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
|
||||
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
|
||||
int (*read_snr)(struct dvb_frontend* fe, u16* snr);
|
||||
@ -301,9 +452,11 @@ struct dvb_frontend_ops {
|
||||
int (*diseqc_reset_overload)(struct dvb_frontend* fe);
|
||||
int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
|
||||
int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
|
||||
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
|
||||
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
|
||||
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
||||
int (*diseqc_send_burst)(struct dvb_frontend *fe,
|
||||
enum fe_sec_mini_cmd minicmd);
|
||||
int (*set_tone)(struct dvb_frontend *fe, enum fe_sec_tone_mode tone);
|
||||
int (*set_voltage)(struct dvb_frontend *fe,
|
||||
enum fe_sec_voltage voltage);
|
||||
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
|
||||
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
|
||||
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
|
||||
@ -311,7 +464,8 @@ struct dvb_frontend_ops {
|
||||
int (*set_lna)(struct dvb_frontend *);
|
||||
int (*set_input)(struct dvb_frontend *, int);
|
||||
|
||||
/* These callbacks are for devices that implement their own
|
||||
/*
|
||||
* These callbacks are for devices that implement their own
|
||||
* tuning algorithms, rather than a simple swzigzag
|
||||
*/
|
||||
enum dvbfe_search (*search)(struct dvb_frontend *fe);
|
||||
@ -328,6 +482,7 @@ struct dvb_frontend_ops {
|
||||
#ifdef __DVB_CORE__
|
||||
#define MAX_EVENT 8
|
||||
|
||||
/* Used only internally at dvb_frontend.c */
|
||||
struct dvb_fe_events {
|
||||
struct dvb_frontend_event events[MAX_EVENT];
|
||||
int eventw;
|
||||
@ -338,30 +493,100 @@ struct dvb_fe_events {
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct dtv_frontend_properties - contains a list of properties that are
|
||||
* specific to a digital TV standard.
|
||||
*
|
||||
* @frequency: frequency in Hz for terrestrial/cable or in kHz for
|
||||
* Satellite
|
||||
* @modulation: Frontend modulation type
|
||||
* @voltage: SEC voltage (only Satellite)
|
||||
* @sectone: SEC tone mode (only Satellite)
|
||||
* @inversion: Spectral inversion
|
||||
* @fec_inner: Forward error correction inner Code Rate
|
||||
* @transmission_mode: Transmission Mode
|
||||
* @bandwidth_hz: Bandwidth, in Hz. A zero value means that userspace
|
||||
* wants to autodetect.
|
||||
* @guard_interval: Guard Interval
|
||||
* @hierarchy: Hierarchy
|
||||
* @symbol_rate: Symbol Rate
|
||||
* @code_rate_HP: high priority stream code rate
|
||||
* @code_rate_LP: low priority stream code rate
|
||||
* @pilot: Enable/disable/autodetect pilot tones
|
||||
* @rolloff: Rolloff factor (alpha)
|
||||
* @delivery_system: FE delivery system (e. g. digital TV standard)
|
||||
* @interleaving: interleaving
|
||||
* @isdbt_partial_reception: ISDB-T partial reception (only ISDB standard)
|
||||
* @isdbt_sb_mode: ISDB-T Sound Broadcast (SB) mode (only ISDB standard)
|
||||
* @isdbt_sb_subchannel: ISDB-T SB subchannel (only ISDB standard)
|
||||
* @isdbt_sb_segment_idx: ISDB-T SB segment index (only ISDB standard)
|
||||
* @isdbt_sb_segment_count: ISDB-T SB segment count (only ISDB standard)
|
||||
* @isdbt_layer_enabled: ISDB Layer enabled (only ISDB standard)
|
||||
* @layer: ISDB per-layer data (only ISDB standard)
|
||||
* @layer.segment_count: Segment Count;
|
||||
* @layer.fec: per layer code rate;
|
||||
* @layer.modulation: per layer modulation;
|
||||
* @layer.interleaving: per layer interleaving.
|
||||
* @stream_id: If different than zero, enable substream filtering, if
|
||||
* hardware supports (DVB-S2 and DVB-T2).
|
||||
* @atscmh_fic_ver: Version number of the FIC (Fast Information Channel)
|
||||
* signaling data (only ATSC-M/H)
|
||||
* @atscmh_parade_id: Parade identification number (only ATSC-M/H)
|
||||
* @atscmh_nog: Number of MH groups per MH subframe for a designated
|
||||
* parade (only ATSC-M/H)
|
||||
* @atscmh_tnog: Total number of MH groups including all MH groups
|
||||
* belonging to all MH parades in one MH subframe
|
||||
* (only ATSC-M/H)
|
||||
* @atscmh_sgn: Start group number (only ATSC-M/H)
|
||||
* @atscmh_prc: Parade repetition cycle (only ATSC-M/H)
|
||||
* @atscmh_rs_frame_mode: Reed Solomon (RS) frame mode (only ATSC-M/H)
|
||||
* @atscmh_rs_frame_ensemble: RS frame ensemble (only ATSC-M/H)
|
||||
* @atscmh_rs_code_mode_pri: RS code mode pri (only ATSC-M/H)
|
||||
* @atscmh_rs_code_mode_sec: RS code mode sec (only ATSC-M/H)
|
||||
* @atscmh_sccc_block_mode: Series Concatenated Convolutional Code (SCCC)
|
||||
* Block Mode (only ATSC-M/H)
|
||||
* @atscmh_sccc_code_mode_a: SCCC code mode A (only ATSC-M/H)
|
||||
* @atscmh_sccc_code_mode_b: SCCC code mode B (only ATSC-M/H)
|
||||
* @atscmh_sccc_code_mode_c: SCCC code mode C (only ATSC-M/H)
|
||||
* @atscmh_sccc_code_mode_d: SCCC code mode D (only ATSC-M/H)
|
||||
* @lna: Power ON/OFF/AUTO the Linear Now-noise Amplifier (LNA)
|
||||
* @strength: DVBv5 API statistics: Signal Strength
|
||||
* @cnr: DVBv5 API statistics: Signal to Noise ratio of the
|
||||
* (main) carrier
|
||||
* @pre_bit_error: DVBv5 API statistics: pre-Viterbi bit error count
|
||||
* @pre_bit_count: DVBv5 API statistics: pre-Viterbi bit count
|
||||
* @post_bit_error: DVBv5 API statistics: post-Viterbi bit error count
|
||||
* @post_bit_count: DVBv5 API statistics: post-Viterbi bit count
|
||||
* @block_error: DVBv5 API statistics: block error count
|
||||
* @block_count: DVBv5 API statistics: block count
|
||||
*
|
||||
* NOTE: derivated statistics like Uncorrected Error blocks (UCE) are
|
||||
* calculated on userspace.
|
||||
*
|
||||
* Only a subset of the properties are needed for a given delivery system.
|
||||
* For more info, consult the media_api.html with the documentation of the
|
||||
* Userspace API.
|
||||
*/
|
||||
struct dtv_frontend_properties {
|
||||
|
||||
/* Cache State */
|
||||
u32 state;
|
||||
|
||||
u32 frequency;
|
||||
fe_modulation_t modulation;
|
||||
enum fe_modulation modulation;
|
||||
|
||||
fe_sec_voltage_t voltage;
|
||||
fe_sec_tone_mode_t sectone;
|
||||
fe_spectral_inversion_t inversion;
|
||||
fe_code_rate_t fec_inner;
|
||||
fe_transmit_mode_t transmission_mode;
|
||||
enum fe_sec_voltage voltage;
|
||||
enum fe_sec_tone_mode sectone;
|
||||
enum fe_spectral_inversion inversion;
|
||||
enum fe_code_rate fec_inner;
|
||||
enum fe_transmit_mode transmission_mode;
|
||||
u32 bandwidth_hz; /* 0 = AUTO */
|
||||
fe_guard_interval_t guard_interval;
|
||||
fe_hierarchy_t hierarchy;
|
||||
enum fe_guard_interval guard_interval;
|
||||
enum fe_hierarchy hierarchy;
|
||||
u32 symbol_rate;
|
||||
fe_code_rate_t code_rate_HP;
|
||||
fe_code_rate_t code_rate_LP;
|
||||
enum fe_code_rate code_rate_HP;
|
||||
enum fe_code_rate code_rate_LP;
|
||||
|
||||
fe_pilot_t pilot;
|
||||
fe_rolloff_t rolloff;
|
||||
enum fe_pilot pilot;
|
||||
enum fe_rolloff rolloff;
|
||||
|
||||
fe_delivery_system_t delivery_system;
|
||||
enum fe_delivery_system delivery_system;
|
||||
|
||||
enum fe_interleaving interleaving;
|
||||
|
||||
@ -374,8 +599,8 @@ struct dtv_frontend_properties {
|
||||
u8 isdbt_layer_enabled;
|
||||
struct {
|
||||
u8 segment_count;
|
||||
fe_code_rate_t fec;
|
||||
fe_modulation_t modulation;
|
||||
enum fe_code_rate fec;
|
||||
enum fe_modulation modulation;
|
||||
u8 interleaving;
|
||||
} layer[3];
|
||||
|
||||
@ -413,9 +638,41 @@ struct dtv_frontend_properties {
|
||||
struct dtv_fe_stats post_bit_count;
|
||||
struct dtv_fe_stats block_error;
|
||||
struct dtv_fe_stats block_count;
|
||||
|
||||
/* private: */
|
||||
/* Cache State */
|
||||
u32 state;
|
||||
|
||||
};
|
||||
|
||||
#define DVB_FE_NO_EXIT 0
|
||||
#define DVB_FE_NORMAL_EXIT 1
|
||||
#define DVB_FE_DEVICE_REMOVED 2
|
||||
#define DVB_FE_DEVICE_RESUME 3
|
||||
|
||||
/**
|
||||
* struct dvb_frontend - Frontend structure to be used on drivers.
|
||||
*
|
||||
* @refcount: refcount to keep track of struct dvb_frontend
|
||||
* references
|
||||
* @ops: embedded struct dvb_frontend_ops
|
||||
* @dvb: pointer to struct dvb_adapter
|
||||
* @demodulator_priv: demod private data
|
||||
* @tuner_priv: tuner private data
|
||||
* @frontend_priv: frontend private data
|
||||
* @sec_priv: SEC private data
|
||||
* @analog_demod_priv: Analog demod private data
|
||||
* @dtv_property_cache: embedded struct dtv_frontend_properties
|
||||
* @callback: callback function used on some drivers to call
|
||||
* either the tuner or the demodulator.
|
||||
* @id: Frontend ID
|
||||
* @exit: Used to inform the DVB core that the frontend
|
||||
* thread should exit (usually, means that the hardware
|
||||
* got disconnected.
|
||||
*/
|
||||
|
||||
struct dvb_frontend {
|
||||
struct kref refcount;
|
||||
struct dvb_frontend_ops ops;
|
||||
struct dvb_adapter *dvb;
|
||||
void *demodulator_priv;
|
||||
@ -428,20 +685,129 @@ struct dvb_frontend {
|
||||
#define DVB_FRONTEND_COMPONENT_DEMOD 1
|
||||
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
|
||||
int id;
|
||||
unsigned int exit;
|
||||
};
|
||||
|
||||
extern int dvb_register_frontend(struct dvb_adapter *dvb,
|
||||
/**
|
||||
* dvb_register_frontend() - Registers a DVB frontend at the adapter
|
||||
*
|
||||
* @dvb: pointer to the dvb adapter
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* Allocate and initialize the private data needed by the frontend core to
|
||||
* manage the frontend and calls dvb_register_device() to register a new
|
||||
* frontend. It also cleans the property cache that stores the frontend
|
||||
* parameters and selects the first available delivery system.
|
||||
*/
|
||||
int dvb_register_frontend(struct dvb_adapter *dvb,
|
||||
struct dvb_frontend *fe);
|
||||
|
||||
extern int dvb_unregister_frontend(struct dvb_frontend *fe);
|
||||
/**
|
||||
* dvb_unregister_frontend() - Unregisters a DVB frontend
|
||||
*
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* Stops the frontend kthread, calls dvb_unregister_device() and frees the
|
||||
* private frontend data allocated by dvb_register_frontend().
|
||||
*
|
||||
* NOTE: This function doesn't frees the memory allocated by the demod,
|
||||
* by the SEC driver and by the tuner. In order to free it, an explicit call to
|
||||
* dvb_frontend_detach() is needed, after calling this function.
|
||||
*/
|
||||
int dvb_unregister_frontend(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_detach(struct dvb_frontend *fe);
|
||||
/**
|
||||
* dvb_frontend_detach() - Detaches and frees frontend specific data
|
||||
*
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* This function should be called after dvb_unregister_frontend(). It
|
||||
* calls the SEC, tuner and demod release functions:
|
||||
* &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release,
|
||||
* &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release.
|
||||
*
|
||||
* If the driver is compiled with CONFIG_MEDIA_ATTACH, it also decreases
|
||||
* the module reference count, needed to allow userspace to remove the
|
||||
* previously used DVB frontend modules.
|
||||
*/
|
||||
void dvb_frontend_detach(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
|
||||
extern int dvb_frontend_suspend(struct dvb_frontend *fe);
|
||||
extern int dvb_frontend_resume(struct dvb_frontend *fe);
|
||||
/**
|
||||
* dvb_frontend_suspend() - Suspends a Digital TV frontend
|
||||
*
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* This function prepares a Digital TV frontend to suspend.
|
||||
*
|
||||
* In order to prepare the tuner to suspend, if
|
||||
* &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise,
|
||||
* it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available.
|
||||
*
|
||||
* It will also call &dvb_frontend_ops.sleep\(\) to put the demod to suspend.
|
||||
*
|
||||
* The drivers should also call dvb_frontend_suspend\(\) as part of their
|
||||
* handler for the &device_driver.suspend\(\).
|
||||
*/
|
||||
int dvb_frontend_suspend(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
|
||||
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
|
||||
/**
|
||||
* dvb_frontend_resume() - Resumes a Digital TV frontend
|
||||
*
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* This function resumes the usual operation of the tuner after resume.
|
||||
*
|
||||
* In order to resume the frontend, it calls the demod &dvb_frontend_ops.init\(\).
|
||||
*
|
||||
* If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it.
|
||||
* Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.
|
||||
*
|
||||
* Once tuner and demods are resumed, it will enforce that the SEC voltage and
|
||||
* tone are restored to their previous values and wake up the frontend's
|
||||
* kthread in order to retune the frontend.
|
||||
*
|
||||
* The drivers should also call dvb_frontend_resume() as part of their
|
||||
* handler for the &device_driver.resume\(\).
|
||||
*/
|
||||
int dvb_frontend_resume(struct dvb_frontend *fe);
|
||||
|
||||
/**
|
||||
* dvb_frontend_reinitialise() - forces a reinitialisation at the frontend
|
||||
*
|
||||
* @fe: pointer to the frontend struct
|
||||
*
|
||||
* Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\),
|
||||
* and resets SEC tone and voltage (for Satellite systems).
|
||||
*
|
||||
* NOTE: Currently, this function is used only by one driver (budget-av).
|
||||
* It seems to be due to address some special issue with that specific
|
||||
* frontend.
|
||||
*/
|
||||
void dvb_frontend_reinitialise(struct dvb_frontend *fe);
|
||||
|
||||
/**
|
||||
* dvb_frontend_sleep_until() - Sleep for the amount of time given by
|
||||
* add_usec parameter
|
||||
*
|
||||
* @waketime: pointer to a struct ktime_t
|
||||
* @add_usec: time to sleep, in microseconds
|
||||
*
|
||||
* This function is used to measure the time required for the
|
||||
* %FE_DISHNETWORK_SEND_LEGACY_CMD ioctl to work. It needs to be as precise
|
||||
* as possible, as it affects the detection of the dish tone command at the
|
||||
* satellite subsystem.
|
||||
*
|
||||
* Its used internally by the DVB frontend core, in order to emulate
|
||||
* %FE_DISHNETWORK_SEND_LEGACY_CMD using the &dvb_frontend_ops.set_voltage\(\)
|
||||
* callback.
|
||||
*
|
||||
* NOTE: it should not be used at the drivers, as the emulation for the
|
||||
* legacy callback is provided by the Kernel. The only situation where this
|
||||
* should be at the drivers is when there are some bugs at the hardware that
|
||||
* would prevent the core emulation to work. On such cases, the driver would
|
||||
* be writing a &dvb_frontend_ops.dishnetwork_send_legacy_command\(\) and
|
||||
* calling this function directly.
|
||||
*/
|
||||
void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec);
|
||||
|
||||
#endif
|
||||
|
@ -13,10 +13,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
@ -13,10 +13,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __DVB_MATH_H
|
||||
@ -25,33 +21,45 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* computes log2 of a value; the result is shifted left by 24 bits
|
||||
* intlog2 - computes log2 of a value; the result is shifted left by 24 bits
|
||||
*
|
||||
* @value: The value (must be != 0)
|
||||
*
|
||||
* to use rational values you can use the following method:
|
||||
*
|
||||
* intlog2(value) = intlog2(value * 2^x) - x * 2^24
|
||||
*
|
||||
* example: intlog2(8) will give 3 << 24 = 3 * 2^24
|
||||
* example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
|
||||
* example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
|
||||
* Some usecase examples:
|
||||
*
|
||||
* @param value The value (must be != 0)
|
||||
* @return log2(value) * 2^24
|
||||
* intlog2(8) will give 3 << 24 = 3 * 2^24
|
||||
*
|
||||
* intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
|
||||
*
|
||||
* intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
|
||||
*
|
||||
*
|
||||
* return: log2(value) * 2^24
|
||||
*/
|
||||
extern unsigned int intlog2(u32 value);
|
||||
|
||||
/**
|
||||
* computes log10 of a value; the result is shifted left by 24 bits
|
||||
* intlog10 - computes log10 of a value; the result is shifted left by 24 bits
|
||||
*
|
||||
* @value: The value (must be != 0)
|
||||
*
|
||||
* to use rational values you can use the following method:
|
||||
*
|
||||
* intlog10(value) = intlog10(value * 10^x) - x * 2^24
|
||||
*
|
||||
* example: intlog10(1000) will give 3 << 24 = 3 * 2^24
|
||||
* An usecase example:
|
||||
*
|
||||
* intlog10(1000) will give 3 << 24 = 3 * 2^24
|
||||
*
|
||||
* due to the implementation intlog10(1000) might be not exactly 3 * 2^24
|
||||
*
|
||||
* look at intlog2 for similar examples
|
||||
*
|
||||
* @param value The value (must be != 0)
|
||||
* @return log10(value) * 2^24
|
||||
* return: log10(value) * 2^24
|
||||
*/
|
||||
extern unsigned int intlog10(u32 value);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DVB_NET_H_
|
||||
|
@ -241,7 +241,7 @@ int dvb_netstream_init(struct dvb_adapter *dvb_adapter,
|
||||
spin_lock_init(&ns->lock);
|
||||
ns->exit = 0;
|
||||
dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns,
|
||||
DVB_DEVICE_NS);
|
||||
DVB_DEVICE_NS, 0);
|
||||
INIT_LIST_HEAD(&ns->nssl);
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,10 +18,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
@ -60,7 +56,13 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
|
||||
|
||||
int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
return (rbuf->pread==rbuf->pwrite);
|
||||
/* smp_load_acquire() to load write pointer on reader side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
||||
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
||||
*
|
||||
* for memory barriers also see Documentation/circular-buffers.txt
|
||||
*/
|
||||
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +71,12 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
ssize_t free;
|
||||
|
||||
free = rbuf->pread - rbuf->pwrite;
|
||||
/* ACCESS_ONCE() to load read pointer on writer side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_read(),
|
||||
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
|
||||
* or dvb_ringbuffer_reset()
|
||||
*/
|
||||
free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite;
|
||||
if (free <= 0)
|
||||
free += rbuf->size;
|
||||
return free-1;
|
||||
@ -81,7 +88,11 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
ssize_t avail;
|
||||
|
||||
avail = rbuf->pwrite - rbuf->pread;
|
||||
/* smp_load_acquire() to load write pointer on reader side
|
||||
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
||||
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
||||
*/
|
||||
avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread;
|
||||
if (avail < 0)
|
||||
avail += rbuf->size;
|
||||
return avail;
|
||||
@ -91,14 +102,25 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
||||
|
||||
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
rbuf->pread = rbuf->pwrite;
|
||||
/* dvb_ringbuffer_flush() counts as read operation
|
||||
* smp_load_acquire() to load write pointer
|
||||
* smp_store_release() to update read pointer, this ensures that the
|
||||
* correct pointer is visible for subsequent dvb_ringbuffer_free()
|
||||
* calls on other cpu cores
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite));
|
||||
rbuf->error = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_flush);
|
||||
|
||||
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
rbuf->pread = rbuf->pwrite = 0;
|
||||
/* dvb_ringbuffer_reset() counts as read and write operation
|
||||
* smp_store_release() to update read pointer
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
/* smp_store_release() to update write pointer */
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
rbuf->error = 0;
|
||||
}
|
||||
|
||||
@ -124,12 +146,17 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
|
||||
return -EFAULT;
|
||||
buf += split;
|
||||
todo -= split;
|
||||
rbuf->pread = 0;
|
||||
/* smp_store_release() for read pointer update to ensure
|
||||
* that buf is not overwritten until read is complete,
|
||||
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
}
|
||||
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
|
||||
return -EFAULT;
|
||||
|
||||
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
||||
/* smp_store_release() to update read pointer, see above */
|
||||
smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -144,11 +171,16 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
|
||||
memcpy(buf, rbuf->data+rbuf->pread, split);
|
||||
buf += split;
|
||||
todo -= split;
|
||||
rbuf->pread = 0;
|
||||
/* smp_store_release() for read pointer update to ensure
|
||||
* that buf is not overwritten until read is complete,
|
||||
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
||||
*/
|
||||
smp_store_release(&rbuf->pread, 0);
|
||||
}
|
||||
memcpy(buf, rbuf->data+rbuf->pread, todo);
|
||||
|
||||
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
||||
/* smp_store_release() to update read pointer, see above */
|
||||
smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
||||
}
|
||||
|
||||
|
||||
@ -163,10 +195,47 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
|
||||
memcpy(rbuf->data+rbuf->pwrite, buf, split);
|
||||
buf += split;
|
||||
todo -= split;
|
||||
rbuf->pwrite = 0;
|
||||
/* smp_store_release() for write pointer update to ensure that
|
||||
* written data is visible on other cpu cores before the pointer
|
||||
* update, this pairs with smp_load_acquire() in
|
||||
* dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
||||
*/
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
}
|
||||
memcpy(rbuf->data+rbuf->pwrite, buf, todo);
|
||||
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
||||
/* smp_store_release() for write pointer update, see above */
|
||||
smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
||||
const u8 __user *buf, size_t len)
|
||||
{
|
||||
int status;
|
||||
size_t todo = len;
|
||||
size_t split;
|
||||
|
||||
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
|
||||
|
||||
if (split > 0) {
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split);
|
||||
if (status)
|
||||
return len - todo;
|
||||
buf += split;
|
||||
todo -= split;
|
||||
/* smp_store_release() for write pointer update to ensure that
|
||||
* written data is visible on other cpu cores before the pointer
|
||||
* update, this pairs with smp_load_acquire() in
|
||||
* dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
||||
*/
|
||||
smp_store_release(&rbuf->pwrite, 0);
|
||||
}
|
||||
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
|
||||
if (status)
|
||||
return len - todo;
|
||||
/* smp_store_release() for write pointer update, see above */
|
||||
smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -302,3 +371,4 @@ EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_read);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write);
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_write_user);
|
||||
|
@ -18,10 +18,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_RINGBUFFER_H_
|
||||
@ -30,6 +26,18 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
/**
|
||||
* struct dvb_ringbuffer - Describes a ring buffer used at DVB framework
|
||||
*
|
||||
* @data: Area were the ringbuffer data is written
|
||||
* @size: size of the ringbuffer
|
||||
* @pread: next position to read
|
||||
* @pwrite: next position to write
|
||||
* @error: used by ringbuffer clients to indicate that an error happened.
|
||||
* @queue: Wait queue used by ringbuffer clients to indicate when buffer
|
||||
* was filled
|
||||
* @lock: Spinlock used to protect the ringbuffer
|
||||
*/
|
||||
struct dvb_ringbuffer {
|
||||
u8 *data;
|
||||
ssize_t size;
|
||||
@ -43,144 +51,230 @@ struct dvb_ringbuffer {
|
||||
|
||||
#define DVB_RINGBUFFER_PKTHDRSIZE 3
|
||||
|
||||
|
||||
/*
|
||||
** Notes:
|
||||
** ------
|
||||
** (1) For performance reasons read and write routines don't check buffer sizes
|
||||
** and/or number of bytes free/available. This has to be done before these
|
||||
** routines are called. For example:
|
||||
**
|
||||
** *** write <buflen> bytes ***
|
||||
** free = dvb_ringbuffer_free(rbuf);
|
||||
** if (free >= buflen)
|
||||
** count = dvb_ringbuffer_write(rbuf, buffer, buflen);
|
||||
** else
|
||||
** ...
|
||||
**
|
||||
** *** read min. 1000, max. <bufsize> bytes ***
|
||||
** avail = dvb_ringbuffer_avail(rbuf);
|
||||
** if (avail >= 1000)
|
||||
** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
|
||||
** else
|
||||
** ...
|
||||
**
|
||||
** (2) If there is exactly one reader and one writer, there is no need
|
||||
** to lock read or write operations.
|
||||
** Two or more readers must be locked against each other.
|
||||
** Flushing the buffer counts as a read operation.
|
||||
** Resetting the buffer counts as a read and write operation.
|
||||
** Two or more writers must be locked against each other.
|
||||
/**
|
||||
* dvb_ringbuffer_init - initialize ring buffer, lock and queue
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @data: pointer to the buffer where the data will be stored
|
||||
* @len: bytes from ring buffer into @buf
|
||||
*/
|
||||
extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data,
|
||||
size_t len);
|
||||
|
||||
/* initialize ring buffer, lock and queue */
|
||||
extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len);
|
||||
|
||||
/* test whether buffer is empty */
|
||||
/**
|
||||
* dvb_ringbuffer_empty - test whether buffer is empty
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*/
|
||||
extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* return the number of free bytes in the buffer */
|
||||
/**
|
||||
* dvb_ringbuffer_free - returns the number of free bytes in the buffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*
|
||||
* Return: number of free bytes in the buffer
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* return the number of bytes waiting in the buffer */
|
||||
/**
|
||||
* dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*
|
||||
* Return: number of bytes waiting in the buffer
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
|
||||
/*
|
||||
** Reset the read and write pointers to zero and flush the buffer
|
||||
** This counts as a read and write operation
|
||||
/**
|
||||
* dvb_ringbuffer_reset - resets the ringbuffer to initial state
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*
|
||||
* Resets the read and write pointers to zero and flush the buffer.
|
||||
*
|
||||
* This counts as a read and write operation
|
||||
*/
|
||||
extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/*
|
||||
* read routines & macros
|
||||
*/
|
||||
|
||||
/* read routines & macros */
|
||||
/* ---------------------- */
|
||||
/* flush buffer */
|
||||
/**
|
||||
* dvb_ringbuffer_flush - flush buffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*/
|
||||
extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* flush buffer protected by spinlock and wake-up waiting task(s) */
|
||||
/**
|
||||
* dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock
|
||||
* and wake-up waiting task(s)
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
*/
|
||||
extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
|
||||
|
||||
/* peek at byte <offs> in the buffer */
|
||||
/**
|
||||
* DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @offs: offset inside the ringbuffer
|
||||
*/
|
||||
#define DVB_RINGBUFFER_PEEK(rbuf, offs) \
|
||||
(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
|
||||
((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size])
|
||||
|
||||
/* advance read ptr by <num> bytes */
|
||||
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
|
||||
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
|
||||
/**
|
||||
* DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @num: number of bytes to advance
|
||||
*/
|
||||
#define DVB_RINGBUFFER_SKIP(rbuf, num) {\
|
||||
(rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\
|
||||
}
|
||||
|
||||
/*
|
||||
** read <len> bytes from ring buffer into <buf>
|
||||
** <usermem> specifies whether <buf> resides in user space
|
||||
** returns number of bytes transferred or -EFAULT
|
||||
/**
|
||||
* dvb_ringbuffer_read_user - Reads a buffer into a user pointer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @buf: pointer to the buffer where the data will be stored
|
||||
* @len: bytes from ring buffer into @buf
|
||||
*
|
||||
* This variant assumes that the buffer is a memory at the userspace. So,
|
||||
* it will internally call copy_to_user().
|
||||
*
|
||||
* Return: number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
|
||||
u8 __user *buf, size_t len);
|
||||
|
||||
/**
|
||||
* dvb_ringbuffer_read - Reads a buffer into a pointer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @buf: pointer to the buffer where the data will be stored
|
||||
* @len: bytes from ring buffer into @buf
|
||||
*
|
||||
* This variant assumes that the buffer is a memory at the Kernel space
|
||||
*
|
||||
* Return: number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
|
||||
u8 *buf, size_t len);
|
||||
|
||||
/*
|
||||
* write routines & macros
|
||||
*/
|
||||
|
||||
/* write routines & macros */
|
||||
/* ----------------------- */
|
||||
/* write single byte to ring buffer */
|
||||
/**
|
||||
* DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @byte: byte to write
|
||||
*/
|
||||
#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \
|
||||
{ (rbuf)->data[(rbuf)->pwrite] = (byte); \
|
||||
(rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; }
|
||||
/*
|
||||
** write <len> bytes to ring buffer
|
||||
** <usermem> specifies whether <buf> resides in user space
|
||||
** returns number of bytes transferred or -EFAULT
|
||||
|
||||
/**
|
||||
* dvb_ringbuffer_write - Writes a buffer into the ringbuffer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @buf: pointer to the buffer where the data will be read
|
||||
* @len: bytes from ring buffer into @buf
|
||||
*
|
||||
* This variant assumes that the buffer is a memory at the Kernel space
|
||||
*
|
||||
* return: number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* dvb_ringbuffer_write_user - Writes a buffer received via a user pointer
|
||||
*
|
||||
* @rbuf: pointer to struct dvb_ringbuffer
|
||||
* @buf: pointer to the buffer where the data will be read
|
||||
* @len: bytes from ring buffer into @buf
|
||||
*
|
||||
* This variant assumes that the buffer is a memory at the userspace. So,
|
||||
* it will internally call copy_from_user().
|
||||
*
|
||||
* Return: number of bytes transferred or -EFAULT
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
||||
const u8 __user *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Write a packet into the ringbuffer.
|
||||
* dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer.
|
||||
*
|
||||
* <rbuf> Ringbuffer to write to.
|
||||
* <buf> Buffer to write.
|
||||
* <len> Length of buffer (currently limited to 65535 bytes max).
|
||||
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
|
||||
* @rbuf: Ringbuffer to write to.
|
||||
* @buf: Buffer to write.
|
||||
* @len: Length of buffer (currently limited to 65535 bytes max).
|
||||
*
|
||||
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
|
||||
* does NOT update the read pointer in the ringbuffer. You must use
|
||||
* dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required.
|
||||
* dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer.
|
||||
*
|
||||
* <rbuf> Ringbuffer concerned.
|
||||
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
* <offset> Offset into packet to read from.
|
||||
* <buf> Destination buffer for data.
|
||||
* <len> Size of destination buffer.
|
||||
* <usermem> Set to 1 if <buf> is in userspace.
|
||||
* returns Number of bytes read, or -EFAULT.
|
||||
* @rbuf: Ringbuffer concerned.
|
||||
* @idx: Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
* @offset: Offset into packet to read from.
|
||||
* @buf: Destination buffer for data.
|
||||
* @len: Size of destination buffer.
|
||||
*
|
||||
* Return: Number of bytes read, or -EFAULT.
|
||||
*
|
||||
* .. note::
|
||||
*
|
||||
* unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer
|
||||
* in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a
|
||||
* packet as no longer required.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf,
|
||||
size_t idx,
|
||||
int offset, u8 __user *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer.
|
||||
* Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer
|
||||
* in the ringbuffer.
|
||||
*
|
||||
* @rbuf: Ringbuffer concerned.
|
||||
* @idx: Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
* @offset: Offset into packet to read from.
|
||||
* @buf: Destination buffer for data.
|
||||
* @len: Size of destination buffer.
|
||||
*
|
||||
* Return: Number of bytes read, or -EFAULT.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
|
||||
int offset, u8 __user *buf, size_t len);
|
||||
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
|
||||
int offset, u8 *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Dispose of a packet in the ring buffer.
|
||||
* dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer.
|
||||
*
|
||||
* <rbuf> Ring buffer concerned.
|
||||
* <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
* @rbuf: Ring buffer concerned.
|
||||
* @idx: Packet index as returned by dvb_ringbuffer_pkt_next().
|
||||
*/
|
||||
extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
|
||||
|
||||
/**
|
||||
* Get the index of the next packet in a ringbuffer.
|
||||
* dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer.
|
||||
*
|
||||
* <rbuf> Ringbuffer concerned.
|
||||
* <idx> Previous packet index, or -1 to return the first packet index.
|
||||
* <pktlen> On success, will be updated to contain the length of the packet in bytes.
|
||||
* @rbuf: Ringbuffer concerned.
|
||||
* @idx: Previous packet index, or -1 to return the first packet index.
|
||||
* @pktlen: On success, will be updated to contain the length of the packet
|
||||
* in bytes.
|
||||
* returns Packet index (if >=0), or -1 if no packets available.
|
||||
*/
|
||||
extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen);
|
||||
|
||||
extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf,
|
||||
size_t idx, size_t *pktlen);
|
||||
|
||||
#endif /* _DVB_RINGBUFFER_H_ */
|
||||
|
@ -15,12 +15,10 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "dvbdev: " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
@ -35,13 +33,22 @@
|
||||
#include <linux/version.h>
|
||||
#include "dvbdev.h"
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0))
|
||||
/* Due to enum tuner_pad_index */
|
||||
#include <media/tuner.h>
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(dvbdev_mutex);
|
||||
static int dvbdev_debug;
|
||||
|
||||
module_param(dvbdev_debug, int, 0644);
|
||||
MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
|
||||
|
||||
#define dprintk if (dvbdev_debug) printk
|
||||
#define dprintk(fmt, arg...) do { \
|
||||
if (dvbdev_debug) \
|
||||
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
|
||||
__func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
static LIST_HEAD(dvb_adapter_list);
|
||||
static DEFINE_MUTEX(dvbdev_register_lock);
|
||||
@ -75,22 +82,15 @@ static int dvb_device_open(struct inode *inode, struct file *file)
|
||||
|
||||
if (dvbdev && dvbdev->fops) {
|
||||
int err = 0;
|
||||
const struct file_operations *old_fops;
|
||||
const struct file_operations *new_fops;
|
||||
|
||||
file->private_data = dvbdev;
|
||||
old_fops = file->f_op;
|
||||
file->f_op = fops_get(dvbdev->fops);
|
||||
if (file->f_op == NULL) {
|
||||
file->f_op = old_fops;
|
||||
new_fops = fops_get(dvbdev->fops);
|
||||
if (!new_fops)
|
||||
goto fail;
|
||||
}
|
||||
file->private_data = dvbdev;
|
||||
replace_fops(file, new_fops);
|
||||
if (file->f_op->open)
|
||||
err = file->f_op->open(inode, file);
|
||||
if (err) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = fops_get(old_fops);
|
||||
}
|
||||
fops_put(old_fops);
|
||||
up_read(&minor_rwsem);
|
||||
mutex_unlock(&dvbdev_mutex);
|
||||
return err;
|
||||
@ -188,26 +188,266 @@ skip:
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
static void dvb_media_device_free(struct dvb_device *dvbdev)
|
||||
{
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
if (dvbdev->entity) {
|
||||
media_device_unregister_entity(dvbdev->entity);
|
||||
kfree(dvbdev->entity);
|
||||
kfree(dvbdev->pads);
|
||||
dvbdev->entity = NULL;
|
||||
dvbdev->pads = NULL;
|
||||
}
|
||||
|
||||
if (dvbdev->tsout_entity) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dvbdev->tsout_num_entities; i++) {
|
||||
media_device_unregister_entity(&dvbdev->tsout_entity[i]);
|
||||
kfree(dvbdev->tsout_entity[i].name);
|
||||
}
|
||||
kfree(dvbdev->tsout_entity);
|
||||
kfree(dvbdev->tsout_pads);
|
||||
dvbdev->tsout_entity = NULL;
|
||||
dvbdev->tsout_pads = NULL;
|
||||
|
||||
dvbdev->tsout_num_entities = 0;
|
||||
}
|
||||
|
||||
if (dvbdev->intf_devnode) {
|
||||
media_devnode_remove(dvbdev->intf_devnode);
|
||||
dvbdev->intf_devnode = NULL;
|
||||
}
|
||||
|
||||
if (dvbdev->adapter->conn) {
|
||||
media_device_unregister_entity(dvbdev->adapter->conn);
|
||||
dvbdev->adapter->conn = NULL;
|
||||
kfree(dvbdev->adapter->conn_pads);
|
||||
dvbdev->adapter->conn_pads = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
||||
const char *name, int npads)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->tsout_pads)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->tsout_entity)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->tsout_num_entities = npads;
|
||||
|
||||
for (i = 0; i < npads; i++) {
|
||||
struct media_pad *pads = &dvbdev->tsout_pads[i];
|
||||
struct media_entity *entity = &dvbdev->tsout_entity[i];
|
||||
|
||||
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
|
||||
if (!entity->name)
|
||||
return -ENOMEM;
|
||||
|
||||
entity->function = MEDIA_ENT_F_IO_DTV;
|
||||
pads->flags = MEDIA_PAD_FL_SINK;
|
||||
|
||||
ret = media_entity_pads_init(entity, 1, pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = media_device_register_entity(dvbdev->adapter->mdev,
|
||||
entity);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEMUX_TSOUT "demux-tsout"
|
||||
#define DVR_TSOUT "dvr-tsout"
|
||||
|
||||
static int dvb_create_media_entity(struct dvb_device *dvbdev,
|
||||
int type, int demux_sink_pads)
|
||||
{
|
||||
int i, ret, npads;
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
npads = 2;
|
||||
break;
|
||||
case DVB_DEVICE_DVR:
|
||||
ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT,
|
||||
demux_sink_pads);
|
||||
return ret;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
npads = 1 + demux_sink_pads;
|
||||
ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT,
|
||||
demux_sink_pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
npads = 2;
|
||||
break;
|
||||
case DVB_DEVICE_NET:
|
||||
/*
|
||||
* We should be creating entities for the MPE/ULE
|
||||
* decapsulation hardware (or software implementation).
|
||||
*
|
||||
* However, the number of for the MPE/ULE decaps may not be
|
||||
* fixed. As we don't have yet dynamic support for PADs at
|
||||
* the Media Controller, let's not create the decap
|
||||
* entities yet.
|
||||
*/
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
|
||||
if (!dvbdev->entity)
|
||||
return -ENOMEM;
|
||||
|
||||
dvbdev->entity->name = dvbdev->name;
|
||||
|
||||
if (npads) {
|
||||
dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
|
||||
GFP_KERNEL);
|
||||
if (!dvbdev->pads)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
for (i = 1; i < npads; i++)
|
||||
dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
dvbdev->entity->function = MEDIA_ENT_F_DTV_CA;
|
||||
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
|
||||
dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
|
||||
break;
|
||||
default:
|
||||
/* Should never happen, as the first switch prevents it */
|
||||
kfree(dvbdev->entity);
|
||||
kfree(dvbdev->pads);
|
||||
dvbdev->entity = NULL;
|
||||
dvbdev->pads = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (npads) {
|
||||
ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = media_device_register_entity(dvbdev->adapter->mdev,
|
||||
dvbdev->entity);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pr_info("%s: media entity '%s' registered.\n",
|
||||
__func__, dvbdev->entity->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dvb_register_media_device(struct dvb_device *dvbdev,
|
||||
int type, int minor,
|
||||
unsigned demux_sink_pads)
|
||||
{
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
struct media_link *link;
|
||||
u32 intf_type;
|
||||
int ret;
|
||||
|
||||
if (!dvbdev->adapter->mdev)
|
||||
return 0;
|
||||
|
||||
ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (type) {
|
||||
case DVB_DEVICE_FRONTEND:
|
||||
intf_type = MEDIA_INTF_T_DVB_FE;
|
||||
break;
|
||||
case DVB_DEVICE_DEMUX:
|
||||
intf_type = MEDIA_INTF_T_DVB_DEMUX;
|
||||
break;
|
||||
case DVB_DEVICE_DVR:
|
||||
intf_type = MEDIA_INTF_T_DVB_DVR;
|
||||
break;
|
||||
case DVB_DEVICE_CA:
|
||||
intf_type = MEDIA_INTF_T_DVB_CA;
|
||||
break;
|
||||
case DVB_DEVICE_NET:
|
||||
intf_type = MEDIA_INTF_T_DVB_NET;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
|
||||
intf_type, 0,
|
||||
DVB_MAJOR, minor);
|
||||
|
||||
if (!dvbdev->intf_devnode)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Create the "obvious" link, e. g. the ones that represent
|
||||
* a direct association between an interface and an entity.
|
||||
* Other links should be created elsewhere, like:
|
||||
* DVB FE intf -> tuner
|
||||
* DVB demux intf -> dvr
|
||||
*/
|
||||
|
||||
if (!dvbdev->entity)
|
||||
return 0;
|
||||
|
||||
link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
const struct dvb_device *template, void *priv, int type)
|
||||
const struct dvb_device *template, void *priv, int type,
|
||||
int demux_sink_pads)
|
||||
{
|
||||
struct dvb_device *dvbdev;
|
||||
struct file_operations *dvbdevfops;
|
||||
struct device *clsdev;
|
||||
int minor;
|
||||
int id;
|
||||
int id, ret;
|
||||
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
|
||||
if ((id = dvbdev_get_free_id (adap, type)) < 0){
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
*pdvbdev = NULL;
|
||||
printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
|
||||
pr_err("%s: couldn't find free device id\n", __func__);
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
|
||||
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
|
||||
|
||||
if (!dvbdev){
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
@ -256,18 +496,30 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
dvb_minors[minor] = dvbdev;
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
||||
if (ret) {
|
||||
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
|
||||
__func__);
|
||||
|
||||
dvb_media_device_free(dvbdev);
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
clsdev = device_create(dvb_class, adap->device,
|
||||
MKDEV(DVB_MAJOR, minor),
|
||||
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
if (IS_ERR(clsdev)) {
|
||||
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
|
||||
return PTR_ERR(clsdev);
|
||||
}
|
||||
|
||||
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
adap->num, dnames[type], id, minor, minor);
|
||||
|
||||
return 0;
|
||||
@ -275,7 +527,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
EXPORT_SYMBOL(dvb_register_device);
|
||||
|
||||
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
void dvb_remove_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (!dvbdev)
|
||||
return;
|
||||
@ -284,14 +536,244 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
dvb_minors[dvbdev->minor] = NULL;
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
dvb_media_device_free(dvbdev);
|
||||
|
||||
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
|
||||
|
||||
list_del (&dvbdev->list_head);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_remove_device);
|
||||
|
||||
|
||||
void dvb_free_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (!dvbdev)
|
||||
return;
|
||||
|
||||
kfree (dvbdev->fops);
|
||||
kfree (dvbdev);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_free_device);
|
||||
|
||||
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
dvb_remove_device(dvbdev);
|
||||
dvb_free_device(dvbdev);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_device);
|
||||
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
|
||||
static int dvb_create_io_intf_links(struct dvb_adapter *adap,
|
||||
struct media_interface *intf,
|
||||
char *name)
|
||||
{
|
||||
struct media_device *mdev = adap->mdev;
|
||||
struct media_entity *entity;
|
||||
struct media_link *link;
|
||||
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
if (entity->function == MEDIA_ENT_F_IO_DTV) {
|
||||
if (strncmp(entity->name, name, strlen(name)))
|
||||
continue;
|
||||
link = media_create_intf_link(entity, intf,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
bool create_rf_connector)
|
||||
{
|
||||
struct media_device *mdev = adap->mdev;
|
||||
struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn;
|
||||
struct media_entity *demux = NULL, *ca = NULL;
|
||||
struct media_link *link;
|
||||
struct media_interface *intf;
|
||||
unsigned demux_pad = 0;
|
||||
unsigned dvr_pad = 0;
|
||||
unsigned ntuner = 0, ndemod = 0;
|
||||
int ret;
|
||||
static const char *connector_name = "Television";
|
||||
|
||||
if (!mdev)
|
||||
return 0;
|
||||
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
switch (entity->function) {
|
||||
case MEDIA_ENT_F_TUNER:
|
||||
tuner = entity;
|
||||
ntuner++;
|
||||
break;
|
||||
case MEDIA_ENT_F_DTV_DEMOD:
|
||||
demod = entity;
|
||||
ndemod++;
|
||||
break;
|
||||
case MEDIA_ENT_F_TS_DEMUX:
|
||||
demux = entity;
|
||||
break;
|
||||
case MEDIA_ENT_F_DTV_CA:
|
||||
ca = entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare to signalize to media_create_pad_links() that multiple
|
||||
* entities of the same type exists and a 1:n or n:1 links need to be
|
||||
* created.
|
||||
* NOTE: if both tuner and demod have multiple instances, it is up
|
||||
* to the caller driver to create such links.
|
||||
*/
|
||||
if (ntuner > 1)
|
||||
tuner = NULL;
|
||||
if (ndemod > 1)
|
||||
demod = NULL;
|
||||
|
||||
if (create_rf_connector) {
|
||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||
if (!conn)
|
||||
return -ENOMEM;
|
||||
adap->conn = conn;
|
||||
|
||||
adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL);
|
||||
if (!adap->conn_pads)
|
||||
return -ENOMEM;
|
||||
|
||||
conn->flags = MEDIA_ENT_FL_CONNECTOR;
|
||||
conn->function = MEDIA_ENT_F_CONN_RF;
|
||||
conn->name = connector_name;
|
||||
adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
ret = media_entity_pads_init(conn, 1, adap->conn_pads);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = media_device_register_entity(mdev, conn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ntuner)
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_CONN_RF,
|
||||
conn, 0,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 0,
|
||||
MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
else
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_CONN_RF,
|
||||
conn, 0,
|
||||
MEDIA_ENT_F_TUNER,
|
||||
tuner, TUNER_PAD_RF_INPUT,
|
||||
MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ntuner && ndemod) {
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_TUNER,
|
||||
tuner, TUNER_PAD_OUTPUT,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 0, MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ndemod && demux) {
|
||||
ret = media_create_pad_links(mdev,
|
||||
MEDIA_ENT_F_DTV_DEMOD,
|
||||
demod, 1,
|
||||
MEDIA_ENT_F_TS_DEMUX,
|
||||
demux, 0, MEDIA_LNK_FL_ENABLED,
|
||||
false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (demux && ca) {
|
||||
ret = media_create_pad_link(demux, 1, ca,
|
||||
0, MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create demux links for each ringbuffer/pad */
|
||||
if (demux) {
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
if (entity->function == MEDIA_ENT_F_IO_DTV) {
|
||||
if (!strncmp(entity->name, DVR_TSOUT,
|
||||
strlen(DVR_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++dvr_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!strncmp(entity->name, DEMUX_TSOUT,
|
||||
strlen(DEMUX_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++demux_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create interface links for FE->tuner, DVR->demux and CA->ca */
|
||||
media_device_for_each_intf(intf, mdev) {
|
||||
if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
|
||||
link = media_create_intf_link(ca, intf,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
|
||||
link = media_create_intf_link(tuner, intf,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* Indirect link - let's not create yet, as we don't know how
|
||||
* to handle indirect links, nor if this will
|
||||
* actually be needed.
|
||||
*/
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
|
||||
link = media_create_intf_link(demux, intf,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DVR) {
|
||||
ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (intf->type == MEDIA_INTF_T_DVB_DEMUX) {
|
||||
ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dvb_create_media_graph);
|
||||
#endif
|
||||
|
||||
static int dvbdev_check_free_adapter_num(int num)
|
||||
{
|
||||
struct list_head *entry;
|
||||
@ -347,7 +829,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
memset (adap, 0, sizeof(struct dvb_adapter));
|
||||
INIT_LIST_HEAD (&adap->device_list);
|
||||
|
||||
printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
|
||||
pr_info("DVB: registering new adapter (%s)\n", name);
|
||||
|
||||
adap->num = num;
|
||||
adap->name = name;
|
||||
@ -419,11 +901,8 @@ int dvb_usercopy(struct file *file,
|
||||
}
|
||||
|
||||
/* call driver */
|
||||
/* this lock is much too coarse */
|
||||
//mutex_lock(&dvbdev_mutex);
|
||||
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
|
||||
err = -ENOTTY;
|
||||
//mutex_unlock(&dvbdev_mutex);
|
||||
|
||||
if (err < 0)
|
||||
goto out;
|
||||
@ -454,11 +933,7 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
|
||||
static char *dvb_devnode(struct device *dev, mode_t *mode)
|
||||
#else
|
||||
static char *dvb_devnode(struct device *dev, umode_t *mode)
|
||||
#endif
|
||||
{
|
||||
struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||
|
||||
@ -473,13 +948,13 @@ static int __init init_dvbdev(void)
|
||||
dev_t dev = MKDEV(DVB_MAJOR, 0);
|
||||
|
||||
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
|
||||
printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
|
||||
pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
|
||||
return retval;
|
||||
}
|
||||
|
||||
cdev_init(&dvb_device_cdev, &dvb_device_fops);
|
||||
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
|
||||
printk(KERN_ERR "dvb-core: unable register character device\n");
|
||||
pr_err("dvb-core: unable register character device\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DVBDEV_H_
|
||||
@ -27,6 +23,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <media/media-device.h>
|
||||
|
||||
#define DVB_MAJOR 212
|
||||
|
||||
@ -60,6 +57,28 @@
|
||||
|
||||
struct dvb_frontend;
|
||||
|
||||
/**
|
||||
* struct dvb_adapter - represents a Digital TV adapter using Linux DVB API
|
||||
*
|
||||
* @num: Number of the adapter
|
||||
* @list_head: List with the DVB adapters
|
||||
* @device_list: List with the DVB devices
|
||||
* @name: Name of the adapter
|
||||
* @proposed_mac: proposed MAC address for the adapter
|
||||
* @priv: private data
|
||||
* @device: pointer to struct device
|
||||
* @module: pointer to struct module
|
||||
* @mfe_shared: mfe shared: indicates mutually exclusive frontends
|
||||
* Thie usage of this flag is currently deprecated
|
||||
* @mfe_dvbdev: Frontend device in use, in the case of MFE
|
||||
* @mfe_lock: Lock to prevent using the other frontends when MFE is
|
||||
* used.
|
||||
* @mdev: pointer to struct media_device, used when the media
|
||||
* controller is used.
|
||||
* @conn: RF connector. Used only if the device has no separate
|
||||
* tuner.
|
||||
* @conn_pads: pointer to struct media_pad associated with @conn;
|
||||
*/
|
||||
struct dvb_adapter {
|
||||
int num;
|
||||
struct list_head list_head;
|
||||
@ -75,9 +94,47 @@ struct dvb_adapter {
|
||||
int mfe_shared; /* indicates mutually exclusive frontends */
|
||||
struct dvb_device *mfe_dvbdev; /* frontend device in use */
|
||||
struct mutex mfe_lock; /* access lock for thread creation */
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
struct media_device *mdev;
|
||||
struct media_entity *conn;
|
||||
struct media_pad *conn_pads;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct dvb_device - represents a DVB device node
|
||||
*
|
||||
* @list_head: List head with all DVB devices
|
||||
* @fops: pointer to struct file_operations
|
||||
* @adapter: pointer to the adapter that holds this device node
|
||||
* @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND,
|
||||
* DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET
|
||||
* @minor: devnode minor number. Major number is always DVB_MAJOR.
|
||||
* @id: device ID number, inside the adapter
|
||||
* @readers: Initialized by the caller. Each call to open() in Read Only mode
|
||||
* decreases this counter by one.
|
||||
* @writers: Initialized by the caller. Each call to open() in Read/Write
|
||||
* mode decreases this counter by one.
|
||||
* @users: Initialized by the caller. Each call to open() in any mode
|
||||
* decreases this counter by one.
|
||||
* @wait_queue: wait queue, used to wait for certain events inside one of
|
||||
* the DVB API callers
|
||||
* @kernel_ioctl: callback function used to handle ioctl calls from userspace.
|
||||
* @name: Name to be used for the device at the Media Controller
|
||||
* @entity: pointer to struct media_entity associated with the device node
|
||||
* @pads: pointer to struct media_pad associated with @entity;
|
||||
* @priv: private data
|
||||
* @intf_devnode: Pointer to media_intf_devnode. Used by the dvbdev core to
|
||||
* store the MC device node interface
|
||||
* @tsout_num_entities: Number of Transport Stream output entities
|
||||
* @tsout_entity: array with MC entities associated to each TS output node
|
||||
* @tsout_pads: array with the source pads for each @tsout_entity
|
||||
*
|
||||
* This structure is used by the DVB core (frontend, CA, net, demux) in
|
||||
* order to create the device nodes. Usually, driver should not initialize
|
||||
* this struct diretly.
|
||||
*/
|
||||
struct dvb_device {
|
||||
struct list_head list_head;
|
||||
const struct file_operations *fops;
|
||||
@ -96,33 +153,144 @@ struct dvb_device {
|
||||
/* don't really need those !? -- FIXME: use video_usercopy */
|
||||
int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
|
||||
|
||||
/* Needed for media controller register/unregister */
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
const char *name;
|
||||
|
||||
/* Allocated and filled inside dvbdev.c */
|
||||
struct media_intf_devnode *intf_devnode;
|
||||
|
||||
unsigned tsout_num_entities;
|
||||
struct media_entity *entity, *tsout_entity;
|
||||
struct media_pad *pads, *tsout_pads;
|
||||
#endif
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
||||
extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
/**
|
||||
* dvb_register_adapter - Registers a new DVB adapter
|
||||
*
|
||||
* @adap: pointer to struct dvb_adapter
|
||||
* @name: Adapter's name
|
||||
* @module: initialized with THIS_MODULE at the caller
|
||||
* @device: pointer to struct device that corresponds to the device driver
|
||||
* @adapter_nums: Array with a list of the numbers for @dvb_register_adapter;
|
||||
* to select among them. Typically, initialized with:
|
||||
* DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums)
|
||||
*/
|
||||
int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
struct module *module, struct device *device,
|
||||
short *adapter_nums);
|
||||
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
|
||||
|
||||
extern int dvb_register_device (struct dvb_adapter *adap,
|
||||
/**
|
||||
* dvb_unregister_adapter - Unregisters a DVB adapter
|
||||
*
|
||||
* @adap: pointer to struct dvb_adapter
|
||||
*/
|
||||
int dvb_unregister_adapter(struct dvb_adapter *adap);
|
||||
|
||||
/**
|
||||
* dvb_register_device - Registers a new DVB device
|
||||
*
|
||||
* @adap: pointer to struct dvb_adapter
|
||||
* @pdvbdev: pointer to the place where the new struct dvb_device will be
|
||||
* stored
|
||||
* @template: Template used to create &pdvbdev;
|
||||
* @priv: private data
|
||||
* @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND,
|
||||
* %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA,
|
||||
* %DVB_DEVICE_NET
|
||||
* @demux_sink_pads: Number of demux outputs, to be used to create the TS
|
||||
* outputs via the Media Controller.
|
||||
*/
|
||||
int dvb_register_device(struct dvb_adapter *adap,
|
||||
struct dvb_device **pdvbdev,
|
||||
const struct dvb_device *template,
|
||||
void *priv,
|
||||
int type);
|
||||
int type,
|
||||
int demux_sink_pads);
|
||||
|
||||
extern void dvb_unregister_device (struct dvb_device *dvbdev);
|
||||
/**
|
||||
* dvb_remove_device - Remove a registered DVB device
|
||||
*
|
||||
* This does not free memory. To do that, call dvb_free_device().
|
||||
*
|
||||
* @dvbdev: pointer to struct dvb_device
|
||||
*/
|
||||
void dvb_remove_device(struct dvb_device *dvbdev);
|
||||
|
||||
extern int dvb_generic_open (struct inode *inode, struct file *file);
|
||||
extern int dvb_generic_release (struct inode *inode, struct file *file);
|
||||
extern long dvb_generic_ioctl (struct file *file,
|
||||
/**
|
||||
* dvb_free_device - Free memory occupied by a DVB device.
|
||||
*
|
||||
* Call dvb_unregister_device() before calling this function.
|
||||
*
|
||||
* @dvbdev: pointer to struct dvb_device
|
||||
*/
|
||||
void dvb_free_device(struct dvb_device *dvbdev);
|
||||
|
||||
/**
|
||||
* dvb_unregister_device - Unregisters a DVB device
|
||||
*
|
||||
* This is a combination of dvb_remove_device() and dvb_free_device().
|
||||
* Using this function is usually a mistake, and is often an indicator
|
||||
* for a use-after-free bug (when a userspace process keeps a file
|
||||
* handle to a detached device).
|
||||
*
|
||||
* @dvbdev: pointer to struct dvb_device
|
||||
*/
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev);
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
/**
|
||||
* dvb_create_media_graph - Creates media graph for the Digital TV part of the
|
||||
* device.
|
||||
*
|
||||
* @adap: pointer to struct dvb_adapter
|
||||
* @create_rf_connector: if true, it creates the RF connector too
|
||||
*
|
||||
* This function checks all DVB-related functions at the media controller
|
||||
* entities and creates the needed links for the media graph. It is
|
||||
* capable of working with multiple tuners or multiple frontends, but it
|
||||
* won't create links if the device has multiple tuners and multiple frontends
|
||||
* or if the device has multiple muxes. In such case, the caller driver should
|
||||
* manually create the remaining links.
|
||||
*/
|
||||
__must_check int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
bool create_rf_connector);
|
||||
|
||||
static inline void dvb_register_media_controller(struct dvb_adapter *adap,
|
||||
struct media_device *mdev)
|
||||
{
|
||||
adap->mdev = mdev;
|
||||
}
|
||||
|
||||
static inline struct media_device
|
||||
*dvb_get_media_controller(struct dvb_adapter *adap)
|
||||
{
|
||||
return adap->mdev;
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
bool create_rf_connector)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
#define dvb_register_media_controller(a, b) {}
|
||||
#define dvb_get_media_controller(a) NULL
|
||||
#endif
|
||||
|
||||
int dvb_generic_open (struct inode *inode, struct file *file);
|
||||
int dvb_generic_release (struct inode *inode, struct file *file);
|
||||
long dvb_generic_ioctl (struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* we don't mess with video_usercopy() any more,
|
||||
we simply define out own dvb_usercopy(), which will hopefully become
|
||||
generic_usercopy() someday... */
|
||||
|
||||
extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
int (*func)(struct file *file, unsigned int cmd, void *arg));
|
||||
|
||||
/** generic DVB attach function. */
|
||||
@ -140,11 +308,15 @@ extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
__r; \
|
||||
})
|
||||
|
||||
#define dvb_detach(FUNC) symbol_put_addr(FUNC)
|
||||
|
||||
#else
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
FUNCTION(ARGS); \
|
||||
})
|
||||
|
||||
#define dvb_detach(FUNC) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _DVBDEV_H_ */
|
||||
|
@ -1679,7 +1679,7 @@ static int get_stats(struct dvb_frontend *fe)
|
||||
}
|
||||
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct cxd_state *state = fe->demodulator_priv;
|
||||
u8 rdata;
|
||||
@ -2191,7 +2191,7 @@ static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, fe_status_t *status)
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
struct cxd_state *state = fe->demodulator_priv;
|
||||
int r;
|
||||
@ -2217,7 +2217,7 @@ static enum dvbfe_search search(struct dvb_frontend *fe)
|
||||
{
|
||||
int r;
|
||||
u32 loops = 20, i;
|
||||
fe_status_t status;
|
||||
enum fe_status status;
|
||||
|
||||
r = set_parameters(fe);
|
||||
|
||||
@ -2241,10 +2241,9 @@ static int get_algo(struct dvb_frontend *fe)
|
||||
return DVBFE_ALGO_HW;
|
||||
}
|
||||
|
||||
static int get_fe_t2(struct cxd_state *state)
|
||||
static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct dvb_frontend *fe = &state->frontend;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u8 ofdm[5], modcod[2];
|
||||
|
||||
freeze_regst(state);
|
||||
@ -2345,10 +2344,9 @@ static int get_fe_t2(struct cxd_state *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_fe_t(struct cxd_state *state)
|
||||
static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct dvb_frontend *fe = &state->frontend;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u8 tps[7];
|
||||
|
||||
read_tps(state, tps);
|
||||
@ -2447,10 +2445,9 @@ static int get_fe_t(struct cxd_state *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_fe_c(struct cxd_state *state)
|
||||
static int get_fe_c(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct dvb_frontend *fe = &state->frontend;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u8 qam;
|
||||
|
||||
freeze_regst(state);
|
||||
@ -2460,7 +2457,7 @@ static int get_fe_c(struct cxd_state *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe)
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct cxd_state *state = fe->demodulator_priv;
|
||||
|
||||
@ -2469,13 +2466,13 @@ static int get_frontend(struct dvb_frontend *fe)
|
||||
|
||||
switch (state->state) {
|
||||
case ActiveT:
|
||||
get_fe_t(state);
|
||||
get_fe_t(state, p);
|
||||
break;
|
||||
case ActiveT2:
|
||||
get_fe_t2(state);
|
||||
get_fe_t2(state, p);
|
||||
break;
|
||||
case ActiveC:
|
||||
get_fe_c(state);
|
||||
get_fe_c(state, p);
|
||||
break;
|
||||
case ActiveC2:
|
||||
break;
|
||||
|
@ -4892,14 +4892,14 @@ static int drxk_set_parameters (struct dvb_frontend *fe,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drxk_c_get_frontend(struct dvb_frontend *fe)
|
||||
static int drxk_c_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
//struct drxk_state *state = fe->demodulator_priv;
|
||||
//printk("%s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int drxk_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct drxk_state *state = fe->demodulator_priv;
|
||||
u32 stat;
|
||||
@ -4986,7 +4986,7 @@ static int drxk_t_sleep(struct dvb_frontend* fe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drxk_t_get_frontend(struct dvb_frontend *fe)
|
||||
static int drxk_t_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
//struct drxk_state *state = fe->demodulator_priv;
|
||||
//printk("%s\n", __FUNCTION__);
|
||||
|
@ -62,7 +62,7 @@ static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len)
|
||||
}
|
||||
|
||||
static int lnbh25_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
enum fe_sec_voltage voltage)
|
||||
{
|
||||
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
|
||||
u8 oldreg0 = lnbh->reg[0];
|
||||
@ -107,7 +107,7 @@ static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
}
|
||||
|
||||
static int lnbh25_set_tone(struct dvb_frontend *fe,
|
||||
fe_sec_tone_mode_t tone)
|
||||
enum fe_sec_tone_mode tone)
|
||||
{
|
||||
/* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */
|
||||
|
||||
|
@ -45,7 +45,7 @@ struct lnbp21 {
|
||||
};
|
||||
|
||||
static int lnbp21_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
enum fe_sec_voltage voltage)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
|
||||
@ -98,7 +98,7 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
}
|
||||
|
||||
static int lnbp21_set_tone(struct dvb_frontend *fe,
|
||||
fe_sec_tone_mode_t tone)
|
||||
enum fe_sec_tone_mode tone)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
|
||||
|
@ -560,7 +560,7 @@ static int set_parameters(struct dvb_frontend *fe)
|
||||
|
||||
static int get_stats(struct dvb_frontend *fe);
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
|
||||
@ -582,10 +582,10 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, fe_status_t *status)
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
/* struct dtv_frontend_properties *p = &fe->dtv_property_cache; */
|
||||
int r = 0;
|
||||
|
||||
*delay = HZ / 2;
|
||||
@ -659,7 +659,7 @@ static int read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u32 reg[8], reg2[4], n = 0, d = 0;
|
||||
u32 reg[8], reg2[4];
|
||||
int stat;
|
||||
|
||||
*ber = 0;
|
||||
@ -748,7 +748,7 @@ static int get_stats(struct dvb_frontend *fe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static fe_code_rate_t conv_fec(MXL_HYDRA_FEC_E fec)
|
||||
static enum fe_code_rate conv_fec(MXL_HYDRA_FEC_E fec)
|
||||
{
|
||||
enum fe_code_rate fec2fec[11] = {
|
||||
FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3,
|
||||
@ -761,10 +761,9 @@ static fe_code_rate_t conv_fec(MXL_HYDRA_FEC_E fec)
|
||||
return fec2fec[fec];
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe)
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct mxl *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u32 regData[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE];
|
||||
u32 freq;
|
||||
int stat;
|
||||
|
@ -58,7 +58,7 @@ enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted };
|
||||
|
||||
struct stv_state {
|
||||
struct dvb_frontend frontend;
|
||||
fe_modulation_t modulation;
|
||||
enum fe_modulation modulation;
|
||||
u32 symbol_rate;
|
||||
u32 bandwidth;
|
||||
struct device *dev;
|
||||
@ -1861,7 +1861,7 @@ static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus,
|
||||
|
||||
#endif
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct stv_state *state = fe->demodulator_priv;
|
||||
*status=0;
|
||||
|
@ -5072,10 +5072,9 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
|
||||
return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
|
||||
}
|
||||
|
||||
static int stv090x_get_frontend(struct dvb_frontend *fe)
|
||||
static int stv090x_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct stv090x_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u8 tmp;
|
||||
u32 reg = 0;
|
||||
|
||||
|
@ -849,10 +849,12 @@ static int init_search_param(struct stv *state)
|
||||
|
||||
read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp);
|
||||
tmp |= 0x20; // Filter_en (no effect if SIS=non-MIS
|
||||
tmp &= ~0x20; // Filter_en (no effect if SIS=non-MIS
|
||||
write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp);
|
||||
|
||||
read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, &tmp);
|
||||
tmp &= ~0x02; // frame mode = 0
|
||||
tmp |= 0x80; // frame mode = 0
|
||||
write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, tmp);
|
||||
|
||||
write_reg(state, RSTV0910_P2_UPLCCST0 + state->regoff, 0xe0);
|
||||
@ -1260,10 +1262,9 @@ static int get_frequency_offset(struct stv *state, s32 *off)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_frontend(struct dvb_frontend *fe)
|
||||
static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||
{
|
||||
struct stv *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
u8 tmp;
|
||||
|
||||
if (state->receive_mode == RCVMODE_DVBS2) {
|
||||
@ -1345,7 +1346,7 @@ static int read_snr(struct dvb_frontend *fe, u16 *snr);
|
||||
static int read_signal_strength(struct dvb_frontend *fe, u16 *strength);
|
||||
static int read_ber(struct dvb_frontend *fe, u32 *ber);
|
||||
|
||||
static int read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
{
|
||||
struct stv *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
@ -1528,7 +1529,7 @@ get_stat:
|
||||
|
||||
static int tune(struct dvb_frontend *fe, bool re_tune,
|
||||
unsigned int mode_flags,
|
||||
unsigned int *delay, fe_status_t *status)
|
||||
unsigned int *delay, enum fe_status *status)
|
||||
{
|
||||
struct stv *state = fe->demodulator_priv;
|
||||
int r;
|
||||
@ -1554,7 +1555,7 @@ static int get_algo(struct dvb_frontend *fe)
|
||||
return DVBFE_ALGO_HW;
|
||||
}
|
||||
|
||||
static int set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
|
||||
static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
|
||||
{
|
||||
struct stv *state = fe->demodulator_priv;
|
||||
u16 offs = state->nr ? 0x40 : 0;
|
||||
@ -1608,7 +1609,7 @@ static int recv_slave_reply(struct dvb_frontend *fe,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
|
||||
static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
||||
{
|
||||
#if 0
|
||||
struct stv *state = fe->demodulator_priv;
|
||||
|
@ -32,6 +32,9 @@
|
||||
#include "stv6110x.h"
|
||||
#include "stv6110x_priv.h"
|
||||
|
||||
/* Max transfer size done by I2C transfer functions */
|
||||
#define MAX_XFER_SIZE 64
|
||||
|
||||
static unsigned int verbose;
|
||||
module_param(verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "Set Verbosity level");
|
||||
@ -61,7 +64,8 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da
|
||||
{
|
||||
int ret;
|
||||
const struct stv6110x_config *config = stv6110x->config;
|
||||
u8 buf[len + 1];
|
||||
u8 buf[MAX_XFER_SIZE];
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = config->addr,
|
||||
.flags = 0,
|
||||
@ -69,6 +73,13 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da
|
||||
.len = len + 1
|
||||
};
|
||||
|
||||
if (1 + len > sizeof(buf)) {
|
||||
printk(KERN_WARNING
|
||||
"%s: i2c wr: len=%d is too big!\n",
|
||||
KBUILD_MODNAME, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (start + len > 8)
|
||||
return -EINVAL;
|
||||
|
||||
@ -324,17 +335,15 @@ static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
|
||||
}
|
||||
|
||||
|
||||
static int stv6110x_release(struct dvb_frontend *fe)
|
||||
static void stv6110x_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
fe->tuner_priv = NULL;
|
||||
kfree(stv6110x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops stv6110x_ops = {
|
||||
static const struct dvb_tuner_ops stv6110x_ops = {
|
||||
.info = {
|
||||
.name = "STV6110(A) Silicon Tuner",
|
||||
.frequency_min = 950000,
|
||||
@ -344,7 +353,7 @@ static struct dvb_tuner_ops stv6110x_ops = {
|
||||
.release = stv6110x_release
|
||||
};
|
||||
|
||||
static struct stv6110x_devctl stv6110x_ctl = {
|
||||
static const struct stv6110x_devctl stv6110x_ctl = {
|
||||
.tuner_init = stv6110x_init,
|
||||
.tuner_sleep = stv6110x_sleep,
|
||||
.tuner_set_mode = stv6110x_set_mode,
|
||||
@ -358,7 +367,7 @@ static struct stv6110x_devctl stv6110x_ctl = {
|
||||
.tuner_get_status = stv6110x_get_status,
|
||||
};
|
||||
|
||||
struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
const struct stv6110x_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
|
@ -53,14 +53,20 @@ struct stv6110x_devctl {
|
||||
};
|
||||
|
||||
|
||||
#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
|
||||
#define IS_REACHABLE(option) (config_enabled(option) || \
|
||||
(config_enabled(option##_MODULE) && config_enabled(MODULE)))
|
||||
#endif
|
||||
|
||||
extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
#if IS_REACHABLE(CONFIG_DVB_STV6110x)
|
||||
|
||||
extern const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
const struct stv6110x_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
|
||||
#else
|
||||
static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
static inline const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
const struct stv6110x_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ struct stv6110x_state {
|
||||
const struct stv6110x_config *config;
|
||||
u8 regs[8];
|
||||
|
||||
struct stv6110x_devctl *devctl;
|
||||
const struct stv6110x_devctl *devctl;
|
||||
};
|
||||
|
||||
#endif /* __STV6110x_PRIV_H */
|
||||
|
@ -203,11 +203,10 @@ static int init(struct dvb_frontend *fe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int release(struct dvb_frontend *fe)
|
||||
static void release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_bandwidth(struct dvb_frontend *fe, u32 CutOffFrequency)
|
||||
|
@ -790,11 +790,10 @@ static int init(struct dvb_frontend *fe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int release(struct dvb_frontend *fe)
|
||||
static void release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_params(struct dvb_frontend *fe)
|
||||
|
@ -1144,11 +1144,10 @@ static int init(struct dvb_frontend *fe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int release(struct dvb_frontend *fe)
|
||||
static void release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,67 +24,131 @@
|
||||
#ifndef _DVBCA_H_
|
||||
#define _DVBCA_H_
|
||||
|
||||
/* slot interface types and info */
|
||||
/**
|
||||
* struct ca_slot_info - CA slot interface types and info.
|
||||
*
|
||||
* @num: slot number.
|
||||
* @type: slot type.
|
||||
* @flags: flags applicable to the slot.
|
||||
*
|
||||
* This struct stores the CA slot information.
|
||||
*
|
||||
* @type can be:
|
||||
*
|
||||
* - %CA_CI - CI high level interface;
|
||||
* - %CA_CI_LINK - CI link layer level interface;
|
||||
* - %CA_CI_PHYS - CI physical layer level interface;
|
||||
* - %CA_DESCR - built-in descrambler;
|
||||
* - %CA_SC -simple smart card interface.
|
||||
*
|
||||
* @flags can be:
|
||||
*
|
||||
* - %CA_CI_MODULE_PRESENT - module (or card) inserted;
|
||||
* - %CA_CI_MODULE_READY - module is ready for usage.
|
||||
*/
|
||||
|
||||
typedef struct ca_slot_info {
|
||||
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_DESCR 8 /* built-in descrambler */
|
||||
#define CA_SC 128 /* simple smart card interface */
|
||||
struct ca_slot_info {
|
||||
int num;
|
||||
int type;
|
||||
#define CA_CI 1
|
||||
#define CA_CI_LINK 2
|
||||
#define CA_CI_PHYS 4
|
||||
#define CA_DESCR 8
|
||||
#define CA_SC 128
|
||||
|
||||
unsigned int flags;
|
||||
#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
|
||||
#define CA_CI_MODULE_PRESENT 1
|
||||
#define CA_CI_MODULE_READY 2
|
||||
} ca_slot_info_t;
|
||||
};
|
||||
|
||||
|
||||
/* descrambler types and info */
|
||||
|
||||
typedef struct ca_descr_info {
|
||||
unsigned int num; /* number of available descramblers (keys) */
|
||||
unsigned int type; /* type of supported scrambling system */
|
||||
/**
|
||||
* struct ca_descr_info - descrambler types and info.
|
||||
*
|
||||
* @num: number of available descramblers (keys).
|
||||
* @type: type of supported scrambling system.
|
||||
*
|
||||
* Identifies the number of descramblers and their type.
|
||||
*
|
||||
* @type can be:
|
||||
*
|
||||
* - %CA_ECD - European Common Descrambler (ECD) hardware;
|
||||
* - %CA_NDS - Videoguard (NDS) hardware;
|
||||
* - %CA_DSS - Distributed Sample Scrambling (DSS) hardware.
|
||||
*/
|
||||
struct ca_descr_info {
|
||||
unsigned int num;
|
||||
unsigned int type;
|
||||
#define CA_ECD 1
|
||||
#define CA_NDS 2
|
||||
#define CA_DSS 4
|
||||
} ca_descr_info_t;
|
||||
};
|
||||
|
||||
typedef struct ca_caps {
|
||||
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_caps_t;
|
||||
/**
|
||||
* struct ca_caps - CA slot interface capabilities.
|
||||
*
|
||||
* @slot_num: total number of CA card and module slots.
|
||||
* @slot_type: bitmap with all supported types as defined at
|
||||
* &struct ca_slot_info (e. g. %CA_CI, %CA_CI_LINK, etc).
|
||||
* @descr_num: total number of descrambler slots (keys)
|
||||
* @descr_type: bitmap with all supported types as defined at
|
||||
* &struct ca_descr_info (e. g. %CA_ECD, %CA_NDS, etc).
|
||||
*/
|
||||
struct ca_caps {
|
||||
unsigned int slot_num;
|
||||
unsigned int slot_type;
|
||||
unsigned int descr_num;
|
||||
unsigned int descr_type;
|
||||
};
|
||||
|
||||
/* a message to/from a CI-CAM */
|
||||
typedef struct ca_msg {
|
||||
/**
|
||||
* struct ca_msg - a message to/from a CI-CAM
|
||||
*
|
||||
* @index: unused
|
||||
* @type: unused
|
||||
* @length: length of the message
|
||||
* @msg: message
|
||||
*
|
||||
* This struct carries a message to be send/received from a CI CA module.
|
||||
*/
|
||||
struct ca_msg {
|
||||
unsigned int index;
|
||||
unsigned int type;
|
||||
unsigned int length;
|
||||
unsigned char msg[256];
|
||||
} ca_msg_t;
|
||||
};
|
||||
|
||||
typedef struct ca_descr {
|
||||
/**
|
||||
* struct ca_descr - CA descrambler control words info
|
||||
*
|
||||
* @index: CA Descrambler slot
|
||||
* @parity: control words parity, where 0 means even and 1 means odd
|
||||
* @cw: CA Descrambler control words
|
||||
*/
|
||||
struct ca_descr {
|
||||
unsigned int index;
|
||||
unsigned int parity; /* 0 == even, 1 == odd */
|
||||
unsigned int parity;
|
||||
unsigned char cw[8];
|
||||
} ca_descr_t;
|
||||
|
||||
typedef struct ca_pid {
|
||||
unsigned int pid;
|
||||
int index; /* -1 == disable*/
|
||||
} ca_pid_t;
|
||||
};
|
||||
|
||||
#define CA_RESET _IO('o', 128)
|
||||
#define CA_GET_CAP _IOR('o', 129, ca_caps_t)
|
||||
#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t)
|
||||
#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
|
||||
#define CA_GET_MSG _IOR('o', 132, ca_msg_t)
|
||||
#define CA_SEND_MSG _IOW('o', 133, ca_msg_t)
|
||||
#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
|
||||
#define CA_SET_PID _IOW('o', 135, ca_pid_t)
|
||||
#define CA_GET_CAP _IOR('o', 129, struct ca_caps)
|
||||
#define CA_GET_SLOT_INFO _IOR('o', 130, struct ca_slot_info)
|
||||
#define CA_GET_DESCR_INFO _IOR('o', 131, struct ca_descr_info)
|
||||
#define CA_GET_MSG _IOR('o', 132, struct ca_msg)
|
||||
#define CA_SEND_MSG _IOW('o', 133, struct ca_msg)
|
||||
#define CA_SET_DESCR _IOW('o', 134, struct ca_descr)
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
/* This is needed for legacy userspace support */
|
||||
typedef struct ca_slot_info ca_slot_info_t;
|
||||
typedef struct ca_descr_info ca_descr_info_t;
|
||||
typedef struct ca_caps ca_caps_t;
|
||||
typedef struct ca_msg ca_msg_t;
|
||||
typedef struct ca_descr ca_descr_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -32,27 +32,74 @@
|
||||
|
||||
#define DMX_FILTER_SIZE 16
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_OUT_DECODER, /* Streaming directly to decoder. */
|
||||
DMX_OUT_TAP, /* Output going to a memory buffer */
|
||||
/* (to be retrieved via the read command).*/
|
||||
DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */
|
||||
/* (to be retrieved by reading from the */
|
||||
/* logical DVR device). */
|
||||
DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
|
||||
} dmx_output_t;
|
||||
/**
|
||||
* enum dmx_output - Output for the demux.
|
||||
*
|
||||
* @DMX_OUT_DECODER:
|
||||
* Streaming directly to decoder.
|
||||
* @DMX_OUT_TAP:
|
||||
* Output going to a memory buffer (to be retrieved via the read command).
|
||||
* Delivers the stream output to the demux device on which the ioctl
|
||||
* is called.
|
||||
* @DMX_OUT_TS_TAP:
|
||||
* Output multiplexed into a new TS (to be retrieved by reading from the
|
||||
* logical DVR device). Routes output to the logical DVR device
|
||||
* ``/dev/dvb/adapter?/dvr?``, which delivers a TS multiplexed from all
|
||||
* filters for which @DMX_OUT_TS_TAP was specified.
|
||||
* @DMX_OUT_TSDEMUX_TAP:
|
||||
* Like @DMX_OUT_TS_TAP but retrieved from the DMX device.
|
||||
*/
|
||||
enum dmx_output {
|
||||
DMX_OUT_DECODER,
|
||||
DMX_OUT_TAP,
|
||||
DMX_OUT_TS_TAP,
|
||||
DMX_OUT_TSDEMUX_TAP
|
||||
};
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_IN_FRONTEND, /* Input from a front-end device. */
|
||||
DMX_IN_DVR /* Input from the logical DVR device. */
|
||||
} dmx_input_t;
|
||||
/**
|
||||
* enum dmx_input - Input from the demux.
|
||||
*
|
||||
* @DMX_IN_FRONTEND: Input from a front-end device.
|
||||
* @DMX_IN_DVR: Input from the logical DVR device.
|
||||
*/
|
||||
enum dmx_input {
|
||||
DMX_IN_FRONTEND,
|
||||
DMX_IN_DVR
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dmx_ts_pes - type of the PES filter.
|
||||
*
|
||||
* @DMX_PES_AUDIO0: first audio PID. Also referred as @DMX_PES_AUDIO.
|
||||
* @DMX_PES_VIDEO0: first video PID. Also referred as @DMX_PES_VIDEO.
|
||||
* @DMX_PES_TELETEXT0: first teletext PID. Also referred as @DMX_PES_TELETEXT.
|
||||
* @DMX_PES_SUBTITLE0: first subtitle PID. Also referred as @DMX_PES_SUBTITLE.
|
||||
* @DMX_PES_PCR0: first Program Clock Reference PID.
|
||||
* Also referred as @DMX_PES_PCR.
|
||||
*
|
||||
* @DMX_PES_AUDIO1: second audio PID.
|
||||
* @DMX_PES_VIDEO1: second video PID.
|
||||
* @DMX_PES_TELETEXT1: second teletext PID.
|
||||
* @DMX_PES_SUBTITLE1: second subtitle PID.
|
||||
* @DMX_PES_PCR1: second Program Clock Reference PID.
|
||||
*
|
||||
* @DMX_PES_AUDIO2: third audio PID.
|
||||
* @DMX_PES_VIDEO2: third video PID.
|
||||
* @DMX_PES_TELETEXT2: third teletext PID.
|
||||
* @DMX_PES_SUBTITLE2: third subtitle PID.
|
||||
* @DMX_PES_PCR2: third Program Clock Reference PID.
|
||||
*
|
||||
* @DMX_PES_AUDIO3: fourth audio PID.
|
||||
* @DMX_PES_VIDEO3: fourth video PID.
|
||||
* @DMX_PES_TELETEXT3: fourth teletext PID.
|
||||
* @DMX_PES_SUBTITLE3: fourth subtitle PID.
|
||||
* @DMX_PES_PCR3: fourth Program Clock Reference PID.
|
||||
*
|
||||
* @DMX_PES_OTHER: any other PID.
|
||||
*/
|
||||
|
||||
typedef enum dmx_ts_pes
|
||||
{
|
||||
enum dmx_ts_pes {
|
||||
DMX_PES_AUDIO0,
|
||||
DMX_PES_VIDEO0,
|
||||
DMX_PES_TELETEXT0,
|
||||
@ -78,7 +125,7 @@ typedef enum dmx_ts_pes
|
||||
DMX_PES_PCR3,
|
||||
|
||||
DMX_PES_OTHER
|
||||
} dmx_pes_type_t;
|
||||
};
|
||||
|
||||
#define DMX_PES_AUDIO DMX_PES_AUDIO0
|
||||
#define DMX_PES_VIDEO DMX_PES_VIDEO0
|
||||
@ -87,69 +134,100 @@ typedef enum dmx_ts_pes
|
||||
#define DMX_PES_PCR DMX_PES_PCR0
|
||||
|
||||
|
||||
typedef struct dmx_filter
|
||||
{
|
||||
|
||||
/**
|
||||
* struct dmx_filter - Specifies a section header filter.
|
||||
*
|
||||
* @filter: bit array with bits to be matched at the section header.
|
||||
* @mask: bits that are valid at the filter bit array.
|
||||
* @mode: mode of match: if bit is zero, it will match if equal (positive
|
||||
* match); if bit is one, it will match if the bit is negated.
|
||||
*
|
||||
* Note: All arrays in this struct have a size of DMX_FILTER_SIZE (16 bytes).
|
||||
*/
|
||||
struct dmx_filter {
|
||||
__u8 filter[DMX_FILTER_SIZE];
|
||||
__u8 mask[DMX_FILTER_SIZE];
|
||||
__u8 mode[DMX_FILTER_SIZE];
|
||||
} dmx_filter_t;
|
||||
};
|
||||
|
||||
|
||||
struct dmx_sct_filter_params
|
||||
{
|
||||
/**
|
||||
* struct dmx_sct_filter_params - Specifies a section filter.
|
||||
*
|
||||
* @pid: PID to be filtered.
|
||||
* @filter: section header filter, as defined by &struct dmx_filter.
|
||||
* @timeout: maximum time to filter, in milliseconds.
|
||||
* @flags: extra flags for the section filter.
|
||||
*
|
||||
* Carries the configuration for a MPEG-TS section filter.
|
||||
*
|
||||
* The @flags can be:
|
||||
*
|
||||
* - %DMX_CHECK_CRC - only deliver sections where the CRC check succeeded;
|
||||
* - %DMX_ONESHOT - disable the section filter after one section
|
||||
* has been delivered;
|
||||
* - %DMX_IMMEDIATE_START - Start filter immediately without requiring a
|
||||
* :ref:`DMX_START`.
|
||||
*/
|
||||
struct dmx_sct_filter_params {
|
||||
__u16 pid;
|
||||
dmx_filter_t filter;
|
||||
struct dmx_filter filter;
|
||||
__u32 timeout;
|
||||
__u32 flags;
|
||||
#define DMX_CHECK_CRC 1
|
||||
#define DMX_ONESHOT 2
|
||||
#define DMX_IMMEDIATE_START 4
|
||||
#define DMX_KERNEL_CLIENT 0x8000
|
||||
};
|
||||
|
||||
|
||||
struct dmx_pes_filter_params
|
||||
{
|
||||
/**
|
||||
* struct dmx_pes_filter_params - Specifies Packetized Elementary Stream (PES)
|
||||
* filter parameters.
|
||||
*
|
||||
* @pid: PID to be filtered.
|
||||
* @input: Demux input, as specified by &enum dmx_input.
|
||||
* @output: Demux output, as specified by &enum dmx_output.
|
||||
* @pes_type: Type of the pes filter, as specified by &enum dmx_pes_type.
|
||||
* @flags: Demux PES flags.
|
||||
*/
|
||||
struct dmx_pes_filter_params {
|
||||
__u16 pid;
|
||||
dmx_input_t input;
|
||||
dmx_output_t output;
|
||||
dmx_pes_type_t pes_type;
|
||||
enum dmx_input input;
|
||||
enum dmx_output output;
|
||||
enum dmx_ts_pes pes_type;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
typedef struct dmx_caps {
|
||||
__u32 caps;
|
||||
int num_decoders;
|
||||
} dmx_caps_t;
|
||||
|
||||
typedef enum {
|
||||
DMX_SOURCE_FRONT0 = 0,
|
||||
DMX_SOURCE_FRONT1,
|
||||
DMX_SOURCE_FRONT2,
|
||||
DMX_SOURCE_FRONT3,
|
||||
DMX_SOURCE_DVR0 = 16,
|
||||
DMX_SOURCE_DVR1,
|
||||
DMX_SOURCE_DVR2,
|
||||
DMX_SOURCE_DVR3
|
||||
} dmx_source_t;
|
||||
|
||||
/**
|
||||
* struct dmx_stc - Stores System Time Counter (STC) information.
|
||||
*
|
||||
* @num: input data: number of the STC, from 0 to N.
|
||||
* @base: output: divisor for STC to get 90 kHz clock.
|
||||
* @stc: output: stc in @base * 90 kHz units.
|
||||
*/
|
||||
struct dmx_stc {
|
||||
unsigned int num; /* input : which STC? 0..N */
|
||||
unsigned int base; /* output: divisor for stc to get 90 kHz clock */
|
||||
__u64 stc; /* output: stc in 'base'*90 kHz units */
|
||||
unsigned int num;
|
||||
unsigned int base;
|
||||
__u64 stc;
|
||||
};
|
||||
|
||||
|
||||
#define DMX_START _IO('o', 41)
|
||||
#define DMX_STOP _IO('o', 42)
|
||||
#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
|
||||
#define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params)
|
||||
#define DMX_SET_BUFFER_SIZE _IO('o', 45)
|
||||
#define DMX_GET_PES_PIDS _IOR('o', 47, __u16[5])
|
||||
#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t)
|
||||
#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t)
|
||||
#define DMX_GET_STC _IOWR('o', 50, struct dmx_stc)
|
||||
#define DMX_ADD_PID _IOW('o', 51, __u16)
|
||||
#define DMX_REMOVE_PID _IOW('o', 52, __u16)
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
/* This is needed for legacy userspace support */
|
||||
typedef enum dmx_output dmx_output_t;
|
||||
typedef enum dmx_input dmx_input_t;
|
||||
typedef enum dmx_ts_pes dmx_pes_type_t;
|
||||
typedef struct dmx_filter dmx_filter_t;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI_DVBDMX_H_ */
|
||||
|
@ -28,15 +28,47 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
typedef enum fe_type {
|
||||
FE_QPSK,
|
||||
FE_QAM,
|
||||
FE_OFDM,
|
||||
FE_ATSC
|
||||
} fe_type_t;
|
||||
|
||||
|
||||
typedef enum fe_caps {
|
||||
/**
|
||||
* enum fe_caps - Frontend capabilities
|
||||
*
|
||||
* @FE_IS_STUPID: There's something wrong at the
|
||||
* frontend, and it can't report its
|
||||
* capabilities.
|
||||
* @FE_CAN_INVERSION_AUTO: Can auto-detect frequency spectral
|
||||
* band inversion
|
||||
* @FE_CAN_FEC_1_2: Supports FEC 1/2
|
||||
* @FE_CAN_FEC_2_3: Supports FEC 2/3
|
||||
* @FE_CAN_FEC_3_4: Supports FEC 3/4
|
||||
* @FE_CAN_FEC_4_5: Supports FEC 4/5
|
||||
* @FE_CAN_FEC_5_6: Supports FEC 5/6
|
||||
* @FE_CAN_FEC_6_7: Supports FEC 6/7
|
||||
* @FE_CAN_FEC_7_8: Supports FEC 7/8
|
||||
* @FE_CAN_FEC_8_9: Supports FEC 8/9
|
||||
* @FE_CAN_FEC_AUTO: Can auto-detect FEC
|
||||
* @FE_CAN_QPSK: Supports QPSK modulation
|
||||
* @FE_CAN_QAM_16: Supports 16-QAM modulation
|
||||
* @FE_CAN_QAM_32: Supports 32-QAM modulation
|
||||
* @FE_CAN_QAM_64: Supports 64-QAM modulation
|
||||
* @FE_CAN_QAM_128: Supports 128-QAM modulation
|
||||
* @FE_CAN_QAM_256: Supports 256-QAM modulation
|
||||
* @FE_CAN_QAM_AUTO: Can auto-detect QAM modulation
|
||||
* @FE_CAN_TRANSMISSION_MODE_AUTO: Can auto-detect transmission mode
|
||||
* @FE_CAN_BANDWIDTH_AUTO: Can auto-detect bandwidth
|
||||
* @FE_CAN_GUARD_INTERVAL_AUTO: Can auto-detect guard interval
|
||||
* @FE_CAN_HIERARCHY_AUTO: Can auto-detect hierarchy
|
||||
* @FE_CAN_8VSB: Supports 8-VSB modulation
|
||||
* @FE_CAN_16VSB: Supporta 16-VSB modulation
|
||||
* @FE_HAS_EXTENDED_CAPS: Unused
|
||||
* @FE_CAN_MULTISTREAM: Supports multistream filtering
|
||||
* @FE_CAN_TURBO_FEC: Supports "turbo FEC" modulation
|
||||
* @FE_CAN_2G_MODULATION: Supports "2nd generation" modulation,
|
||||
* e. g. DVB-S2, DVB-T2, DVB-C2
|
||||
* @FE_NEEDS_BENDING: Unused
|
||||
* @FE_CAN_RECOVER: Can recover from a cable unplug
|
||||
* automatically
|
||||
* @FE_CAN_MUTE_TS: Can stop spurious TS data output
|
||||
*/
|
||||
enum fe_caps {
|
||||
FE_IS_STUPID = 0,
|
||||
FE_CAN_INVERSION_AUTO = 0x1,
|
||||
FE_CAN_FEC_1_2 = 0x2,
|
||||
@ -61,80 +93,163 @@ typedef enum fe_caps {
|
||||
FE_CAN_HIERARCHY_AUTO = 0x100000,
|
||||
FE_CAN_8VSB = 0x200000,
|
||||
FE_CAN_16VSB = 0x400000,
|
||||
FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */
|
||||
FE_CAN_MULTISTREAM = 0x4000000, /* frontend supports multistream filtering */
|
||||
FE_CAN_TURBO_FEC = 0x8000000, /* frontend supports "turbo fec modulation" */
|
||||
FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
|
||||
FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
|
||||
FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */
|
||||
FE_CAN_MUTE_TS = 0x80000000 /* frontend can stop spurious TS data output */
|
||||
} fe_caps_t;
|
||||
FE_HAS_EXTENDED_CAPS = 0x800000,
|
||||
FE_CAN_MULTISTREAM = 0x4000000,
|
||||
FE_CAN_TURBO_FEC = 0x8000000,
|
||||
FE_CAN_2G_MODULATION = 0x10000000,
|
||||
FE_NEEDS_BENDING = 0x20000000,
|
||||
FE_CAN_RECOVER = 0x40000000,
|
||||
FE_CAN_MUTE_TS = 0x80000000
|
||||
};
|
||||
|
||||
/*
|
||||
* DEPRECATED: Should be kept just due to backward compatibility.
|
||||
*/
|
||||
enum fe_type {
|
||||
FE_QPSK,
|
||||
FE_QAM,
|
||||
FE_OFDM,
|
||||
FE_ATSC
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_frontend_info - Frontend properties and capabilities
|
||||
*
|
||||
* @name: Name of the frontend
|
||||
* @type: **DEPRECATED**.
|
||||
* Should not be used on modern programs,
|
||||
* as a frontend may have more than one type.
|
||||
* In order to get the support types of a given
|
||||
* frontend, use :c:type:`DTV_ENUM_DELSYS`
|
||||
* instead.
|
||||
* @frequency_min: Minimal frequency supported by the frontend.
|
||||
* @frequency_max: Minimal frequency supported by the frontend.
|
||||
* @frequency_stepsize: All frequencies are multiple of this value.
|
||||
* @frequency_tolerance: Frequency tolerance.
|
||||
* @symbol_rate_min: Minimal symbol rate, in bauds
|
||||
* (for Cable/Satellite systems).
|
||||
* @symbol_rate_max: Maximal symbol rate, in bauds
|
||||
* (for Cable/Satellite systems).
|
||||
* @symbol_rate_tolerance: Maximal symbol rate tolerance, in ppm
|
||||
* (for Cable/Satellite systems).
|
||||
* @notifier_delay: **DEPRECATED**. Not used by any driver.
|
||||
* @caps: Capabilities supported by the frontend,
|
||||
* as specified in &enum fe_caps.
|
||||
*
|
||||
* .. note:
|
||||
*
|
||||
* #. The frequencies are specified in Hz for Terrestrial and Cable
|
||||
* systems.
|
||||
* #. The frequencies are specified in kHz for Satellite systems.
|
||||
*/
|
||||
struct dvb_frontend_info {
|
||||
char name[128];
|
||||
fe_type_t type; /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
|
||||
enum fe_type type; /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
|
||||
__u32 frequency_min;
|
||||
__u32 frequency_max;
|
||||
__u32 frequency_stepsize;
|
||||
__u32 frequency_tolerance;
|
||||
__u32 symbol_rate_min;
|
||||
__u32 symbol_rate_max;
|
||||
__u32 symbol_rate_tolerance; /* ppm */
|
||||
__u32 symbol_rate_tolerance;
|
||||
__u32 notifier_delay; /* DEPRECATED */
|
||||
fe_caps_t caps;
|
||||
enum fe_caps caps;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct dvb_diseqc_master_cmd - DiSEqC master command
|
||||
*
|
||||
* @msg:
|
||||
* DiSEqC message to be sent. It contains a 3 bytes header with:
|
||||
* framing + address + command, and an optional argument
|
||||
* of up to 3 bytes of data.
|
||||
* @msg_len:
|
||||
* Length of the DiSEqC message. Valid values are 3 to 6.
|
||||
*
|
||||
* Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
|
||||
* the meaning of this struct...
|
||||
* the possible messages that can be used.
|
||||
*/
|
||||
struct dvb_diseqc_master_cmd {
|
||||
__u8 msg [6]; /* { framing, address, command, data [3] } */
|
||||
__u8 msg_len; /* valid values are 3...6 */
|
||||
__u8 msg[6];
|
||||
__u8 msg_len;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct dvb_diseqc_slave_reply - DiSEqC received data
|
||||
*
|
||||
* @msg:
|
||||
* DiSEqC message buffer to store a message received via DiSEqC.
|
||||
* It contains one byte header with: framing and
|
||||
* an optional argument of up to 3 bytes of data.
|
||||
* @msg_len:
|
||||
* Length of the DiSEqC message. Valid values are 0 to 4,
|
||||
* where 0 means no message.
|
||||
* @timeout:
|
||||
* Return from ioctl after timeout ms with errorcode when
|
||||
* no message was received.
|
||||
*
|
||||
* Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
|
||||
* the possible messages that can be used.
|
||||
*/
|
||||
struct dvb_diseqc_slave_reply {
|
||||
__u8 msg [4]; /* { framing, data [3] } */
|
||||
__u8 msg_len; /* valid values are 0...4, 0 means no msg */
|
||||
int timeout; /* return from ioctl after timeout ms with */
|
||||
}; /* errorcode when no message was received */
|
||||
__u8 msg[4];
|
||||
__u8 msg_len;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
|
||||
typedef enum fe_sec_voltage {
|
||||
/**
|
||||
* enum fe_sec_voltage - DC Voltage used to feed the LNBf
|
||||
*
|
||||
* @SEC_VOLTAGE_13: Output 13V to the LNBf
|
||||
* @SEC_VOLTAGE_18: Output 18V to the LNBf
|
||||
* @SEC_VOLTAGE_OFF: Don't feed the LNBf with a DC voltage
|
||||
*/
|
||||
enum fe_sec_voltage {
|
||||
SEC_VOLTAGE_13,
|
||||
SEC_VOLTAGE_18,
|
||||
SEC_VOLTAGE_OFF
|
||||
} fe_sec_voltage_t;
|
||||
|
||||
|
||||
typedef enum fe_sec_tone_mode {
|
||||
SEC_TONE_ON,
|
||||
SEC_TONE_OFF
|
||||
} fe_sec_tone_mode_t;
|
||||
|
||||
|
||||
typedef enum fe_sec_mini_cmd {
|
||||
SEC_MINI_A,
|
||||
SEC_MINI_B
|
||||
} fe_sec_mini_cmd_t;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum fe_status - enumerates the possible frontend status
|
||||
* @FE_HAS_SIGNAL: found something above the noise level
|
||||
* @FE_HAS_CARRIER: found a DVB signal
|
||||
* @FE_HAS_VITERBI: FEC is stable
|
||||
* @FE_HAS_SYNC: found sync bytes
|
||||
* @FE_HAS_LOCK: everything's working
|
||||
* @FE_TIMEDOUT: no lock within the last ~2 seconds
|
||||
* @FE_REINIT: frontend was reinitialized, application is recommended
|
||||
* to reset DiSEqC, tone and parameters
|
||||
* enum fe_sec_tone_mode - Type of tone to be send to the LNBf.
|
||||
* @SEC_TONE_ON: Sends a 22kHz tone burst to the antenna.
|
||||
* @SEC_TONE_OFF: Don't send a 22kHz tone to the antenna (except
|
||||
* if the ``FE_DISEQC_*`` ioctls are called).
|
||||
*/
|
||||
enum fe_sec_tone_mode {
|
||||
SEC_TONE_ON,
|
||||
SEC_TONE_OFF
|
||||
};
|
||||
|
||||
typedef enum fe_status {
|
||||
/**
|
||||
* enum fe_sec_mini_cmd - Type of mini burst to be sent
|
||||
*
|
||||
* @SEC_MINI_A: Sends a mini-DiSEqC 22kHz '0' Tone Burst to select
|
||||
* satellite-A
|
||||
* @SEC_MINI_B: Sends a mini-DiSEqC 22kHz '1' Data Burst to select
|
||||
* satellite-B
|
||||
*/
|
||||
enum fe_sec_mini_cmd {
|
||||
SEC_MINI_A,
|
||||
SEC_MINI_B
|
||||
};
|
||||
|
||||
/**
|
||||
* enum fe_status - Enumerates the possible frontend status.
|
||||
* @FE_NONE: The frontend doesn't have any kind of lock.
|
||||
* That's the initial frontend status
|
||||
* @FE_HAS_SIGNAL: Has found something above the noise level.
|
||||
* @FE_HAS_CARRIER: Has found a signal.
|
||||
* @FE_HAS_VITERBI: FEC inner coding (Viterbi, LDPC or other inner code).
|
||||
* is stable.
|
||||
* @FE_HAS_SYNC: Synchronization bytes was found.
|
||||
* @FE_HAS_LOCK: Digital TV were locked and everything is working.
|
||||
* @FE_TIMEDOUT: Fo lock within the last about 2 seconds.
|
||||
* @FE_REINIT: Frontend was reinitialized, application is recommended
|
||||
* to reset DiSEqC, tone and parameters.
|
||||
*/
|
||||
enum fe_status {
|
||||
FE_NONE = 0x00,
|
||||
FE_HAS_SIGNAL = 0x01,
|
||||
FE_HAS_CARRIER = 0x02,
|
||||
FE_HAS_VITERBI = 0x04,
|
||||
@ -142,16 +257,48 @@ typedef enum fe_status {
|
||||
FE_HAS_LOCK = 0x10,
|
||||
FE_TIMEDOUT = 0x20,
|
||||
FE_REINIT = 0x40,
|
||||
} fe_status_t;
|
||||
};
|
||||
|
||||
typedef enum fe_spectral_inversion {
|
||||
/**
|
||||
* enum fe_spectral_inversion - Type of inversion band
|
||||
*
|
||||
* @INVERSION_OFF: Don't do spectral band inversion.
|
||||
* @INVERSION_ON: Do spectral band inversion.
|
||||
* @INVERSION_AUTO: Autodetect spectral band inversion.
|
||||
*
|
||||
* This parameter indicates if spectral inversion should be presumed or
|
||||
* not. In the automatic setting (``INVERSION_AUTO``) the hardware will try
|
||||
* to figure out the correct setting by itself. If the hardware doesn't
|
||||
* support, the %dvb_frontend will try to lock at the carrier first with
|
||||
* inversion off. If it fails, it will try to enable inversion.
|
||||
*/
|
||||
enum fe_spectral_inversion {
|
||||
INVERSION_OFF,
|
||||
INVERSION_ON,
|
||||
INVERSION_AUTO
|
||||
} fe_spectral_inversion_t;
|
||||
};
|
||||
|
||||
|
||||
typedef enum fe_code_rate {
|
||||
/**
|
||||
* enum fe_code_rate - Type of Forward Error Correction (FEC)
|
||||
*
|
||||
*
|
||||
* @FEC_NONE: No Forward Error Correction Code
|
||||
* @FEC_1_2: Forward Error Correction Code 1/2
|
||||
* @FEC_2_3: Forward Error Correction Code 2/3
|
||||
* @FEC_3_4: Forward Error Correction Code 3/4
|
||||
* @FEC_4_5: Forward Error Correction Code 4/5
|
||||
* @FEC_5_6: Forward Error Correction Code 5/6
|
||||
* @FEC_6_7: Forward Error Correction Code 6/7
|
||||
* @FEC_7_8: Forward Error Correction Code 7/8
|
||||
* @FEC_8_9: Forward Error Correction Code 8/9
|
||||
* @FEC_AUTO: Autodetect Error Correction Code
|
||||
* @FEC_3_5: Forward Error Correction Code 3/5
|
||||
* @FEC_9_10: Forward Error Correction Code 9/10
|
||||
* @FEC_2_5: Forward Error Correction Code 2/5
|
||||
*
|
||||
* Please note that not all FEC types are supported by a given standard.
|
||||
*/
|
||||
enum fe_code_rate {
|
||||
FEC_NONE = 0,
|
||||
FEC_1_2,
|
||||
FEC_2_3,
|
||||
@ -167,10 +314,29 @@ typedef enum fe_code_rate {
|
||||
FEC_2_5,
|
||||
FEC_1_4,
|
||||
FEC_1_3,
|
||||
} fe_code_rate_t;
|
||||
};
|
||||
|
||||
|
||||
typedef enum fe_modulation {
|
||||
/**
|
||||
* enum fe_modulation - Type of modulation/constellation
|
||||
* @QPSK: QPSK modulation
|
||||
* @QAM_16: 16-QAM modulation
|
||||
* @QAM_32: 32-QAM modulation
|
||||
* @QAM_64: 64-QAM modulation
|
||||
* @QAM_128: 128-QAM modulation
|
||||
* @QAM_256: 256-QAM modulation
|
||||
* @QAM_AUTO: Autodetect QAM modulation
|
||||
* @VSB_8: 8-VSB modulation
|
||||
* @VSB_16: 16-VSB modulation
|
||||
* @PSK_8: 8-PSK modulation
|
||||
* @APSK_16: 16-APSK modulation
|
||||
* @APSK_32: 32-APSK modulation
|
||||
* @DQPSK: DQPSK modulation
|
||||
* @QAM_4_NR: 4-QAM-NR modulation
|
||||
*
|
||||
* Please note that not all modulations are supported by a given standard.
|
||||
*
|
||||
*/
|
||||
enum fe_modulation {
|
||||
QPSK,
|
||||
QAM_16,
|
||||
QAM_32,
|
||||
@ -185,9 +351,35 @@ typedef enum fe_modulation {
|
||||
APSK_32,
|
||||
DQPSK,
|
||||
QAM_4_NR,
|
||||
} fe_modulation_t;
|
||||
};
|
||||
|
||||
typedef enum fe_transmit_mode {
|
||||
/**
|
||||
* enum fe_transmit_mode - Transmission mode
|
||||
*
|
||||
* @TRANSMISSION_MODE_AUTO:
|
||||
* Autodetect transmission mode. The hardware will try to find the
|
||||
* correct FFT-size (if capable) to fill in the missing parameters.
|
||||
* @TRANSMISSION_MODE_1K:
|
||||
* Transmission mode 1K
|
||||
* @TRANSMISSION_MODE_2K:
|
||||
* Transmission mode 2K
|
||||
* @TRANSMISSION_MODE_8K:
|
||||
* Transmission mode 8K
|
||||
* @TRANSMISSION_MODE_4K:
|
||||
* Transmission mode 4K
|
||||
* @TRANSMISSION_MODE_16K:
|
||||
* Transmission mode 16K
|
||||
* @TRANSMISSION_MODE_32K:
|
||||
* Transmission mode 32K
|
||||
* @TRANSMISSION_MODE_C1:
|
||||
* Single Carrier (C=1) transmission mode (DTMB only)
|
||||
* @TRANSMISSION_MODE_C3780:
|
||||
* Multi Carrier (C=3780) transmission mode (DTMB only)
|
||||
*
|
||||
* Please note that not all transmission modes are supported by a given
|
||||
* standard.
|
||||
*/
|
||||
enum fe_transmit_mode {
|
||||
TRANSMISSION_MODE_2K,
|
||||
TRANSMISSION_MODE_8K,
|
||||
TRANSMISSION_MODE_AUTO,
|
||||
@ -198,21 +390,26 @@ typedef enum fe_transmit_mode {
|
||||
TRANSMISSION_MODE_C1,
|
||||
TRANSMISSION_MODE_C3780,
|
||||
TRANSMISSION_MODE_64K,
|
||||
} fe_transmit_mode_t;
|
||||
};
|
||||
|
||||
#if defined(__DVB_CORE__) || !defined (__KERNEL__)
|
||||
typedef enum fe_bandwidth {
|
||||
BANDWIDTH_8_MHZ,
|
||||
BANDWIDTH_7_MHZ,
|
||||
BANDWIDTH_6_MHZ,
|
||||
BANDWIDTH_AUTO,
|
||||
BANDWIDTH_5_MHZ,
|
||||
BANDWIDTH_10_MHZ,
|
||||
BANDWIDTH_1_712_MHZ,
|
||||
} fe_bandwidth_t;
|
||||
#endif
|
||||
|
||||
typedef enum fe_guard_interval {
|
||||
/**
|
||||
* enum fe_guard_interval - Guard interval
|
||||
*
|
||||
* @GUARD_INTERVAL_AUTO: Autodetect the guard interval
|
||||
* @GUARD_INTERVAL_1_128: Guard interval 1/128
|
||||
* @GUARD_INTERVAL_1_32: Guard interval 1/32
|
||||
* @GUARD_INTERVAL_1_16: Guard interval 1/16
|
||||
* @GUARD_INTERVAL_1_8: Guard interval 1/8
|
||||
* @GUARD_INTERVAL_1_4: Guard interval 1/4
|
||||
* @GUARD_INTERVAL_19_128: Guard interval 19/128
|
||||
* @GUARD_INTERVAL_19_256: Guard interval 19/256
|
||||
* @GUARD_INTERVAL_PN420: PN length 420 (1/4)
|
||||
* @GUARD_INTERVAL_PN595: PN length 595 (1/6)
|
||||
* @GUARD_INTERVAL_PN945: PN length 945 (1/9)
|
||||
*
|
||||
* Please note that not all guard intervals are supported by a given standard.
|
||||
*/
|
||||
enum fe_guard_interval {
|
||||
GUARD_INTERVAL_1_32,
|
||||
GUARD_INTERVAL_1_16,
|
||||
GUARD_INTERVAL_1_8,
|
||||
@ -224,17 +421,35 @@ typedef enum fe_guard_interval {
|
||||
GUARD_INTERVAL_PN420,
|
||||
GUARD_INTERVAL_PN595,
|
||||
GUARD_INTERVAL_PN945,
|
||||
} fe_guard_interval_t;
|
||||
};
|
||||
|
||||
|
||||
typedef enum fe_hierarchy {
|
||||
/**
|
||||
* enum fe_hierarchy - Hierarchy
|
||||
* @HIERARCHY_NONE: No hierarchy
|
||||
* @HIERARCHY_AUTO: Autodetect hierarchy (if supported)
|
||||
* @HIERARCHY_1: Hierarchy 1
|
||||
* @HIERARCHY_2: Hierarchy 2
|
||||
* @HIERARCHY_4: Hierarchy 4
|
||||
*
|
||||
* Please note that not all hierarchy types are supported by a given standard.
|
||||
*/
|
||||
enum fe_hierarchy {
|
||||
HIERARCHY_NONE,
|
||||
HIERARCHY_1,
|
||||
HIERARCHY_2,
|
||||
HIERARCHY_4,
|
||||
HIERARCHY_AUTO
|
||||
} fe_hierarchy_t;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum fe_interleaving - Interleaving
|
||||
* @INTERLEAVING_NONE: No interleaving.
|
||||
* @INTERLEAVING_AUTO: Auto-detect interleaving.
|
||||
* @INTERLEAVING_240: Interleaving of 240 symbols.
|
||||
* @INTERLEAVING_720: Interleaving of 720 symbols.
|
||||
*
|
||||
* Please note that, currently, only DTMB uses it.
|
||||
*/
|
||||
enum fe_interleaving {
|
||||
INTERLEAVING_NONE,
|
||||
INTERLEAVING_AUTO,
|
||||
@ -242,52 +457,8 @@ enum fe_interleaving {
|
||||
INTERLEAVING_720,
|
||||
};
|
||||
|
||||
#if defined(__DVB_CORE__) || !defined (__KERNEL__)
|
||||
struct dvb_qpsk_parameters {
|
||||
__u32 symbol_rate; /* symbol rate in Symbols per second */
|
||||
fe_code_rate_t fec_inner; /* forward error correction (see above) */
|
||||
};
|
||||
/* DVBv5 property Commands */
|
||||
|
||||
struct dvb_qam_parameters {
|
||||
__u32 symbol_rate; /* symbol rate in Symbols per second */
|
||||
fe_code_rate_t fec_inner; /* forward error correction (see above) */
|
||||
fe_modulation_t modulation; /* modulation type (see above) */
|
||||
};
|
||||
|
||||
struct dvb_vsb_parameters {
|
||||
fe_modulation_t modulation; /* modulation type (see above) */
|
||||
};
|
||||
|
||||
struct dvb_ofdm_parameters {
|
||||
fe_bandwidth_t bandwidth;
|
||||
fe_code_rate_t code_rate_HP; /* high priority stream code rate */
|
||||
fe_code_rate_t code_rate_LP; /* low priority stream code rate */
|
||||
fe_modulation_t constellation; /* modulation type (see above) */
|
||||
fe_transmit_mode_t transmission_mode;
|
||||
fe_guard_interval_t guard_interval;
|
||||
fe_hierarchy_t hierarchy_information;
|
||||
};
|
||||
|
||||
|
||||
struct dvb_frontend_parameters {
|
||||
__u32 frequency; /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
|
||||
/* intermediate frequency in kHz for QPSK */
|
||||
fe_spectral_inversion_t inversion;
|
||||
union {
|
||||
struct dvb_qpsk_parameters qpsk;
|
||||
struct dvb_qam_parameters qam;
|
||||
struct dvb_ofdm_parameters ofdm;
|
||||
struct dvb_vsb_parameters vsb;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct dvb_frontend_event {
|
||||
fe_status_t status;
|
||||
struct dvb_frontend_parameters parameters;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* S2API Commands */
|
||||
#define DTV_UNDEFINED 0
|
||||
#define DTV_TUNE 1
|
||||
#define DTV_CLEAR 2
|
||||
@ -383,20 +554,80 @@ struct dvb_frontend_event {
|
||||
|
||||
#define DTV_MAX_COMMAND DTV_PLS
|
||||
|
||||
typedef enum fe_pilot {
|
||||
/**
|
||||
* enum fe_pilot - Type of pilot tone
|
||||
*
|
||||
* @PILOT_ON: Pilot tones enabled
|
||||
* @PILOT_OFF: Pilot tones disabled
|
||||
* @PILOT_AUTO: Autodetect pilot tones
|
||||
*/
|
||||
enum fe_pilot {
|
||||
PILOT_ON,
|
||||
PILOT_OFF,
|
||||
PILOT_AUTO,
|
||||
} fe_pilot_t;
|
||||
};
|
||||
|
||||
typedef enum fe_rolloff {
|
||||
ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
|
||||
/**
|
||||
* enum fe_rolloff - Rolloff factor
|
||||
* @ROLLOFF_35: Roloff factor: α=35%
|
||||
* @ROLLOFF_20: Roloff factor: α=20%
|
||||
* @ROLLOFF_25: Roloff factor: α=25%
|
||||
* @ROLLOFF_AUTO: Auto-detect the roloff factor.
|
||||
*
|
||||
* .. note:
|
||||
*
|
||||
* Roloff factor of 35% is implied on DVB-S. On DVB-S2, it is default.
|
||||
*/
|
||||
enum fe_rolloff {
|
||||
ROLLOFF_35,
|
||||
ROLLOFF_20,
|
||||
ROLLOFF_25,
|
||||
ROLLOFF_AUTO,
|
||||
} fe_rolloff_t;
|
||||
};
|
||||
|
||||
typedef enum fe_delivery_system {
|
||||
/**
|
||||
* enum fe_delivery_system - Type of the delivery system
|
||||
*
|
||||
* @SYS_UNDEFINED:
|
||||
* Undefined standard. Generally, indicates an error
|
||||
* @SYS_DVBC_ANNEX_A:
|
||||
* Cable TV: DVB-C following ITU-T J.83 Annex A spec
|
||||
* @SYS_DVBC_ANNEX_B:
|
||||
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
|
||||
* @SYS_DVBC_ANNEX_C:
|
||||
* Cable TV: DVB-C following ITU-T J.83 Annex C spec
|
||||
* @SYS_ISDBC:
|
||||
* Cable TV: ISDB-C (no drivers yet)
|
||||
* @SYS_DVBT:
|
||||
* Terrestrial TV: DVB-T
|
||||
* @SYS_DVBT2:
|
||||
* Terrestrial TV: DVB-T2
|
||||
* @SYS_ISDBT:
|
||||
* Terrestrial TV: ISDB-T
|
||||
* @SYS_ATSC:
|
||||
* Terrestrial TV: ATSC
|
||||
* @SYS_ATSCMH:
|
||||
* Terrestrial TV (mobile): ATSC-M/H
|
||||
* @SYS_DTMB:
|
||||
* Terrestrial TV: DTMB
|
||||
* @SYS_DVBS:
|
||||
* Satellite TV: DVB-S
|
||||
* @SYS_DVBS2:
|
||||
* Satellite TV: DVB-S2
|
||||
* @SYS_TURBO:
|
||||
* Satellite TV: DVB-S Turbo
|
||||
* @SYS_ISDBS:
|
||||
* Satellite TV: ISDB-S
|
||||
* @SYS_DAB:
|
||||
* Digital audio: DAB (not fully supported)
|
||||
* @SYS_DSS:
|
||||
* Satellite TV: DSS (not fully supported)
|
||||
* @SYS_CMMB:
|
||||
* Terrestrial TV (mobile): CMMB (not fully supported)
|
||||
* @SYS_DVBH:
|
||||
* Terrestrial TV (mobile): DVB-H (standard deprecated)
|
||||
*/
|
||||
enum fe_delivery_system {
|
||||
SYS_UNDEFINED,
|
||||
SYS_DVBC_ANNEX_A,
|
||||
SYS_DVBC_ANNEX_B,
|
||||
@ -417,37 +648,87 @@ typedef enum fe_delivery_system {
|
||||
SYS_TURBO,
|
||||
SYS_DVBC_ANNEX_C,
|
||||
SYS_DVBC2,
|
||||
} fe_delivery_system_t;
|
||||
};
|
||||
|
||||
/* backward compatibility */
|
||||
/* backward compatibility definitions for delivery systems */
|
||||
#define SYS_DVBC_ANNEX_AC SYS_DVBC_ANNEX_A
|
||||
#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB instead */
|
||||
#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB */
|
||||
|
||||
/* ATSC-MH */
|
||||
/* ATSC-MH specific parameters */
|
||||
|
||||
/**
|
||||
* enum atscmh_sccc_block_mode - Type of Series Concatenated Convolutional
|
||||
* Code Block Mode.
|
||||
*
|
||||
* @ATSCMH_SCCC_BLK_SEP:
|
||||
* Separate SCCC: the SCCC outer code mode shall be set independently
|
||||
* for each Group Region (A, B, C, D)
|
||||
* @ATSCMH_SCCC_BLK_COMB:
|
||||
* Combined SCCC: all four Regions shall have the same SCCC outer
|
||||
* code mode.
|
||||
* @ATSCMH_SCCC_BLK_RES:
|
||||
* Reserved. Shouldn't be used.
|
||||
*/
|
||||
enum atscmh_sccc_block_mode {
|
||||
ATSCMH_SCCC_BLK_SEP = 0,
|
||||
ATSCMH_SCCC_BLK_COMB = 1,
|
||||
ATSCMH_SCCC_BLK_RES = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum atscmh_sccc_code_mode - Type of Series Concatenated Convolutional
|
||||
* Code Rate.
|
||||
*
|
||||
* @ATSCMH_SCCC_CODE_HLF:
|
||||
* The outer code rate of a SCCC Block is 1/2 rate.
|
||||
* @ATSCMH_SCCC_CODE_QTR:
|
||||
* The outer code rate of a SCCC Block is 1/4 rate.
|
||||
* @ATSCMH_SCCC_CODE_RES:
|
||||
* Reserved. Should not be used.
|
||||
*/
|
||||
enum atscmh_sccc_code_mode {
|
||||
ATSCMH_SCCC_CODE_HLF = 0,
|
||||
ATSCMH_SCCC_CODE_QTR = 1,
|
||||
ATSCMH_SCCC_CODE_RES = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum atscmh_rs_frame_ensemble - Reed Solomon(RS) frame ensemble.
|
||||
*
|
||||
* @ATSCMH_RSFRAME_ENS_PRI: Primary Ensemble.
|
||||
* @ATSCMH_RSFRAME_ENS_SEC: Secondary Ensemble.
|
||||
*/
|
||||
enum atscmh_rs_frame_ensemble {
|
||||
ATSCMH_RSFRAME_ENS_PRI = 0,
|
||||
ATSCMH_RSFRAME_ENS_SEC = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum atscmh_rs_frame_mode - Reed Solomon (RS) frame mode.
|
||||
*
|
||||
* @ATSCMH_RSFRAME_PRI_ONLY:
|
||||
* Single Frame: There is only a primary RS Frame for all Group
|
||||
* Regions.
|
||||
* @ATSCMH_RSFRAME_PRI_SEC:
|
||||
* Dual Frame: There are two separate RS Frames: Primary RS Frame for
|
||||
* Group Region A and B and Secondary RS Frame for Group Region C and
|
||||
* D.
|
||||
* @ATSCMH_RSFRAME_RES:
|
||||
* Reserved. Shouldn't be used.
|
||||
*/
|
||||
enum atscmh_rs_frame_mode {
|
||||
ATSCMH_RSFRAME_PRI_ONLY = 0,
|
||||
ATSCMH_RSFRAME_PRI_SEC = 1,
|
||||
ATSCMH_RSFRAME_RES = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum atscmh_rs_code_mode
|
||||
* @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
|
||||
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
|
||||
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
|
||||
* @ATSCMH_RSCODE_RES: Reserved. Shouldn't be used.
|
||||
*/
|
||||
enum atscmh_rs_code_mode {
|
||||
ATSCMH_RSCODE_211_187 = 0,
|
||||
ATSCMH_RSCODE_223_187 = 1,
|
||||
@ -459,23 +740,13 @@ enum atscmh_rs_code_mode {
|
||||
#define NO_SCRAMBLING_CODE (~0U)
|
||||
#define LNA_AUTO (~0U)
|
||||
|
||||
struct dtv_cmds_h {
|
||||
char *name; /* A display name for debugging purposes */
|
||||
|
||||
__u32 cmd; /* A unique ID */
|
||||
|
||||
/* Flags */
|
||||
__u32 set:1; /* Either a set or get property */
|
||||
__u32 buffer:1; /* Does this property use the buffer? */
|
||||
__u32 reserved:30; /* Align */
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale types for the quality parameters.
|
||||
* enum fecap_scale_params - scale types for the quality parameters.
|
||||
*
|
||||
* @FE_SCALE_NOT_AVAILABLE: That QoS measure is not available. That
|
||||
* could indicate a temporary or a permanent
|
||||
* condition.
|
||||
* @FE_SCALE_DECIBEL: The scale is measured in 0.0001 dB steps, typically
|
||||
* @FE_SCALE_DECIBEL: The scale is measured in 0.001 dB steps, typically
|
||||
* used on signal measures.
|
||||
* @FE_SCALE_RELATIVE: The scale is a relative percentual measure,
|
||||
* ranging from 0 (0%) to 0xffff (100%).
|
||||
@ -492,50 +763,92 @@ enum fecap_scale_params {
|
||||
/**
|
||||
* struct dtv_stats - Used for reading a DTV status property
|
||||
*
|
||||
* @value: value of the measure. Should range from 0 to 0xffff;
|
||||
* @scale: Filled with enum fecap_scale_params - the scale
|
||||
* in usage for that parameter
|
||||
*
|
||||
* The ``{unnamed_union}`` may have either one of the values below:
|
||||
*
|
||||
* %svalue
|
||||
* integer value of the measure, for %FE_SCALE_DECIBEL,
|
||||
* used for dB measures. The unit is 0.001 dB.
|
||||
*
|
||||
* %uvalue
|
||||
* unsigned integer value of the measure, used when @scale is
|
||||
* either %FE_SCALE_RELATIVE or %FE_SCALE_COUNTER.
|
||||
*
|
||||
* For most delivery systems, this will return a single value for each
|
||||
* parameter.
|
||||
*
|
||||
* It should be noticed, however, that new OFDM delivery systems like
|
||||
* ISDB can use different modulation types for each group of carriers.
|
||||
* On such standards, up to 8 groups of statistics can be provided, one
|
||||
* for each carrier group (called "layer" on ISDB).
|
||||
*
|
||||
* In order to be consistent with other delivery systems, the first
|
||||
* value refers to the entire set of carriers ("global").
|
||||
* dtv_status:scale should use the value FE_SCALE_NOT_AVAILABLE when
|
||||
*
|
||||
* @scale should use the value %FE_SCALE_NOT_AVAILABLE when
|
||||
* the value for the entire group of carriers or from one specific layer
|
||||
* is not provided by the hardware.
|
||||
* st.len should be filled with the latest filled status + 1.
|
||||
*
|
||||
* In other words, for ISDB, those values should be filled like:
|
||||
* @len should be filled with the latest filled status + 1.
|
||||
*
|
||||
* In other words, for ISDB, those values should be filled like::
|
||||
*
|
||||
* u.st.stat.svalue[0] = global statistics;
|
||||
* u.st.stat.scale[0] = FE_SCALE_DECIBELS;
|
||||
* u.st.stat.scale[0] = FE_SCALE_DECIBEL;
|
||||
* u.st.stat.value[1] = layer A statistics;
|
||||
* u.st.stat.scale[1] = FE_SCALE_NOT_AVAILABLE (if not available);
|
||||
* u.st.stat.svalue[2] = layer B statistics;
|
||||
* u.st.stat.scale[2] = FE_SCALE_DECIBELS;
|
||||
* u.st.stat.scale[2] = FE_SCALE_DECIBEL;
|
||||
* u.st.stat.svalue[3] = layer C statistics;
|
||||
* u.st.stat.scale[3] = FE_SCALE_DECIBELS;
|
||||
* u.st.stat.scale[3] = FE_SCALE_DECIBEL;
|
||||
* u.st.len = 4;
|
||||
*/
|
||||
struct dtv_stats {
|
||||
__u8 scale; /* enum fecap_scale_params type */
|
||||
union {
|
||||
__u64 uvalue; /* for counters and relative scales */
|
||||
__s64 svalue; /* for 0.0001 dB measures */
|
||||
__s64 svalue; /* for 0.001 dB measures */
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#define MAX_DTV_STATS 4
|
||||
|
||||
/**
|
||||
* struct dtv_fe_stats - store Digital TV frontend statistics
|
||||
*
|
||||
* @len: length of the statistics - if zero, stats is disabled.
|
||||
* @stat: array with digital TV statistics.
|
||||
*
|
||||
* On most standards, @len can either be 0 or 1. However, for ISDB, each
|
||||
* layer is modulated in separate. So, each layer may have its own set
|
||||
* of statistics. If so, stat[0] carries on a global value for the property.
|
||||
* Indexes 1 to 3 means layer A to B.
|
||||
*/
|
||||
struct dtv_fe_stats {
|
||||
__u8 len;
|
||||
struct dtv_stats stat[MAX_DTV_STATS];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct dtv_property - store one of frontend command and its value
|
||||
*
|
||||
* @cmd: Digital TV command.
|
||||
* @reserved: Not used.
|
||||
* @u: Union with the values for the command.
|
||||
* @result: Result of the command set (currently unused).
|
||||
*
|
||||
* The @u union may have either one of the values below:
|
||||
*
|
||||
* %data
|
||||
* an unsigned 32-bits number.
|
||||
* %st
|
||||
* a &struct dtv_fe_stats array of statistics.
|
||||
* %buffer
|
||||
* a buffer of up to 32 characters (currently unused).
|
||||
*/
|
||||
struct dtv_property {
|
||||
__u32 cmd;
|
||||
__u32 reserved[3];
|
||||
@ -555,24 +868,27 @@ struct dtv_property {
|
||||
/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
|
||||
#define DTV_IOCTL_MAX_MSGS 64
|
||||
|
||||
/**
|
||||
* struct dtv_properties - a set of command/value pairs.
|
||||
*
|
||||
* @num: amount of commands stored at the struct.
|
||||
* @props: a pointer to &struct dtv_property.
|
||||
*/
|
||||
struct dtv_properties {
|
||||
__u32 num;
|
||||
struct dtv_property *props;
|
||||
};
|
||||
|
||||
#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
|
||||
#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* When set, this flag will disable any zigzagging or other "normal" tuning
|
||||
* behaviour. Additionally, there will be no automatic monitoring of the lock
|
||||
* behavior. Additionally, there will be no automatic monitoring of the lock
|
||||
* status, and hence no frontend events will be generated. If a frontend device
|
||||
* is closed, this flag will be automatically turned off when the device is
|
||||
* reopened read-write.
|
||||
*/
|
||||
#define FE_TUNE_MODE_ONESHOT 0x01
|
||||
|
||||
/* Digital TV Frontend API calls */
|
||||
|
||||
#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
|
||||
|
||||
@ -591,11 +907,110 @@ struct dtv_properties {
|
||||
#define FE_READ_SNR _IOR('o', 72, __u16)
|
||||
#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
|
||||
|
||||
#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
|
||||
#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
|
||||
#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */
|
||||
#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
|
||||
|
||||
#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
|
||||
|
||||
#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
|
||||
#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
|
||||
|
||||
#if defined(__DVB_CORE__) || !defined(__KERNEL__)
|
||||
|
||||
/*
|
||||
* DEPRECATED: Everything below is deprecated in favor of DVBv5 API
|
||||
*
|
||||
* The DVBv3 only ioctls, structs and enums should not be used on
|
||||
* newer programs, as it doesn't support the second generation of
|
||||
* digital TV standards, nor supports newer delivery systems.
|
||||
* They also don't support modern frontends with usually support multiple
|
||||
* delivery systems.
|
||||
*
|
||||
* Drivers shouldn't use them.
|
||||
*
|
||||
* New applications should use DVBv5 delivery system instead
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
enum fe_bandwidth {
|
||||
BANDWIDTH_8_MHZ,
|
||||
BANDWIDTH_7_MHZ,
|
||||
BANDWIDTH_6_MHZ,
|
||||
BANDWIDTH_AUTO,
|
||||
BANDWIDTH_5_MHZ,
|
||||
BANDWIDTH_10_MHZ,
|
||||
BANDWIDTH_1_712_MHZ,
|
||||
};
|
||||
|
||||
/* This is kept for legacy userspace support */
|
||||
typedef enum fe_sec_voltage fe_sec_voltage_t;
|
||||
typedef enum fe_caps fe_caps_t;
|
||||
typedef enum fe_type fe_type_t;
|
||||
typedef enum fe_sec_tone_mode fe_sec_tone_mode_t;
|
||||
typedef enum fe_sec_mini_cmd fe_sec_mini_cmd_t;
|
||||
typedef enum fe_status fe_status_t;
|
||||
typedef enum fe_spectral_inversion fe_spectral_inversion_t;
|
||||
typedef enum fe_code_rate fe_code_rate_t;
|
||||
typedef enum fe_modulation fe_modulation_t;
|
||||
typedef enum fe_transmit_mode fe_transmit_mode_t;
|
||||
typedef enum fe_bandwidth fe_bandwidth_t;
|
||||
typedef enum fe_guard_interval fe_guard_interval_t;
|
||||
typedef enum fe_hierarchy fe_hierarchy_t;
|
||||
typedef enum fe_pilot fe_pilot_t;
|
||||
typedef enum fe_rolloff fe_rolloff_t;
|
||||
typedef enum fe_delivery_system fe_delivery_system_t;
|
||||
|
||||
/* DVBv3 structs */
|
||||
|
||||
struct dvb_qpsk_parameters {
|
||||
__u32 symbol_rate; /* symbol rate in Symbols per second */
|
||||
fe_code_rate_t fec_inner; /* forward error correction (see above) */
|
||||
};
|
||||
|
||||
struct dvb_qam_parameters {
|
||||
__u32 symbol_rate; /* symbol rate in Symbols per second */
|
||||
fe_code_rate_t fec_inner; /* forward error correction (see above) */
|
||||
fe_modulation_t modulation; /* modulation type (see above) */
|
||||
};
|
||||
|
||||
struct dvb_vsb_parameters {
|
||||
fe_modulation_t modulation; /* modulation type (see above) */
|
||||
};
|
||||
|
||||
struct dvb_ofdm_parameters {
|
||||
fe_bandwidth_t bandwidth;
|
||||
fe_code_rate_t code_rate_HP; /* high priority stream code rate */
|
||||
fe_code_rate_t code_rate_LP; /* low priority stream code rate */
|
||||
fe_modulation_t constellation; /* modulation type (see above) */
|
||||
fe_transmit_mode_t transmission_mode;
|
||||
fe_guard_interval_t guard_interval;
|
||||
fe_hierarchy_t hierarchy_information;
|
||||
};
|
||||
|
||||
struct dvb_frontend_parameters {
|
||||
__u32 frequency; /* (absolute) frequency in Hz for DVB-C/DVB-T/ATSC */
|
||||
/* intermediate frequency in kHz for DVB-S */
|
||||
fe_spectral_inversion_t inversion;
|
||||
union {
|
||||
struct dvb_qpsk_parameters qpsk; /* DVB-S */
|
||||
struct dvb_qam_parameters qam; /* DVB-C */
|
||||
struct dvb_ofdm_parameters ofdm; /* DVB-T */
|
||||
struct dvb_vsb_parameters vsb; /* ATSC */
|
||||
} u;
|
||||
};
|
||||
|
||||
struct dvb_frontend_event {
|
||||
fe_status_t status;
|
||||
struct dvb_frontend_parameters parameters;
|
||||
};
|
||||
|
||||
/* DVBv3 API calls */
|
||||
|
||||
#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
|
||||
#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*_DVBFRONTEND_H_*/
|
||||
|
@ -26,6 +26,21 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* struct dvb_net_if - describes a DVB network interface
|
||||
*
|
||||
* @pid: Packet ID (PID) of the MPEG-TS that contains data
|
||||
* @if_num: number of the Digital TV interface.
|
||||
* @feedtype: Encapsulation type of the feed.
|
||||
*
|
||||
* A MPEG-TS stream may contain packet IDs with IP packages on it.
|
||||
* This struct describes it, and the type of encoding.
|
||||
*
|
||||
* @feedtype can be:
|
||||
*
|
||||
* - %DVB_NET_FEEDTYPE_MPE for MPE encoding
|
||||
* - %DVB_NET_FEEDTYPE_ULE for ULE encoding.
|
||||
*/
|
||||
struct dvb_net_if {
|
||||
__u16 pid;
|
||||
__u16 if_num;
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
@ -139,7 +138,8 @@ struct video_event {
|
||||
#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
|
||||
#define VIDEO_EVENT_DECODER_STOPPED 3
|
||||
#define VIDEO_EVENT_VSYNC 4
|
||||
__kernel_time_t timestamp;
|
||||
/* unused, make sure to use atomic time for y2038 if it ever gets used */
|
||||
long timestamp;
|
||||
union {
|
||||
video_size_t size;
|
||||
unsigned int frame_rate; /* in frames per 1000sec */
|
||||
@ -211,7 +211,8 @@ typedef __u16 video_attributes_t;
|
||||
/* 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)) */
|
||||
/* 0 film/camera mode (0=
|
||||
*camera, 1=film (625/50 only)) */
|
||||
|
||||
|
||||
/* bit definitions for capabilities: */
|
||||
|
Loading…
Reference in New Issue
Block a user