Merge tag 'media/v4.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - videobuf2 was moved to a media/common dir, as it is now used by the
   DVB subsystem too

 - Digital TV core memory mapped support interface

 - new sensor driver: ov7740

 - several improvements at ddbridge driver

 - new V4L2 driver: IPU3 CIO2 CSI-2 receiver unit, found on some Intel
   SoCs

 - new tuner driver: tda18250

 - finally got rid of all LIRC staging drivers

 - as we don't have old lirc drivers anymore, restruct the lirc device
   code

 - add support for UVC metadata

 - add a new staging driver for NVIDIA Tegra Video Decoder Engine

 - DVB kAPI headers moved to include/media

 - synchronize the kAPI and uAPI for the DVB subsystem, removing the gap
   for non-legacy APIs

 - reduce the kAPI gap for V4L2

 - lots of other driver enhancements, cleanups, etc.

* tag 'media/v4.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (407 commits)
  media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-ioctl.c: use check_fmt for enum/g/s/try_fmt
  media: vivid: fix module load error when enabling fb and no_error_inj=1
  media: dvb_demux: improve debug messages
  media: dvb_demux: Better handle discontinuity errors
  media: cxusb, dib0700: ignore XC2028_I2C_FLUSH
  media: ts2020: avoid integer overflows on 32 bit machines
  media: i2c: ov7740: use gpio/consumer.h instead of gpio.h
  media: entity: Add a nop variant of media_entity_cleanup
  ...
This commit is contained in:
Linus Torvalds
2018-02-06 11:27:48 -08:00
953 changed files with 21729 additions and 14041 deletions

View File

@@ -40,3 +40,16 @@ config DVB_DEMUX_SECTION_LOSS_LOG
be very verbose.
If you are unsure about this, say N here.
config DVB_ULE_DEBUG
bool "Enable DVB net ULE packet debug messages"
depends on DVB_CORE
default n
help
Enable extra log messages meant to detect problems while
handling DVB network ULE 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.

View File

@@ -4,9 +4,10 @@
#
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
dvb-vb2-$(CONFIG_DVB_MMSP) := dvb_vb2.o
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o dvb_math.o
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o

View File

@@ -1,589 +0,0 @@
/*
* 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:
* Copyright (c) 2000 Nokia Research Center
* Tampere, FINLAND
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __DEMUX_H
#define __DEMUX_H
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/dvb/dmx.h>
/*
* Common definitions
*/
/*
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
*/
#ifndef DMX_MAX_FILTER_SIZE
#define DMX_MAX_FILTER_SIZE 18
#endif
/*
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed
* filter.
*/
#ifndef DMX_MAX_SECTION_SIZE
#define DMX_MAX_SECTION_SIZE 4096
#endif
#ifndef DMX_MAX_SECFEED_SIZE
#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
#endif
/*
* TS packet reception
*/
/**
* 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,
};
/**
* 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;
struct dmx_demux *parent;
void *priv;
int (*set)(struct dmx_ts_feed *feed,
u16 pid,
int type,
enum dmx_ts_pes pes_type,
ktime_t timeout);
int (*start_filtering)(struct dmx_ts_feed *feed);
int (*stop_filtering)(struct dmx_ts_feed *feed);
};
/*
* 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];
u8 filter_mode[DMX_MAX_FILTER_SIZE];
struct dmx_section_feed *parent; /* Back-pointer */
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;
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,
int check_crc);
int (*allocate_filter)(struct dmx_section_feed *feed,
struct dmx_section_filter **filter);
int (*release_filter)(struct dmx_section_feed *feed,
struct dmx_section_filter *filter);
int (*start_filtering)(struct dmx_section_feed *feed);
int (*stop_filtering)(struct dmx_section_feed *feed);
};
/**
* 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);
/**
* 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);
/*
* 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,
};
/**
* 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;
enum dmx_frontend_source source;
};
/*
* MPEG-2 TS Demux
*/
/**
* 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
* 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)
/**
* 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 {
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 (*allocate_ts_feed)(struct dmx_demux *demux,
struct dmx_ts_feed **feed,
dmx_ts_cb callback);
int (*release_ts_feed)(struct dmx_demux *demux,
struct dmx_ts_feed *feed);
int (*allocate_section_feed)(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback);
int (*release_section_feed)(struct dmx_demux *demux,
struct dmx_section_feed *feed);
int (*add_frontend)(struct dmx_demux *demux,
struct dmx_frontend *frontend);
int (*remove_frontend)(struct dmx_demux *demux,
struct dmx_frontend *frontend);
struct list_head *(*get_frontends)(struct dmx_demux *demux);
int (*connect_frontend)(struct dmx_demux *demux,
struct dmx_frontend *frontend);
int (*disconnect_frontend)(struct dmx_demux *demux);
int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids);
/* 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);
};
#endif /* #ifndef __DEMUX_H */

View File

@@ -27,7 +27,8 @@
#include <linux/ioctl.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include "dmxdev.h"
#include <media/dmxdev.h>
#include <media/dvb_vb2.h>
static int debug;
@@ -127,6 +128,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
struct dmx_frontend *front;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__);
@@ -138,14 +144,19 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENODEV;
}
#ifndef DVB_MMAP
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#else
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
mutex_unlock(&dmxdev->mutex);
return -EOPNOTSUPP;
}
}
#endif
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
if (need_ringbuffer) {
void *mem;
if (!dvbdev->readers) {
@@ -158,6 +169,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
return -ENOMEM;
}
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
file->f_flags & O_NONBLOCK);
dvbdev->readers--;
}
@@ -187,6 +200,11 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
mutex_lock(&dmxdev->mutex);
@@ -195,7 +213,15 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->demux->connect_frontend(dmxdev->demux,
dmxdev->dvr_orig_fe);
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
#ifndef DVB_MMAP
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#endif
if (need_ringbuffer) {
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
dvbdev->readers++;
if (dmxdev->dvr_buffer.data) {
void *mem = dmxdev->dvr_buffer.data;
@@ -359,7 +385,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;
if (dmxdevfilter->buffer.error) {
if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
@@ -370,11 +397,19 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
}
del_timer(&dmxdevfilter->timer);
dprintk("section callback %*ph\n", 6, buffer1);
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
buffer1_len);
if (ret == buffer1_len) {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
buffer2_len);
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer1, buffer1_len);
if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
buffer2, buffer2_len);
} else {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
buffer1, buffer1_len);
if (ret == buffer1_len) {
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
buffer2, buffer2_len);
}
}
if (ret < 0)
dmxdevfilter->buffer.error = ret;
@@ -391,6 +426,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
#ifdef DVB_MMAP
struct dvb_vb2_ctx *ctx;
#endif
int ret;
spin_lock(&dmxdevfilter->dev->lock);
@@ -399,19 +437,34 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
return 0;
}
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
|| dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
buffer = &dmxdevfilter->buffer;
else
#ifdef DVB_MMAP
ctx = &dmxdevfilter->vb2_ctx;
#endif
} else {
buffer = &dmxdevfilter->dev->dvr_buffer;
if (buffer->error) {
spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
#ifdef DVB_MMAP
ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
#endif
}
if (dvb_vb2_is_streaming(ctx)) {
ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
if (ret == buffer1_len)
ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
} else {
if (buffer->error) {
spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
}
ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
if (ret == buffer1_len)
ret = dvb_dmxdev_buffer_write(buffer,
buffer2, buffer2_len);
}
ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
if (ret == buffer1_len)
ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
if (ret < 0)
buffer->error = ret;
spin_unlock(&dmxdevfilter->dev->lock);
@@ -750,6 +803,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
file->private_data = dmxdevfilter;
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
file->f_flags & O_NONBLOCK);
dmxdevfilter->type = DMXDEV_TYPE_NONE;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0);
@@ -765,6 +820,10 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
{
mutex_lock(&dmxdev->mutex);
mutex_lock(&dmxdevfilter->mutex);
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx);
dvb_vb2_release(&dmxdevfilter->vb2_ctx);
dvb_dmxdev_filter_stop(dmxdevfilter);
dvb_dmxdev_filter_reset(dmxdevfilter);
@@ -1052,6 +1111,54 @@ static int dvb_demux_do_ioctl(struct file *file,
mutex_unlock(&dmxdevfilter->mutex);
break;
#ifdef DVB_MMAP
case DMX_REQBUFS:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_QUERYBUF:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_EXPBUF:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_QBUF:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg);
if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx);
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_DQBUF:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
#endif
default:
ret = -EINVAL;
break;
@@ -1073,6 +1180,8 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
return POLLERR;
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
return dvb_vb2_poll(&dmxdevfilter->vb2_ctx, file, wait);
poll_wait(file, &dmxdevfilter->buffer.queue, wait);
@@ -1090,11 +1199,33 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
return mask;
}
#ifdef DVB_MMAP
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
{
struct dmxdev_filter *dmxdevfilter = file->private_data;
struct dmxdev *dmxdev = dmxdevfilter->dev;
int ret;
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma);
mutex_unlock(&dmxdevfilter->mutex);
mutex_unlock(&dmxdev->mutex);
return ret;
}
#endif
static int dvb_demux_release(struct inode *inode, struct file *file)
{
struct dmxdev_filter *dmxdevfilter = file->private_data;
struct dmxdev *dmxdev = dmxdevfilter->dev;
int ret;
ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
@@ -1118,6 +1249,9 @@ static const struct file_operations dvb_demux_fops = {
.release = dvb_demux_release,
.poll = dvb_demux_poll,
.llseek = default_llseek,
#ifdef DVB_MMAP
.mmap = dvb_demux_mmap,
#endif
};
static const struct dvb_device dvbdev_demux = {
@@ -1146,6 +1280,29 @@ static int dvb_dvr_do_ioctl(struct file *file,
ret = dvb_dvr_set_buffer_size(dmxdev, arg);
break;
#ifdef DVB_MMAP
case DMX_REQBUFS:
ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
break;
case DMX_QUERYBUF:
ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg);
break;
case DMX_EXPBUF:
ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg);
break;
case DMX_QBUF:
ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg);
if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx);
break;
case DMX_DQBUF:
ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
break;
#endif
default:
ret = -EINVAL;
break;
@@ -1165,15 +1322,26 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
__poll_t mask = 0;
#ifndef DVB_MMAP
bool need_ringbuffer = false;
#else
const bool need_ringbuffer = true;
#endif
dprintk("%s\n", __func__);
if (dmxdev->exit)
return POLLERR;
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
return dvb_vb2_poll(&dmxdev->dvr_vb2_ctx, file, wait);
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
#ifndef DVB_MMAP
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
need_ringbuffer = true;
#endif
if (need_ringbuffer) {
if (dmxdev->dvr_buffer.error)
mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
@@ -1185,6 +1353,25 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
return mask;
}
#ifdef DVB_MMAP
static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
{
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
int ret;
if (dmxdev->exit)
return -ENODEV;
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma);
mutex_unlock(&dmxdev->mutex);
return ret;
}
#endif
static const struct file_operations dvb_dvr_fops = {
.owner = THIS_MODULE,
.read = dvb_dvr_read,
@@ -1194,6 +1381,9 @@ static const struct file_operations dvb_dvr_fops = {
.release = dvb_dvr_release,
.poll = dvb_dvr_poll,
.llseek = default_llseek,
#ifdef DVB_MMAP
.mmap = dvb_dvr_mmap,
#endif
};
static const struct dvb_device dvbdev_dvr = {

View File

@@ -1,201 +0,0 @@
/*
* dmxdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DMXDEV_H_
#define _DMXDEV_H_
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/dvb/dmx.h>
#include "dvbdev.h"
#include "demux.h"
#include "dvb_ringbuffer.h"
/**
* enum dmxdev_type - type of demux filter type.
*
* @DMXDEV_TYPE_NONE: no filter set.
* @DMXDEV_TYPE_SEC: section filter.
* @DMXDEV_TYPE_PES: Program Elementary Stream (PES) filter.
*/
enum dmxdev_type {
DMXDEV_TYPE_NONE,
DMXDEV_TYPE_SEC,
DMXDEV_TYPE_PES,
};
/**
* enum dmxdev_state - state machine for the dmxdev.
*
* @DMXDEV_STATE_FREE: indicates that the filter is freed.
* @DMXDEV_STATE_ALLOCATED: indicates that the filter was allocated
* to be used.
* @DMXDEV_STATE_SET: indicates that the filter parameters are set.
* @DMXDEV_STATE_GO: indicates that the filter is running.
* @DMXDEV_STATE_DONE: indicates that a packet was already filtered
* and the filter is now disabled.
* Set only if %DMX_ONESHOT. See
* &dmx_sct_filter_params.
* @DMXDEV_STATE_TIMEDOUT: Indicates a timeout condition.
*/
enum dmxdev_state {
DMXDEV_STATE_FREE,
DMXDEV_STATE_ALLOCATED,
DMXDEV_STATE_SET,
DMXDEV_STATE_GO,
DMXDEV_STATE_DONE,
DMXDEV_STATE_TIMEDOUT
};
/**
* struct dmxdev_feed - digital TV dmxdev feed
*
* @pid: Program ID to be filtered
* @ts: pointer to &struct dmx_ts_feed
* @next: &struct list_head pointing to the next feed.
*/
struct dmxdev_feed {
u16 pid;
struct dmx_ts_feed *ts;
struct list_head next;
};
/**
* struct dmxdev_filter - digital TV dmxdev filter
*
* @filter: a dmxdev filter. Currently used only for section filter:
* if the filter is Section, it contains a
* &struct dmx_section_filter @sec pointer.
* @feed: a dmxdev feed. Depending on the feed type, it can be:
* for TS feed: a &struct list_head @ts list of TS and PES
* feeds;
* for section feed: a &struct dmx_section_feed @sec pointer.
* @params: dmxdev filter parameters. Depending on the feed type, it
* can be:
* for section filter: a &struct dmx_sct_filter_params @sec
* embedded struct;
* for a TS filter: a &struct dmx_pes_filter_params @pes
* embedded struct.
* @type: type of the dmxdev filter, as defined by &enum dmxdev_type.
* @state: state of the dmxdev filter, as defined by &enum dmxdev_state.
* @dev: pointer to &struct dmxdev.
* @buffer: an embedded &struct dvb_ringbuffer buffer.
* @mutex: protects the access to &struct dmxdev_filter.
* @timer: &struct timer_list embedded timer, used to check for
* feed timeouts.
* Only for section filter.
* @todo: index for the @secheader.
* Only for section filter.
* @secheader: buffer cache to parse the section header.
* Only for section filter.
*/
struct dmxdev_filter {
union {
struct dmx_section_filter *sec;
} filter;
union {
/* list of TS and PES feeds (struct dmxdev_feed) */
struct list_head ts;
struct dmx_section_feed *sec;
} feed;
union {
struct dmx_sct_filter_params sec;
struct dmx_pes_filter_params pes;
} params;
enum dmxdev_type type;
enum dmxdev_state state;
struct dmxdev *dev;
struct dvb_ringbuffer buffer;
struct mutex mutex;
/* only for sections */
struct timer_list timer;
int todo;
u8 secheader[3];
};
/**
* struct dmxdev - Describes a digital TV demux device.
*
* @dvbdev: pointer to &struct dvb_device associated with
* the demux device node.
* @dvr_dvbdev: pointer to &struct dvb_device associated with
* the dvr device node.
* @filter: pointer to &struct dmxdev_filter.
* @demux: pointer to &struct dmx_demux.
* @filternum: number of filters.
* @capabilities: demux capabilities as defined by &enum dmx_demux_caps.
* @exit: flag to indicate that the demux is being released.
* @dvr_orig_fe: pointer to &struct dmx_frontend.
* @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output.
* @mutex: protects the usage of this structure.
* @lock: protects access to &dmxdev->filter->data.
*/
struct dmxdev {
struct dvb_device *dvbdev;
struct dvb_device *dvr_dvbdev;
struct dmxdev_filter *filter;
struct dmx_demux *demux;
int filternum;
int capabilities;
unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1
struct dmx_frontend *dvr_orig_fe;
struct dvb_ringbuffer dvr_buffer;
#define DVR_BUFFER_SIZE (10*188*1024)
struct mutex mutex;
spinlock_t lock;
};
/**
* dvb_dmxdev_init - initializes a digital TV demux and registers both demux
* and DVR devices.
*
* @dmxdev: pointer to &struct dmxdev.
* @adap: pointer to &struct dvb_adapter.
*/
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap);
/**
* dvb_dmxdev_release - releases a digital TV demux and unregisters it.
*
* @dmxdev: pointer to &struct dmxdev.
*/
void dvb_dmxdev_release(struct dmxdev *dmxdev);
#endif /* _DMXDEV_H_ */

View File

@@ -1,421 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* dvb-usb-ids.h is part of the DVB USB library.
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) see
* dvb-usb-init.c for copyright information.
*
* a header file containing define's for the USB device supported by the
* various drivers.
*/
#ifndef _DVB_USB_IDS_H_
#define _DVB_USB_IDS_H_
/* Vendor IDs */
#define USB_VID_ADSTECH 0x06e1
#define USB_VID_AFATECH 0x15a4
#define USB_VID_ALCOR_MICRO 0x058f
#define USB_VID_ALINK 0x05e3
#define USB_VID_AMT 0x1c73
#define USB_VID_ANCHOR 0x0547
#define USB_VID_ANSONIC 0x10b9
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
#define USB_VID_ASUS 0x0b05
#define USB_VID_AVERMEDIA 0x07ca
#define USB_VID_COMPRO 0x185b
#define USB_VID_COMPRO_UNK 0x145f
#define USB_VID_CONEXANT 0x0572
#define USB_VID_CYPRESS 0x04b4
#define USB_VID_DEXATEK 0x1d19
#define USB_VID_DIBCOM 0x10b8
#define USB_VID_DPOSH 0x1498
#define USB_VID_DVICO 0x0fe9
#define USB_VID_E3C 0x18b4
#define USB_VID_ELGATO 0x0fd9
#define USB_VID_EMPIA 0xeb1a
#define USB_VID_GENPIX 0x09c0
#define USB_VID_GRANDTEC 0x5032
#define USB_VID_GTEK 0x1f4d
#define USB_VID_HANFTEK 0x15f4
#define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_INTEL 0x8086
#define USB_VID_ITETECH 0x048d
#define USB_VID_KWORLD 0xeb2a
#define USB_VID_KWORLD_2 0x1b80
#define USB_VID_KYE 0x0458
#define USB_VID_LEADTEK 0x0413
#define USB_VID_LITEON 0x04ca
#define USB_VID_MEDION 0x1660
#define USB_VID_MIGLIA 0x18f3
#define USB_VID_MSI 0x0db0
#define USB_VID_MSI_2 0x1462
#define USB_VID_OPERA1 0x695c
#define USB_VID_PINNACLE 0x2304
#define USB_VID_PCTV 0x2013
#define USB_VID_PIXELVIEW 0x1554
#define USB_VID_REALTEK 0x0bda
#define USB_VID_TECHNOTREND 0x0b48
#define USB_VID_TERRATEC 0x0ccd
#define USB_VID_TELESTAR 0x10b9
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_SONY 0x1415
#define USB_PID_TEVII_S421 0xd421
#define USB_PID_TEVII_S480_1 0xd481
#define USB_PID_TEVII_S480_2 0xd482
#define USB_PID_TEVII_S630 0xd630
#define USB_PID_TEVII_S632 0xd632
#define USB_PID_TEVII_S650 0xd650
#define USB_PID_TEVII_S660 0xd660
#define USB_PID_TEVII_S662 0xd662
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
#define USB_VID_UNIWILL 0x1584
#define USB_VID_WIDEVIEW 0x14aa
#define USB_VID_GIGABYTE 0x1044
#define USB_VID_YUAN 0x1164
#define USB_VID_XTENSIONS 0x1ae7
#define USB_VID_ZYDAS 0x0ace
#define USB_VID_HUMAX_COEX 0x10b9
#define USB_VID_774 0x7a69
#define USB_VID_EVOLUTEPC 0x1e59
#define USB_VID_AZUREWAVE 0x13d3
#define USB_VID_TECHNISAT 0x14f7
#define USB_VID_HAMA 0x147f
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
#define USB_PID_ADSTECH_USB2_WARM 0xa334
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_PID_AFATECH_AF9015_9015 0x9015
#define USB_PID_AFATECH_AF9015_9016 0x9016
#define USB_PID_AFATECH_AF9035_1000 0x1000
#define USB_PID_AFATECH_AF9035_1001 0x1001
#define USB_PID_AFATECH_AF9035_1002 0x1002
#define USB_PID_AFATECH_AF9035_1003 0x1003
#define USB_PID_AFATECH_AF9035_9035 0x9035
#define USB_PID_TREKSTOR_DVBT 0x901b
#define USB_PID_TREKSTOR_TERRES_2_0 0xC803
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
#define USB_PID_ANYSEE 0x861f
#define USB_PID_AZUREWAVE_AD_TU700 0x3237
#define USB_PID_AZUREWAVE_6007 0x0ccd
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
#define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_CREATIX_CTX1921 0x1921
#define USB_PID_DELOCK_USB2_DVBT 0xb803
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
#define USB_PID_DIBCOM_STK7700P 0x1e14
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
#define USB_PID_DIBCOM_STK7700D 0x1ef0
#define USB_PID_DIBCOM_STK7700_U7000 0x7001
#define USB_PID_DIBCOM_STK7070P 0x1ebc
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_STK807XP 0x1f90
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_STK8096PVR 0x1faa
#define USB_PID_DIBCOM_NIM8096MD 0x1fa8
#define USB_PID_DIBCOM_TFE8096P 0x1f9C
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DIBCOM_NIM7090 0x1bb2
#define USB_PID_DIBCOM_TFE7090PVR 0x1bb4
#define USB_PID_DIBCOM_TFE7790P 0x1e6e
#define USB_PID_DIBCOM_NIM9090M 0x2383
#define USB_PID_DIBCOM_NIM9090MD 0x2384
#define USB_PID_DPOSH_M9206_COLD 0x9206
#define USB_PID_DPOSH_M9206_WARM 0xa090
#define USB_PID_E3C_EC168 0x1689
#define USB_PID_E3C_EC168_2 0xfffa
#define USB_PID_E3C_EC168_3 0xfffb
#define USB_PID_E3C_EC168_4 0x1001
#define USB_PID_E3C_EC168_5 0x1002
#define USB_PID_FREECOM_DVBT 0x0160
#define USB_PID_FREECOM_DVBT_2 0x0161
#define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_GOTVIEW_SAT_HD 0x5456
#define USB_PID_INTEL_CE9500 0x9500
#define USB_PID_ITETECH_IT9135 0x9135
#define USB_PID_ITETECH_IT9135_9005 0x9005
#define USB_PID_ITETECH_IT9135_9006 0x9006
#define USB_PID_ITETECH_IT9303 0x9306
#define USB_PID_KWORLD_399U 0xe399
#define USB_PID_KWORLD_399U_2 0xe400
#define USB_PID_KWORLD_395U 0xe396
#define USB_PID_KWORLD_395U_2 0xe39b
#define USB_PID_KWORLD_395U_3 0xe395
#define USB_PID_KWORLD_395U_4 0xe39a
#define USB_PID_KWORLD_MC810 0xc810
#define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_PC160_T 0xc161
#define USB_PID_KWORLD_UB383_T 0xe383
#define USB_PID_KWORLD_UB499_2T_T09 0xe409
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_PROF_1100 0xb012
#define USB_PID_TERRATEC_CINERGY_S 0x0064
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069
#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
#define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097
#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099
#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 0x00a9
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
#define USB_PID_TWINHAN_VP7020_WARM 0x3204
#define USB_PID_TWINHAN_VP7045_COLD 0x3205
#define USB_PID_TWINHAN_VP7045_WARM 0x3206
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
#define USB_PID_TWINHAN_VP7049 0x3219
#define USB_PID_TINYTWIN 0x3226
#define USB_PID_TINYTWIN_2 0xe402
#define USB_PID_TINYTWIN_3 0x9016
#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
#define USB_PID_ARTEC_T14_COLD 0x810b
#define USB_PID_ARTEC_T14_WARM 0x810c
#define USB_PID_ARTEC_T14BR 0x810f
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
#define USB_PID_DTT200U_COLD 0x0201
#define USB_PID_DTT200U_WARM 0x0301
#define USB_PID_WT220U_ZAP250_COLD 0x0220
#define USB_PID_WT220U_COLD 0x0222
#define USB_PID_WT220U_WARM 0x0221
#define USB_PID_WT220U_FC_COLD 0x0225
#define USB_PID_WT220U_FC_WARM 0x0226
#define USB_PID_WT220U_ZL0353_COLD 0x022a
#define USB_PID_WT220U_ZL0353_WARM 0x022b
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
#define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200
#define USB_PID_HAUPPAUGE_TIGER_ATSC 0xb200
#define USB_PID_HAUPPAUGE_TIGER_ATSC_B210 0xb210
#define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
#define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868
#define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039
#define USB_PID_AVERMEDIA_VOLAR_X 0xa815
#define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150
#define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_AVERMEDIA_A310 0xa310
#define USB_PID_AVERMEDIA_A850 0x850a
#define USB_PID_AVERMEDIA_A850T 0x850b
#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_AVERMEDIA_A815M 0x815a
#define USB_PID_AVERMEDIA_A835 0xa835
#define USB_PID_AVERMEDIA_B835 0xb835
#define USB_PID_AVERMEDIA_A835B_1835 0x1835
#define USB_PID_AVERMEDIA_A835B_2835 0x2835
#define USB_PID_AVERMEDIA_A835B_3835 0x3835
#define USB_PID_AVERMEDIA_A835B_4835 0x4835
#define USB_PID_AVERMEDIA_1867 0x1867
#define USB_PID_AVERMEDIA_A867 0xa867
#define USB_PID_AVERMEDIA_H335 0x0335
#define USB_PID_AVERMEDIA_TD110 0xa110
#define USB_PID_AVERMEDIA_TWINSTAR 0x0825
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011
#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012
#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2 0x3015
#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
#define USB_PID_TECHNOTREND_CONNECT_S2_4650_CI 0x3017
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab
#define USB_PID_TERRATEC_CINERGY_S2_R1 0x00a8
#define USB_PID_TERRATEC_CINERGY_S2_R2 0x00b0
#define USB_PID_TERRATEC_CINERGY_S2_R3 0x0102
#define USB_PID_TERRATEC_CINERGY_S2_R4 0x0105
#define USB_PID_TERRATEC_H7 0x10b4
#define USB_PID_TERRATEC_H7_2 0x10a3
#define USB_PID_TERRATEC_H7_3 0x10a5
#define USB_PID_TERRATEC_T1 0x10ae
#define USB_PID_TERRATEC_T3 0x10a0
#define USB_PID_TERRATEC_T5 0x10a1
#define USB_PID_NOXON_DAB_STICK 0x00b3
#define USB_PID_NOXON_DAB_STICK_REV2 0x00e0
#define USB_PID_NOXON_DAB_STICK_REV3 0x00b4
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
#define USB_PID_PINNACLE_PCTV2000E 0x022c
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
#define USB_PID_PINNACLE_PCTV71E 0x022b
#define USB_PID_PINNACLE_PCTV72E 0x0236
#define USB_PID_PINNACLE_PCTV73E 0x0237
#define USB_PID_PINNACLE_PCTV310E 0x3211
#define USB_PID_PINNACLE_PCTV801E 0x023a
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
#define USB_PID_PINNACLE_PCTV340E 0x023d
#define USB_PID_PINNACLE_PCTV340E_SE 0x023e
#define USB_PID_PINNACLE_PCTV73A 0x0243
#define USB_PID_PINNACLE_PCTV73ESE 0x0245
#define USB_PID_PINNACLE_PCTV74E 0x0246
#define USB_PID_PINNACLE_PCTV282E 0x0248
#define USB_PID_PIXELVIEW_SBTVD 0x5010
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
#define USB_PID_PCTV_452E 0x021f
#define USB_PID_PCTV_78E 0x025a
#define USB_PID_PCTV_79E 0x0262
#define USB_PID_REALTEK_RTL2831U 0x2831
#define USB_PID_REALTEK_RTL2832U 0x2832
#define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007
#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a
#define USB_PID_NEBULA_DIGITV 0x0201
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501
#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00
#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01
#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10
#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD 0xdb50
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_MSI_MEGASKY580 0x5580
#define USB_PID_MSI_MEGASKY580_55801 0x5581
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
#define USB_PID_LITEON_DVB_T_COLD 0xf000
#define USB_PID_LITEON_DVB_T_WARM 0xf001
#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360
#define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361
#define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6
#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7
#define USB_PID_WINFAST_DTV2000DS 0x6a04
#define USB_PID_WINFAST_DTV2000DS_PLUS 0x6f12
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
#define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01
#define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029
#define USB_PID_WINFAST_DTV_DONGLE_MINID 0x6f0f
#define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
#define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201
#define USB_PID_GENPIX_8PSK_REV_2 0x0202
#define USB_PID_GENPIX_SKYWALKER_1 0x0203
#define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204
#define USB_PID_GENPIX_SKYWALKER_2 0x0206
#define USB_PID_SIGMATEK_DVB_110 0x6610
#define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513
#define USB_PID_MSI_DIGIVOX_DUO 0x8801
#define USB_PID_OPERA1_COLD 0x2830
#define USB_PID_OPERA1_WARM 0x3829
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
#define USB_PID_GIGABYTE_U7000 0x7001
#define USB_PID_GIGABYTE_U8000 0x7002
#define USB_PID_ASUS_U3000 0x171f
#define USB_PID_ASUS_U3000H 0x1736
#define USB_PID_ASUS_U3100 0x173f
#define USB_PID_ASUS_U3100MINI_PLUS 0x1779
#define USB_PID_YUAN_EC372S 0x1edc
#define USB_PID_YUAN_STK7700PH 0x1f08
#define USB_PID_YUAN_PD378S 0x2edc
#define USB_PID_YUAN_MC770 0x0871
#define USB_PID_YUAN_STK7700D 0x1efc
#define USB_PID_YUAN_STK7700D_2 0x1e8c
#define USB_PID_DW2102 0x2102
#define USB_PID_DW2104 0x2104
#define USB_PID_DW3101 0x3101
#define USB_PID_XTENSIONS_XD_380 0x0381
#define USB_PID_TELESTAR_STARSTICK_2 0x8000
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#define USB_PID_SONY_PLAYTV 0x0003
#define USB_PID_MYGICA_D689 0xd811
#define USB_PID_MYGICA_T230 0xc688
#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
#define USB_PID_ELGATO_EYETV_DTT 0x0021
#define USB_PID_ELGATO_EYETV_DTT_2 0x003f
#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
#define USB_PID_ELGATO_EYETV_SAT 0x002a
#define USB_PID_ELGATO_EYETV_SAT_V2 0x0025
#define USB_PID_ELGATO_EYETV_SAT_V3 0x0036
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001
#define USB_PID_FRIIO_WHITE 0x0001
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
#define USB_PID_SVEON_STV20_RTL2832U 0xd39d
#define USB_PID_SVEON_STV21 0xd3b0
#define USB_PID_SVEON_STV22 0xe401
#define USB_PID_SVEON_STV22_IT9137 0xe411
#define USB_PID_AZUREWAVE_AZ6027 0x3275
#define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4
#define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac
#define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001
#define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002
#define USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI 0x0003
#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004
#define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500
#define USB_PID_CPYTO_REDI_PC50A 0xa803
#define USB_PID_CTVDIGDUAL_V2 0xe410
#define USB_PID_PCTV_2002E 0x025c
#define USB_PID_PCTV_2002E_SE 0x025d
#define USB_PID_SVEON_STV27 0xd3af
#define USB_PID_TURBOX_DTT_2000 0xd3a4
#define USB_PID_WINTV_SOLOHD 0x0264
#define USB_PID_EVOLVEO_XTRATV_STICK 0xa115
#define USB_PID_HAMA_DVBT_HYBRID 0x2758
#endif

View File

@@ -37,8 +37,8 @@
#include <linux/sched/signal.h>
#include <linux/kthread.h>
#include "dvb_ca_en50221.h"
#include "dvb_ringbuffer.h"
#include <media/dvb_ca_en50221.h>
#include <media/dvb_ringbuffer.h>
static int dvb_ca_en50221_debug;
@@ -786,7 +786,7 @@ exit:
* @ca: CA instance.
* @slot: Slot to write to.
* @buf: The data in this buffer is treated as a complete link-level packet to
* be written.
* be written.
* @bytes_write: Size of ebuf.
*
* return: Number of bytes written, or < 0 on error.
@@ -1473,6 +1473,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
return -EFAULT;
buf += 2;
count -= 2;
if (slot >= ca->slot_count)
return -EINVAL;
sl = &ca->slot_info[slot];
/* check if the slot is actually running */

View File

@@ -1,142 +0,0 @@
/*
* dvb_ca.h: generic DVB functions for EN50221 CA interfaces
*
* Copyright (C) 2004 Andrew de Quincey
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _DVB_CA_EN50221_H_
#define _DVB_CA_EN50221_H_
#include <linux/list.h>
#include <linux/dvb/ca.h>
#include "dvbdev.h"
#define DVB_CA_EN50221_POLL_CAM_PRESENT 1
#define DVB_CA_EN50221_POLL_CAM_CHANGED 2
#define DVB_CA_EN50221_POLL_CAM_READY 4
#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1
#define DVB_CA_EN50221_FLAG_IRQ_FR 2
#define DVB_CA_EN50221_FLAG_IRQ_DA 4
#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0
#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1
/**
* 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;
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_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_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 (*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);
int (*poll_slot_status)(struct dvb_ca_en50221 *ca, int slot, int open);
void *data;
void *private;
};
/*
* Functions for reporting IRQ events
*/
/**
* dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred.
*
* @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);
/**
* dvb_ca_en50221_frda_irq - An FR or a DA IRQ has occurred.
*
* @ca: CA instance.
* @slot: Slot concerned.
*/
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *ca, int slot);
/*
* Initialisation/shutdown functions
*/
/**
* dvb_ca_en50221_init - Initialise a new DVB CA device.
*
* @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
*/
int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
struct dvb_ca_en50221 *ca, int flags,
int slot_count);
/**
* dvb_ca_en50221_release - Release a DVB CA device.
*
* @ca: The associated dvb_ca instance.
*/
void dvb_ca_en50221_release(struct dvb_ca_en50221 *ca);
#endif

View File

@@ -30,7 +30,7 @@
#include <linux/uaccess.h>
#include <asm/div64.h>
#include "dvb_demux.h"
#include <media/dvb_demux.h>
static int dvb_demux_tscheck;
module_param(dvb_demux_tscheck, int, 0644);
@@ -119,7 +119,8 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (!ccok)
dprintk("missed packet!\n");
dprintk("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f);
#endif
if (buf[1] & 0x40) // PUSI ?
@@ -188,7 +189,7 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
if (sec->secbufp < sec->tsfeedp) {
int i, n = sec->tsfeedp - sec->secbufp;
int n = sec->tsfeedp - sec->secbufp;
/*
* Section padding is done with 0xff bytes entirely.
@@ -196,12 +197,9 @@ 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) {
dprintk("dvb_demux.c section ts padding loss: %d/%d\n",
dprintk("section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
dprintk("dvb_demux.c pad data:");
for (i = 0; i < n; i++)
pr_cont(" %02x", sec->secbuf[i]);
pr_cont("\n");
dprintk("pad data: %*ph\n", n, sec->secbuf);
}
}
#endif
@@ -240,9 +238,9 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#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);
dprintk("section buffer full loss: %d/%d\n",
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
DMX_MAX_SECFEED_SIZE);
#endif
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
}
@@ -275,7 +273,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
dvb_dmx_swfilter_section_feed(feed);
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
else
dprintk("dvb_demux.c pusi not seen, discarding section data\n");
dprintk("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 */
@@ -310,8 +308,12 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
if (!ccok || dc_i) {
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
dprintk("dvb_demux.c discontinuity detected %d bytes lost\n",
count);
if (dc_i)
dprintk("%d frame with disconnect indicator\n",
cc);
else
dprintk("discontinuity: %d instead of %d. %d bytes lost\n",
cc, (feed->cc + 1) & 0x0f, count + 4);
/*
* those bytes under sume circumstances will again be reported
* in the following dvb_dmx_swfilter_section_new
@@ -320,6 +322,9 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
/*
* Discontinuity detected. Reset pusi_seen to
* stop feeding of suspicious data until next PUSI=1 arrives
*
* FIXME: does it make sense if the MPEG-TS is the one
* reporting discontinuity?
*/
feed->pusi_seen = false;
dvb_dmx_swfilter_section_new(feed);
@@ -343,8 +348,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
}
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
else if (count > 0)
dprintk("dvb_demux.c PUSI=1 but %d bytes lost\n",
count);
dprintk("PUSI=1 but %d bytes lost\n", count);
#endif
} else {
/* PUSI=0 (is not set), no section boundary */
@@ -414,9 +418,10 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
1024);
speed_timedelta = ktime_ms_delta(cur_time,
demux->speed_last_time);
dprintk("TS speed %llu Kbits/sec \n",
div64_u64(speed_bytes,
speed_timedelta));
if (speed_timedelta)
dprintk("TS speed %llu Kbits/sec \n",
div64_u64(speed_bytes,
speed_timedelta));
}
demux->speed_last_time = cur_time;
@@ -441,8 +446,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
demux->cnt_storage[pid] = buf[3] & 0xf;
}
}

View File

@@ -1,345 +0,0 @@
/*
* dvb_demux.h: DVB kernel demux API
*
* Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include "demux.h"
/**
* enum dvb_dmx_filter_type - type of demux feed.
*
* @DMX_TYPE_TS: feed is in TS mode.
* @DMX_TYPE_SEC: feed is in Section mode.
*/
enum dvb_dmx_filter_type {
DMX_TYPE_TS,
DMX_TYPE_SEC,
};
/**
* enum dvb_dmx_state - state machine for a demux filter.
*
* @DMX_STATE_FREE: indicates that the filter is freed.
* @DMX_STATE_ALLOCATED: indicates that the filter was allocated
* to be used.
* @DMX_STATE_READY: indicates that the filter is ready
* to be used.
* @DMX_STATE_GO: indicates that the filter is running.
*/
enum dvb_dmx_state {
DMX_STATE_FREE,
DMX_STATE_ALLOCATED,
DMX_STATE_READY,
DMX_STATE_GO,
};
#define DVB_DEMUX_MASK_MAX 18
#define MAX_PID 0x1fff
#define SPEED_PKTS_INTERVAL 50000
/**
* struct dvb_demux_filter - Describes a DVB demux section filter.
*
* @filter: Section filter as defined by &struct dmx_section_filter.
* @maskandmode: logical ``and`` bit mask.
* @maskandnotmode: logical ``and not`` bit mask.
* @doneq: flag that indicates when a filter is ready.
* @next: pointer to the next section filter.
* @feed: &struct dvb_demux_feed pointer.
* @index: index of the used demux filter.
* @state: state of the filter as described by &enum dvb_dmx_state.
* @type: type of the filter as described
* by &enum dvb_dmx_filter_type.
*/
struct dvb_demux_filter {
struct dmx_section_filter filter;
u8 maskandmode[DMX_MAX_FILTER_SIZE];
u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
bool doneq;
struct dvb_demux_filter *next;
struct dvb_demux_feed *feed;
int index;
enum dvb_dmx_state state;
enum dvb_dmx_filter_type type;
/* private: used only by av7110 */
u16 hw_handle;
};
/**
* struct dvb_demux_feed - describes a DVB field
*
* @feed: a digital TV feed. It can either be a TS or a section feed:
* if the feed is TS, it contains &struct dvb_ts_feed @ts;
* if the feed is section, it contains
* &struct dmx_section_feed @sec.
* @cb: digital TV callbacks. depending on the feed type, it can be:
* if the feed is TS, it contains a dmx_ts_cb() @ts callback;
* if the feed is section, it contains a dmx_section_cb() @sec
* callback.
*
* @demux: pointer to &struct dvb_demux.
* @priv: private data that can optionally be used by a DVB driver.
* @type: type of the filter, as defined by &enum dvb_dmx_filter_type.
* @state: state of the filter as defined by &enum dvb_dmx_state.
* @pid: PID to be filtered.
* @timeout: feed timeout.
* @filter: pointer to &struct dvb_demux_filter.
* @ts_type: type of TS, as defined by &enum ts_filter_type.
* @pes_type: type of PES, as defined by &enum dmx_ts_pes.
* @cc: MPEG-TS packet continuity counter
* @pusi_seen: if true, indicates that a discontinuity was detected.
* it is used to prevent feeding of garbage from previous section.
* @peslen: length of the PES (Packet Elementary Stream).
* @list_head: head for the list of digital TV demux feeds.
* @index: a unique index for each feed. Can be used as hardware
* pid filter index.
*/
struct dvb_demux_feed {
union {
struct dmx_ts_feed ts;
struct dmx_section_feed sec;
} feed;
union {
dmx_ts_cb ts;
dmx_section_cb sec;
} cb;
struct dvb_demux *demux;
void *priv;
enum dvb_dmx_filter_type type;
enum dvb_dmx_state state;
u16 pid;
ktime_t timeout;
struct dvb_demux_filter *filter;
enum ts_filter_type ts_type;
enum dmx_ts_pes pes_type;
int cc;
bool pusi_seen;
u16 peslen;
struct list_head list_head;
unsigned int index;
};
/**
* struct dvb_demux - represents a digital TV demux
* @dmx: embedded &struct dmx_demux with demux capabilities
* and callbacks.
* @priv: private data that can optionally be used by
* a DVB driver.
* @filternum: maximum amount of DVB filters.
* @feednum: maximum amount of DVB feeds.
* @start_feed: callback routine to be called in order to start
* a DVB feed.
* @stop_feed: callback routine to be called in order to stop
* a DVB feed.
* @write_to_decoder: callback routine to be called if the feed is TS and
* it is routed to an A/V decoder, when a new TS packet
* is received.
* Used only on av7110-av.c.
* @check_crc32: callback routine to check CRC. If not initialized,
* dvb_demux will use an internal one.
* @memcopy: callback routine to memcopy received data.
* If not initialized, dvb_demux will default to memcpy().
* @users: counter for the number of demux opened file descriptors.
* Currently, it is limited to 10 users.
* @filter: pointer to &struct dvb_demux_filter.
* @feed: pointer to &struct dvb_demux_feed.
* @frontend_list: &struct list_head with frontends used by the demux.
* @pesfilter: array of &struct dvb_demux_feed with the PES types
* that will be filtered.
* @pids: list of filtered program IDs.
* @feed_list: &struct list_head with feeds.
* @tsbuf: temporary buffer used internally to store TS packets.
* @tsbufp: temporary buffer index used internally.
* @mutex: pointer to &struct mutex used to protect feed set
* logic.
* @lock: pointer to &spinlock_t, used to protect buffer handling.
* @cnt_storage: buffer used for TS/TEI continuity check.
* @speed_last_time: &ktime_t used for TS speed check.
* @speed_pkts_cnt: packets count used for TS speed check.
*/
struct dvb_demux {
struct dmx_demux dmx;
void *priv;
int filternum;
int feednum;
int (*start_feed)(struct dvb_demux_feed *feed);
int (*stop_feed)(struct dvb_demux_feed *feed);
int (*write_to_decoder)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
u32 (*check_crc32)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
int users;
#define MAX_DVB_DEMUX_USERS 10
struct dvb_demux_filter *filter;
struct dvb_demux_feed *feed;
struct list_head frontend_list;
struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
u16 pids[DMX_PES_OTHER];
#define DMX_MAX_PID 0x2000
struct list_head feed_list;
u8 tsbuf[204];
int tsbufp;
struct mutex mutex;
spinlock_t lock;
uint8_t *cnt_storage; /* for TS continuity check */
ktime_t speed_last_time; /* for TS speed check */
uint32_t speed_pkts_cnt; /* for TS speed check */
/* private: used only on av7110 */
int playing;
int recording;
};
/**
* dvb_dmx_init - initialize a digital TV demux struct.
*
* @demux: &struct dvb_demux to be initialized.
*
* Before being able to register a digital TV demux struct, drivers
* should call this routine. On its typical usage, some fields should
* be initialized at the driver before calling it.
*
* A typical usecase is::
*
* dvb->demux.dmx.capabilities =
* DMX_TS_FILTERING | DMX_SECTION_FILTERING |
* DMX_MEMORY_BASED_FILTERING;
* dvb->demux.priv = dvb;
* dvb->demux.filternum = 256;
* dvb->demux.feednum = 256;
* dvb->demux.start_feed = driver_start_feed;
* dvb->demux.stop_feed = driver_stop_feed;
* ret = dvb_dmx_init(&dvb->demux);
* if (ret < 0)
* return ret;
*/
int dvb_dmx_init(struct dvb_demux *demux);
/**
* dvb_dmx_release - releases a digital TV demux internal buffers.
*
* @demux: &struct dvb_demux to be released.
*
* The DVB core internally allocates data at @demux. This routine
* releases those data. Please notice that the struct itelf is not
* released, as it can be embedded on other structs.
*/
void dvb_dmx_release(struct dvb_demux *demux);
/**
* dvb_dmx_swfilter_packets - use dvb software filter for a buffer with
* multiple MPEG-TS packets with 188 bytes each.
*
* @demux: pointer to &struct dvb_demux
* @buf: buffer with data to be filtered
* @count: number of MPEG-TS packets with size of 188.
*
* The routine will discard a DVB packet that don't start with 0x47.
*
* Use this routine if the DVB demux fills MPEG-TS buffers that are
* already aligned.
*
* NOTE: The @buf size should have size equal to ``count * 188``.
*/
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count);
/**
* dvb_dmx_swfilter - use dvb software filter for a buffer with
* multiple MPEG-TS packets with 188 bytes each.
*
* @demux: pointer to &struct dvb_demux
* @buf: buffer with data to be filtered
* @count: number of MPEG-TS packets with size of 188.
*
* If a DVB packet doesn't start with 0x47, it will seek for the first
* byte that starts with 0x47.
*
* Use this routine if the DVB demux fill buffers that may not start with
* a packet start mark (0x47).
*
* NOTE: The @buf size should have size equal to ``count * 188``.
*/
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
/**
* dvb_dmx_swfilter_204 - use dvb software filter for a buffer with
* multiple MPEG-TS packets with 204 bytes each.
*
* @demux: pointer to &struct dvb_demux
* @buf: buffer with data to be filtered
* @count: number of MPEG-TS packets with size of 204.
*
* If a DVB packet doesn't start with 0x47, it will seek for the first
* byte that starts with 0x47.
*
* Use this routine if the DVB demux fill buffers that may not start with
* a packet start mark (0x47).
*
* NOTE: The @buf size should have size equal to ``count * 204``.
*/
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
size_t count);
/**
* dvb_dmx_swfilter_raw - make the raw data available to userspace without
* filtering
*
* @demux: pointer to &struct dvb_demux
* @buf: buffer with data
* @count: number of packets to be passed. The actual size of each packet
* depends on the &dvb_demux->feed->cb.ts logic.
*
* Use it if the driver needs to deliver the raw payload to userspace without
* passing through the kernel demux. That is meant to support some
* delivery systems that aren't based on MPEG-TS.
*
* This function relies on &dvb_demux->feed->cb.ts to actually handle the
* buffer.
*/
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
size_t count);
#endif /* _DVB_DEMUX_H_ */

View File

@@ -40,10 +40,11 @@
#include <linux/jiffies.h>
#include <linux/kthread.h>
#include <linux/ktime.h>
#include <linux/compat.h>
#include <asm/processor.h>
#include "dvb_frontend.h"
#include "dvbdev.h"
#include <media/dvb_frontend.h>
#include <media/dvbdev.h>
#include <linux/dvb/version.h>
static int dvb_frontend_debug;
@@ -150,8 +151,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
dvb_frontend_invoke_release(fe, fe->ops.release);
if (fepriv)
kfree(fepriv);
kfree(fepriv);
}
static void dvb_frontend_free(struct kref *ref)
@@ -982,6 +982,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
}
c->stream_id = NO_STREAM_ID_FILTER;
c->scrambling_sequence_index = 0;/* default sequence */
switch (c->delivery_system) {
case SYS_DVBS:
@@ -1072,6 +1073,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_STREAM_ID, 1, 0),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, 1, 0),
_DTV_CMD(DTV_LNA, 1, 0),
/* Get */
@@ -1417,6 +1419,11 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
tvp->u.data = c->stream_id;
break;
/* Physical layer scrambling support */
case DTV_SCRAMBLING_SEQUENCE_INDEX:
tvp->u.data = c->scrambling_sequence_index;
break;
/* ATSC-MH */
case DTV_ATSCMH_FIC_VER:
tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver;
@@ -1900,6 +1907,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
c->stream_id = data;
break;
/* Physical layer scrambling support */
case DTV_SCRAMBLING_SEQUENCE_INDEX:
c->scrambling_sequence_index = data;
break;
/* ATSC-MH */
case DTV_ATSCMH_PARADE_ID:
fe->dtv_property_cache.atscmh_parade_id = data;
@@ -1923,7 +1935,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
return r;
}
static int dvb_frontend_ioctl(struct file *file, unsigned int cmd, void *parg)
static int dvb_frontend_do_ioctl(struct file *file, unsigned int cmd,
void *parg)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
@@ -1966,6 +1979,156 @@ static int dvb_frontend_ioctl(struct file *file, unsigned int cmd, void *parg)
return err;
}
static long dvb_frontend_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
if (!dvbdev)
return -ENODEV;
return dvb_usercopy(file, cmd, arg, dvb_frontend_do_ioctl);
}
#ifdef CONFIG_COMPAT
struct compat_dtv_property {
__u32 cmd;
__u32 reserved[3];
union {
__u32 data;
struct dtv_fe_stats st;
struct {
__u8 data[32];
__u32 len;
__u32 reserved1[3];
compat_uptr_t reserved2;
} buffer;
} u;
int result;
} __attribute__ ((packed));
struct compat_dtv_properties {
__u32 num;
compat_uptr_t props;
};
#define COMPAT_FE_SET_PROPERTY _IOW('o', 82, struct compat_dtv_properties)
#define COMPAT_FE_GET_PROPERTY _IOR('o', 83, struct compat_dtv_properties)
static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int i, err = 0;
if (cmd == COMPAT_FE_SET_PROPERTY) {
struct compat_dtv_properties prop, *tvps = NULL;
struct compat_dtv_property *tvp = NULL;
if (copy_from_user(&prop, compat_ptr(arg), sizeof(prop)))
return -EFAULT;
tvps = &prop;
/*
* Put an arbitrary limit on the number of messages that can
* be sent at once
*/
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(compat_ptr(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, file,
(tvp + i)->cmd,
(tvp + i)->u.data);
if (err < 0) {
kfree(tvp);
return err;
}
}
kfree(tvp);
} else if (cmd == COMPAT_FE_GET_PROPERTY) {
struct compat_dtv_properties prop, *tvps = NULL;
struct compat_dtv_property *tvp = NULL;
struct dtv_frontend_properties getp = fe->dtv_property_cache;
if (copy_from_user(&prop, compat_ptr(arg), sizeof(prop)))
return -EFAULT;
tvps = &prop;
/*
* Put an arbitrary limit on the number of messages that can
* be sent at once
*/
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(compat_ptr(tvps->props), tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
/*
* 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, &getp, NULL);
if (err < 0) {
kfree(tvp);
return err;
}
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(
fe, &getp, (struct dtv_property *)tvp + i, file);
if (err < 0) {
kfree(tvp);
return err;
}
}
if (copy_to_user((void __user *)compat_ptr(tvps->props), tvp,
tvps->num * sizeof(struct compat_dtv_property))) {
kfree(tvp);
return -EFAULT;
}
kfree(tvp);
}
return err;
}
static long dvb_frontend_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int err;
if (cmd == COMPAT_FE_SET_PROPERTY || cmd == COMPAT_FE_GET_PROPERTY) {
if (down_interruptible(&fepriv->sem))
return -ERESTARTSYS;
err = dvb_frontend_handle_compat_ioctl(file, cmd, arg);
up(&fepriv->sem);
return err;
}
return dvb_frontend_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
}
#endif
static int dtv_set_frontend(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -2110,7 +2273,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i, err;
int i, err = -ENOTSUPP;
dev_dbg(fe->dvb->device, "%s:\n", __func__);
@@ -2145,6 +2308,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
}
}
kfree(tvp);
err = 0;
break;
}
case FE_GET_PROPERTY: {
@@ -2196,6 +2360,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
return -EFAULT;
}
kfree(tvp);
err = 0;
break;
}
@@ -2647,7 +2812,10 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
static const struct file_operations dvb_frontend_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = dvb_generic_ioctl,
.unlocked_ioctl = dvb_frontend_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = dvb_frontend_compat_ioctl,
#endif
.poll = dvb_frontend_poll,
.open = dvb_frontend_open,
.release = dvb_frontend_release,
@@ -2715,7 +2883,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
.name = fe->ops.info.name,
#endif
.kernel_ioctl = dvb_frontend_ioctl
};
dev_dbg(dvb->device, "%s:\n", __func__);

View File

@@ -1,790 +0,0 @@
/*
* 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
*
* Written by Ralph Metzler
* Overhauled by Holger Waechtler
* Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU 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_FRONTEND_H_
#define _DVB_FRONTEND_H_
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/dvb/frontend.h>
#include "dvbdev.h"
/*
* Maximum number of Delivery systems per frontend. It
* should be smaller or equal to 32
*/
#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;
int max_drift;
};
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];
u32 frequency_min;
u32 frequency_max;
u32 frequency_step;
u32 bandwidth_min;
u32 bandwidth_max;
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;
unsigned int audmode;
u64 std;
};
/**
* 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.
*
* @DVBFE_ALGO_SW: Software Algorithm -
* These are dumb devices, that require software to do everything
*
* @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
* or it maybe completely done in hardware. In all cases, usage of
* this algorithm, in conjunction with the search and track
* callbacks, utilizes the driver specific algorithm.
*
* @DVBFE_ALGO_RECOVERY: Recovery Algorithm -
* These devices have AUTO recovery capabilities from LOCK failure
*/
enum dvbfe_algo {
DVBFE_ALGO_HW = (1 << 0),
DVBFE_ALGO_SW = (1 << 1),
DVBFE_ALGO_CUSTOM = (1 << 2),
DVBFE_ALGO_RECOVERY = (1 << 31)
};
/**
* enum dvbfe_search - search callback possible return status
*
* @DVBFE_ALGO_SEARCH_SUCCESS:
* The frontend search algorithm completed and returned successfully
*
* @DVBFE_ALGO_SEARCH_ASLEEP:
* The frontend search algorithm is sleeping
*
* @DVBFE_ALGO_SEARCH_FAILED:
* The frontend search for a signal failed
*
* @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:
* The frontend search algorithm failed due to some error
*
* @DVBFE_ALGO_SEARCH_AGAIN:
* The frontend search algorithm was requested to search again
*/
enum dvbfe_search {
DVBFE_ALGO_SEARCH_SUCCESS = (1 << 0),
DVBFE_ALGO_SEARCH_ASLEEP = (1 << 1),
DVBFE_ALGO_SEARCH_FAILED = (1 << 2),
DVBFE_ALGO_SEARCH_INVALID = (1 << 3),
DVBFE_ALGO_SEARCH_AGAIN = (1 << 4),
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 detached.
* 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 &struct 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 strength. Used mostly to support
* analog TV and radio. Digital TV should report, instead,
* via DVBv5 API (&struct 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;
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 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);
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
#define TUNER_STATUS_LOCKED 1
#define TUNER_STATUS_STEREO 2
int (*get_status)(struct dvb_frontend *fe, u32 *status);
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
/*
* 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.
*
* Don't use on newer drivers.
*/
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 detached.
* 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;
void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);
int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
/** This is to allow setting tuner-specific configuration */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
};
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 &struct
* 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
* &struct 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
*/
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);
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
/* if this is set, it overrides the default swzigzag */
int (*tune)(struct dvb_frontend* fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
enum fe_status *status);
/* get frontend tuning algorithm from the module */
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */
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,
struct dtv_frontend_properties *props);
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);
int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
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,
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);
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
int (*set_lna)(struct dvb_frontend *);
/*
* These callbacks are for devices that implement their own
* tuning algorithms, rather than a simple swzigzag
*/
enum dvbfe_search (*search)(struct dvb_frontend *fe);
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_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;
int eventr;
int overflow;
wait_queue_head_t wait_queue;
struct mutex mtx;
};
#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 {
u32 frequency;
enum fe_modulation modulation;
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 */
enum fe_guard_interval guard_interval;
enum fe_hierarchy hierarchy;
u32 symbol_rate;
enum fe_code_rate code_rate_HP;
enum fe_code_rate code_rate_LP;
enum fe_pilot pilot;
enum fe_rolloff rolloff;
enum fe_delivery_system delivery_system;
enum fe_interleaving interleaving;
/* ISDB-T specifics */
u8 isdbt_partial_reception;
u8 isdbt_sb_mode;
u8 isdbt_sb_subchannel;
u32 isdbt_sb_segment_idx;
u32 isdbt_sb_segment_count;
u8 isdbt_layer_enabled;
struct {
u8 segment_count;
enum fe_code_rate fec;
enum fe_modulation modulation;
u8 interleaving;
} layer[3];
/* Multistream specifics */
u32 stream_id;
/* ATSC-MH specifics */
u8 atscmh_fic_ver;
u8 atscmh_parade_id;
u8 atscmh_nog;
u8 atscmh_tnog;
u8 atscmh_sgn;
u8 atscmh_prc;
u8 atscmh_rs_frame_mode;
u8 atscmh_rs_frame_ensemble;
u8 atscmh_rs_code_mode_pri;
u8 atscmh_rs_code_mode_sec;
u8 atscmh_sccc_block_mode;
u8 atscmh_sccc_code_mode_a;
u8 atscmh_sccc_code_mode_b;
u8 atscmh_sccc_code_mode_c;
u8 atscmh_sccc_code_mode_d;
u32 lna;
/* statistics data */
struct dtv_fe_stats strength;
struct dtv_fe_stats cnr;
struct dtv_fe_stats pre_bit_error;
struct dtv_fe_stats pre_bit_count;
struct dtv_fe_stats post_bit_error;
struct dtv_fe_stats post_bit_count;
struct dtv_fe_stats block_error;
struct dtv_fe_stats block_count;
};
#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;
void *tuner_priv;
void *frontend_priv;
void *sec_priv;
void *analog_demod_priv;
struct dtv_frontend_properties dtv_property_cache;
#define DVB_FRONTEND_COMPONENT_TUNER 0
#define DVB_FRONTEND_COMPONENT_DEMOD 1
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
unsigned int exit;
};
/**
* dvb_register_frontend() - Registers a DVB frontend at the adapter
*
* @dvb: pointer to &struct dvb_adapter
* @fe: pointer to &struct dvb_frontend
*
* 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);
/**
* dvb_unregister_frontend() - Unregisters a DVB frontend
*
* @fe: pointer to &struct dvb_frontend
*
* 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);
/**
* dvb_frontend_detach() - Detaches and frees frontend specific data
*
* @fe: pointer to &struct dvb_frontend
*
* 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);
/**
* dvb_frontend_suspend() - Suspends a Digital TV frontend
*
* @fe: pointer to &struct dvb_frontend
*
* 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);
/**
* dvb_frontend_resume() - Resumes a Digital TV frontend
*
* @fe: pointer to &struct dvb_frontend
*
* 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 &struct dvb_frontend
*
* 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 &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

View File

@@ -19,7 +19,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/bug.h>
#include "dvb_math.h"
#include <media/dvb_math.h>
static const unsigned short logtable[256] = {
0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,

View File

@@ -1,66 +0,0 @@
/*
* dvb-math provides some complex fixed-point math
* operations shared between the dvb related stuff
*
* Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#ifndef __DVB_MATH_H
#define __DVB_MATH_H
#include <linux/types.h>
/**
* 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
*
* Some usecase examples:
*
* 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);
/**
* 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
*
* 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
*
* return: log10(value) * 2^24
*/
extern unsigned int intlog10(u32 value);
#endif

View File

@@ -38,7 +38,7 @@
* Competence Center for Advanced Satellite Communications.
* Bugfixes and robustness improvements.
* Filtering on dest MAC addresses, if present (D-Bit = 0)
* ULE_DEBUG compile-time option.
* DVB_ULE_DEBUG compile-time option.
* Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by
* Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
* Paris Lodron University of Salzburg.
@@ -64,8 +64,8 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include "dvb_demux.h"
#include "dvb_net.h"
#include <media/dvb_demux.h>
#include <media/dvb_net.h>
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{
@@ -78,15 +78,18 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
#define DVB_NET_MULTICAST_MAX 10
#undef ULE_DEBUG
#ifdef ULE_DEBUG
#ifdef DVB_ULE_DEBUG
/*
* The code inside DVB_ULE_DEBUG keeps a history of the
* last 100 TS cells processed.
*/
static unsigned char ule_hist[100*TS_SZ] = { 0 };
static unsigned char *ule_where = ule_hist, ule_dump;
static void hexdump(const unsigned char *buf, unsigned short len)
{
print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
}
#endif
struct dvb_net_priv {
@@ -280,11 +283,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
if (l < 0)
return l; /* Stop extension header processing and discard SNDU. */
total_ext_len += l;
#ifdef ULE_DEBUG
pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n",
p->ule_next_hdr, (int)p->ule_sndu_type,
l, total_ext_len);
#endif
} while (p->ule_sndu_type < ETH_P_802_3_MIN);
@@ -320,29 +321,21 @@ struct dvb_net_ule_handle {
const u8 *ts, *ts_end, *from_where;
u8 ts_remain, how_much, new_ts;
bool error;
#ifdef ULE_DEBUG
/*
* The code inside ULE_DEBUG keeps a history of the
* last 100 TS cells processed.
*/
static unsigned char ule_hist[100*TS_SZ];
static unsigned char *ule_where = ule_hist, ule_dump;
#endif
};
static int dvb_net_ule_new_ts_cell(struct dvb_net_ule_handle *h)
{
/* We are about to process a new TS cell. */
#ifdef ULE_DEBUG
if (h->ule_where >= &h->ule_hist[100*TS_SZ])
h->ule_where = h->ule_hist;
memcpy(h->ule_where, h->ts, TS_SZ);
if (h->ule_dump) {
hexdump(h->ule_where, TS_SZ);
h->ule_dump = 0;
#ifdef DVB_ULE_DEBUG
if (ule_where >= &ule_hist[100*TS_SZ])
ule_where = ule_hist;
memcpy(ule_where, h->ts, TS_SZ);
if (ule_dump) {
hexdump(ule_where, TS_SZ);
ule_dump = 0;
}
h->ule_where += TS_SZ;
ule_where += TS_SZ;
#endif
/*
@@ -660,6 +653,7 @@ static int dvb_net_ule_should_drop(struct dvb_net_ule_handle *h)
static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
struct kvec iov[3],
u32 ule_crc, u32 expected_crc)
{
u8 dest_addr[ETH_ALEN];
@@ -672,22 +666,22 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
h->ts_remain > 2 ?
*(unsigned short *)h->from_where : 0);
#ifdef ULE_DEBUG
#ifdef DVB_ULE_DEBUG
hexdump(iov[0].iov_base, iov[0].iov_len);
hexdump(iov[1].iov_base, iov[1].iov_len);
hexdump(iov[2].iov_base, iov[2].iov_len);
if (h->ule_where == h->ule_hist) {
hexdump(&h->ule_hist[98*TS_SZ], TS_SZ);
hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
} else if (h->ule_where == &h->ule_hist[TS_SZ]) {
hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
hexdump(h->ule_hist, TS_SZ);
if (ule_where == ule_hist) {
hexdump(&ule_hist[98*TS_SZ], TS_SZ);
hexdump(&ule_hist[99*TS_SZ], TS_SZ);
} else if (ule_where == &ule_hist[TS_SZ]) {
hexdump(&ule_hist[99*TS_SZ], TS_SZ);
hexdump(ule_hist, TS_SZ);
} else {
hexdump(h->ule_where - TS_SZ - TS_SZ, TS_SZ);
hexdump(h->ule_where - TS_SZ, TS_SZ);
hexdump(ule_where - TS_SZ - TS_SZ, TS_SZ);
hexdump(ule_where - TS_SZ, TS_SZ);
}
h->ule_dump = 1;
ule_dump = 1;
#endif
h->dev->stats.rx_errors++;
@@ -705,11 +699,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
if (!h->priv->ule_dbit) {
if (dvb_net_ule_should_drop(h)) {
#ifdef ULE_DEBUG
netdev_dbg(h->dev,
"Dropping SNDU: MAC destination address does not match: dest addr: %pM, h->dev addr: %pM\n",
h->priv->ule_skb->data, h->dev->dev_addr);
#endif
dev_kfree_skb(h->priv->ule_skb);
return;
}
@@ -779,6 +771,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
int ret;
struct dvb_net_ule_handle h = {
.dev = dev,
.priv = netdev_priv(dev),
.ethh = NULL,
.buf = buf,
.buf_len = buf_len,
.skipped = 0L,
@@ -788,11 +782,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
.ts_remain = 0,
.how_much = 0,
.new_ts = 1,
.ethh = NULL,
.error = false,
#ifdef ULE_DEBUG
.ule_where = ule_hist,
#endif
};
/*
@@ -860,7 +850,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
*(tail - 2) << 8 |
*(tail - 1);
dvb_net_ule_check_crc(&h, ule_crc, expected_crc);
dvb_net_ule_check_crc(&h, iov, ule_crc, expected_crc);
/* Prepare for next SNDU. */
reset_ule(h.priv);

View File

@@ -1,93 +0,0 @@
/*
* dvb_net.h
*
* Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DVB_NET_H_
#define _DVB_NET_H_
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include "dvbdev.h"
#define DVB_NET_DEVICES_MAX 10
#ifdef CONFIG_DVB_NET
/**
* struct dvb_net - describes a DVB network interface
*
* @dvbdev: pointer to &struct dvb_device.
* @device: array of pointers to &struct net_device.
* @state: array of integers to each net device. A value
* different than zero means that the interface is
* in usage.
* @exit: flag to indicate when the device is being removed.
* @demux: pointer to &struct dmx_demux.
* @ioctl_mutex: protect access to this struct.
*
* Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
* devices.
*/
struct dvb_net {
struct dvb_device *dvbdev;
struct net_device *device[DVB_NET_DEVICES_MAX];
int state[DVB_NET_DEVICES_MAX];
unsigned int exit:1;
struct dmx_demux *demux;
struct mutex ioctl_mutex;
};
/**
* dvb_net_init - nitializes a digital TV network device and registers it.
*
* @adap: pointer to &struct dvb_adapter.
* @dvbnet: pointer to &struct dvb_net.
* @dmxdemux: pointer to &struct dmx_demux.
*/
int dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet,
struct dmx_demux *dmxdemux);
/**
* dvb_net_release - releases a digital TV network device and unregisters it.
*
* @dvbnet: pointer to &struct dvb_net.
*/
void dvb_net_release(struct dvb_net *dvbnet);
#else
struct dvb_net {
struct dvb_device *dvbdev;
};
static inline void dvb_net_release(struct dvb_net *dvbnet)
{
}
static inline int dvb_net_init(struct dvb_adapter *adap,
struct dvb_net *dvbnet, struct dmx_demux *dmx)
{
return 0;
}
#endif /* ifdef CONFIG_DVB_NET */
#endif

View File

@@ -29,7 +29,7 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include "dvb_ringbuffer.h"
#include <media/dvb_ringbuffer.h>
#define PKT_READY 0
#define PKT_DISPOSED 1

View File

@@ -1,280 +0,0 @@
/*
*
* dvb_ringbuffer.h: ring buffer implementation for the dvb driver
*
* Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
*
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#ifndef _DVB_RINGBUFFER_H_
#define _DVB_RINGBUFFER_H_
#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;
ssize_t pread;
ssize_t pwrite;
int error;
wait_queue_head_t queue;
spinlock_t lock;
};
#define DVB_RINGBUFFER_PKTHDRSIZE 3
/**
* 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);
/**
* dvb_ringbuffer_empty - test whether buffer is empty
*
* @rbuf: pointer to struct dvb_ringbuffer
*/
extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
/**
* 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);
/**
* 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);
/**
* 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
*/
/**
* dvb_ringbuffer_flush - flush buffer
*
* @rbuf: pointer to struct dvb_ringbuffer
*/
extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
/**
* 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);
/**
* 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])
/**
* 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;\
}
/**
* 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
*/
/**
* 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; }
/**
* 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);
/**
* 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).
*
* 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);
/**
* 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.
*
* 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(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8 *buf, size_t len);
/**
* 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().
*/
extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
/**
* 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.
* 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);
#endif /* _DVB_RINGBUFFER_H_ */

View File

@@ -0,0 +1,430 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dvb-vb2.c - dvb-vb2
*
* Copyright (C) 2015 Samsung Electronics
*
* Author: jh1009.sung@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <media/dvbdev.h>
#include <media/dvb_vb2.h>
#define DVB_V2_MAX_SIZE (4096 * 188)
static int vb2_debug;
module_param(vb2_debug, int, 0644);
#define dprintk(level, fmt, arg...) \
do { \
if (vb2_debug >= level) \
pr_info("vb2: %s: " fmt, __func__, ## arg); \
} while (0)
static int _queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], struct device *alloc_devs[])
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
ctx->buf_cnt = *nbuffers;
*nplanes = 1;
sizes[0] = ctx->buf_siz;
/*
* videobuf2-vmalloc allocator is context-less so no need to set
* alloc_ctxs array.
*/
dprintk(3, "[%s] count=%d, size=%d\n", ctx->name,
*nbuffers, sizes[0]);
return 0;
}
static int _buffer_prepare(struct vb2_buffer *vb)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size = ctx->buf_siz;
if (vb2_plane_size(vb, 0) < size) {
dprintk(1, "[%s] data will not fit into plane (%lu < %lu)\n",
ctx->name, vb2_plane_size(vb, 0), size);
return -EINVAL;
}
vb2_set_plane_payload(vb, 0, size);
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
static void _buffer_queue(struct vb2_buffer *vb)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct dvb_buffer *buf = container_of(vb, struct dvb_buffer, vb);
unsigned long flags = 0;
spin_lock_irqsave(&ctx->slock, flags);
list_add_tail(&buf->list, &ctx->dvb_q);
spin_unlock_irqrestore(&ctx->slock, flags);
dprintk(3, "[%s]\n", ctx->name);
}
static int _start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
dprintk(3, "[%s] count=%d\n", ctx->name, count);
return 0;
}
static void _stop_streaming(struct vb2_queue *vq)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
struct dvb_buffer *buf;
unsigned long flags = 0;
dprintk(3, "[%s]\n", ctx->name);
spin_lock_irqsave(&ctx->slock, flags);
while (!list_empty(&ctx->dvb_q)) {
buf = list_entry(ctx->dvb_q.next,
struct dvb_buffer, list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
list_del(&buf->list);
}
spin_unlock_irqrestore(&ctx->slock, flags);
}
static void _dmxdev_lock(struct vb2_queue *vq)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
mutex_lock(&ctx->mutex);
dprintk(3, "[%s]\n", ctx->name);
}
static void _dmxdev_unlock(struct vb2_queue *vq)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
if (mutex_is_locked(&ctx->mutex))
mutex_unlock(&ctx->mutex);
dprintk(3, "[%s]\n", ctx->name);
}
static const struct vb2_ops dvb_vb2_qops = {
.queue_setup = _queue_setup,
.buf_prepare = _buffer_prepare,
.buf_queue = _buffer_queue,
.start_streaming = _start_streaming,
.stop_streaming = _stop_streaming,
.wait_prepare = _dmxdev_unlock,
.wait_finish = _dmxdev_lock,
};
static void _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct dmx_buffer *b = pb;
b->index = vb->index;
b->length = vb->planes[0].length;
b->bytesused = vb->planes[0].bytesused;
b->offset = vb->planes[0].m.offset;
dprintk(3, "[%s]\n", ctx->name);
}
static int _fill_vb2_buffer(struct vb2_buffer *vb,
const void *pb, struct vb2_plane *planes)
{
struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
planes[0].bytesused = 0;
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
static const struct vb2_buf_ops dvb_vb2_buf_ops = {
.fill_user_buffer = _fill_dmx_buffer,
.fill_vb2_buffer = _fill_vb2_buffer,
};
/*
* Videobuf operations
*/
int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
{
struct vb2_queue *q = &ctx->vb_q;
int ret;
memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
q->type = DVB_BUF_TYPE_CAPTURE;
/**capture type*/
q->is_output = 0;
/**only mmap is supported currently*/
q->io_modes = VB2_MMAP;
q->drv_priv = ctx;
q->buf_struct_size = sizeof(struct dvb_buffer);
q->min_buffers_needed = 1;
q->ops = &dvb_vb2_qops;
q->mem_ops = &vb2_vmalloc_memops;
q->buf_ops = &dvb_vb2_buf_ops;
q->num_buffers = 0;
ret = vb2_core_queue_init(q);
if (ret) {
ctx->state = DVB_VB2_STATE_NONE;
dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret;
}
mutex_init(&ctx->mutex);
spin_lock_init(&ctx->slock);
INIT_LIST_HEAD(&ctx->dvb_q);
strlcpy(ctx->name, name, DVB_VB2_NAME_MAX);
ctx->nonblocking = nonblocking;
ctx->state = DVB_VB2_STATE_INIT;
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
{
struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
if (ctx->state & DVB_VB2_STATE_INIT)
vb2_core_queue_release(q);
ctx->state = DVB_VB2_STATE_NONE;
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx)
{
struct vb2_queue *q = &ctx->vb_q;
int ret;
ret = vb2_core_streamon(q, q->type);
if (ret) {
ctx->state = DVB_VB2_STATE_NONE;
dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret;
}
ctx->state |= DVB_VB2_STATE_STREAMON;
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx)
{
struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
int ret;
ctx->state &= ~DVB_VB2_STATE_STREAMON;
ret = vb2_core_streamoff(q, q->type);
if (ret) {
ctx->state = DVB_VB2_STATE_NONE;
dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret;
}
dprintk(3, "[%s]\n", ctx->name);
return 0;
}
int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
{
return (ctx->state & DVB_VB2_STATE_STREAMON);
}
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
const unsigned char *src, int len)
{
unsigned long flags = 0;
void *vbuf = NULL;
int todo = len;
unsigned char *psrc = (unsigned char *)src;
int ll = 0;
dprintk(3, "[%s] %d bytes are rcvd\n", ctx->name, len);
if (!src) {
dprintk(3, "[%s]:NULL pointer src\n", ctx->name);
/**normal case: This func is called twice from demux driver
* once with valid src pointer, second time with NULL pointer
*/
return 0;
}
spin_lock_irqsave(&ctx->slock, flags);
while (todo) {
if (!ctx->buf) {
if (list_empty(&ctx->dvb_q)) {
dprintk(3, "[%s] Buffer overflow!!!\n",
ctx->name);
break;
}
ctx->buf = list_entry(ctx->dvb_q.next,
struct dvb_buffer, list);
ctx->remain = vb2_plane_size(&ctx->buf->vb, 0);
ctx->offset = 0;
}
if (!dvb_vb2_is_streaming(ctx)) {
vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR);
list_del(&ctx->buf->list);
ctx->buf = NULL;
break;
}
/* Fill buffer */
ll = min(todo, ctx->remain);
vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0);
memcpy(vbuf + ctx->offset, psrc, ll);
todo -= ll;
psrc += ll;
ctx->remain -= ll;
ctx->offset += ll;
if (ctx->remain == 0) {
vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
list_del(&ctx->buf->list);
ctx->buf = NULL;
}
}
if (ctx->nonblocking && ctx->buf) {
vb2_set_plane_payload(&ctx->buf->vb, 0, ll);
vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
list_del(&ctx->buf->list);
ctx->buf = NULL;
}
spin_unlock_irqrestore(&ctx->slock, flags);
if (todo)
dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo);
else
dprintk(3, "[%s]\n", ctx->name);
dprintk(3, "[%s] %d bytes are copied\n", ctx->name, len - todo);
return (len - todo);
}
int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
{
int ret;
/* Adjust size to a sane value */
if (req->size > DVB_V2_MAX_SIZE)
req->size = DVB_V2_MAX_SIZE;
/* FIXME: round req->size to a 188 or 204 multiple */
ctx->buf_siz = req->size;
ctx->buf_cnt = req->count;
ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
if (ret) {
ctx->state = DVB_VB2_STATE_NONE;
dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,
ctx->buf_cnt, ctx->buf_siz, ret);
return ret;
}
ctx->state |= DVB_VB2_STATE_REQBUFS;
dprintk(3, "[%s] count=%d size=%d\n", ctx->name,
ctx->buf_cnt, ctx->buf_siz);
return 0;
}
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
vb2_core_querybuf(&ctx->vb_q, b->index, b);
dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
return 0;
}
int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
{
struct vb2_queue *q = &ctx->vb_q;
int ret;
ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index,
0, exp->flags);
if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
exp->index, ret);
return ret;
}
dprintk(3, "[%s] index=%d fd=%d\n", ctx->name, exp->index, exp->fd);
return 0;
}
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
int ret;
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b);
if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
b->index, ret);
return ret;
}
dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
return 0;
}
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
int ret;
ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
if (ret) {
dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret;
}
dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
return 0;
}
int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma)
{
int ret;
ret = vb2_mmap(&ctx->vb_q, vma);
if (ret) {
dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
return ret;
}
dprintk(3, "[%s] ret=%d\n", ctx->name, ret);
return 0;
}
unsigned int dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file,
poll_table *wait)
{
dprintk(3, "[%s]\n", ctx->name);
return vb2_core_poll(&ctx->vb_q, file, wait);
}

View File

@@ -30,7 +30,7 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include "dvbdev.h"
#include <media/dvbdev.h>
/* Due to enum tuner_pad_index */
#include <media/tuner.h>

View File

@@ -1,407 +0,0 @@
/*
* dvbdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DVBDEV_H_
#define _DVBDEV_H_
#include <linux/types.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <media/media-device.h>
#define DVB_MAJOR 212
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
#else
#define DVB_MAX_ADAPTERS 16
#endif
#define DVB_UNSET (-1)
/* List of DVB device types */
/**
* enum dvb_device_type - type of the Digital TV device
*
* @DVB_DEVICE_SEC: Digital TV standalone Common Interface (CI)
* @DVB_DEVICE_FRONTEND: Digital TV frontend.
* @DVB_DEVICE_DEMUX: Digital TV demux.
* @DVB_DEVICE_DVR: Digital TV digital video record (DVR).
* @DVB_DEVICE_CA: Digital TV Conditional Access (CA).
* @DVB_DEVICE_NET: Digital TV network.
*
* @DVB_DEVICE_VIDEO: Digital TV video decoder.
* Deprecated. Used only on av7110-av.
* @DVB_DEVICE_AUDIO: Digital TV audio decoder.
* Deprecated. Used only on av7110-av.
* @DVB_DEVICE_OSD: Digital TV On Screen Display (OSD).
* Deprecated. Used only on av7110.
*/
enum dvb_device_type {
DVB_DEVICE_SEC,
DVB_DEVICE_FRONTEND,
DVB_DEVICE_DEMUX,
DVB_DEVICE_DVR,
DVB_DEVICE_CA,
DVB_DEVICE_NET,
DVB_DEVICE_VIDEO,
DVB_DEVICE_AUDIO,
DVB_DEVICE_OSD,
};
#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
static short adapter_nr[] = \
{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
module_param_array(adapter_nr, short, NULL, 0444); \
MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
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;
struct list_head device_list;
const char *name;
u8 proposed_mac [6];
void* priv;
struct device *device;
struct module *module;
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, as defined by &enum dvb_device_type.
* @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;
struct dvb_adapter *adapter;
enum dvb_device_type type;
int minor;
u32 id;
/* in theory, 'users' can vanish now,
but I don't want to change too much now... */
int readers;
int writers;
int users;
wait_queue_head_t wait_queue;
/* 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;
};
/**
* 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);
/**
* 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, as defined by &enum dvb_device_type.
* @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,
enum dvb_device_type type,
int demux_sink_pads);
/**
* 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);
/**
* 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);
/**
* dvb_register_media_controller - registers a media controller at DVB adapter
*
* @adap: pointer to &struct dvb_adapter
* @mdev: pointer to &struct media_device
*/
static inline void dvb_register_media_controller(struct dvb_adapter *adap,
struct media_device *mdev)
{
adap->mdev = mdev;
}
/**
* dvb_get_media_controller - gets the associated media controller
*
* @adap: pointer to &struct dvb_adapter
*/
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
/**
* dvb_generic_open - Digital TV open function, used by DVB devices
*
* @inode: pointer to &struct inode.
* @file: pointer to &struct file.
*
* Checks if a DVB devnode is still valid, and if the permissions are
* OK and increment negative use count.
*/
int dvb_generic_open(struct inode *inode, struct file *file);
/**
* dvb_generic_close - Digital TV close function, used by DVB devices
*
* @inode: pointer to &struct inode.
* @file: pointer to &struct file.
*
* Checks if a DVB devnode is still valid, and if the permissions are
* OK and decrement negative use count.
*/
int dvb_generic_release(struct inode *inode, struct file *file);
/**
* dvb_generic_ioctl - Digital TV close function, used by DVB devices
*
* @file: pointer to &struct file.
* @cmd: Ioctl name.
* @arg: Ioctl argument.
*
* Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid.
* If so, calls dvb_usercopy().
*/
long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
/**
* dvb_usercopy - copies data from/to userspace memory when an ioctl is
* issued.
*
* @file: Pointer to struct &file.
* @cmd: Ioctl name.
* @arg: Ioctl argument.
* @func: function that will actually handle the ioctl
*
* Ancillary function that uses ioctl direction and size to copy from
* userspace. Then, it calls @func, and, if needed, data is copied back
* to userspace.
*/
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. */
#ifdef CONFIG_MEDIA_ATTACH
/**
* dvb_attach - attaches a DVB frontend into the DVB core.
*
* @FUNCTION: function on a frontend module to be called.
* @ARGS...: @FUNCTION arguments.
*
* This ancillary function loads a frontend module in runtime and runs
* the @FUNCTION function there, with @ARGS.
* As it increments symbol usage cont, at unregister, dvb_detach()
* should be called.
*/
#define dvb_attach(FUNCTION, ARGS...) ({ \
void *__r = NULL; \
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
if (__a) { \
__r = (void *) __a(ARGS); \
if (__r == NULL) \
symbol_put(FUNCTION); \
} else { \
printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
} \
__r; \
})
/**
* dvb_detach - detaches a DVB frontend loaded via dvb_attach()
*
* @FUNC: attach function
*
* Decrements usage count for a function previously called via dvb_attach().
*/
#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_ */