diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core')
20 files changed, 0 insertions, 11335 deletions
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile deleted file mode 100644 index 0b5182835cc..00000000000 --- a/drivers/media/dvb/dvb-core/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the kernel DVB device drivers. -# - -dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\ -		 dvb_ca_en50221.o dvb_frontend.o 		\ -		 dvb_net.o dvb_ringbuffer.o dvb_math.o - -obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h deleted file mode 100644 index eb91fd808c1..00000000000 --- a/drivers/media/dvb/dvb-core/demux.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * demux.h - * - * 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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#ifndef __DEMUX_H -#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 - - -/* - * enum dmx_success: Success codes for the Demux Callback API. - */ - -enum dmx_success { -  DMX_OK = 0, /* Received Ok */ -  DMX_LENGTH_ERROR, /* Incorrect length */ -  DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ -  DMX_CRC_ERROR, /* Incorrect CRC */ -  DMX_FRAME_ERROR, /* Frame alignment error */ -  DMX_FIFO_ERROR, /* Receiver FIFO overrun */ -  DMX_MISSED_ERROR /* Receiver missed packet */ -} ; - -/*--------------------------------------------------------------------------*/ -/* TS packet reception */ -/*--------------------------------------------------------------------------*/ - -/* TS filter type for set() */ - -#define TS_PACKET       1   /* send TS packets (188 bytes) to callback (default) */ -#define	TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS -			       payload (<=184 bytes per packet) to callback */ -#define TS_DECODER      4   /* send stream to built-in decoder (if present) */ -#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to -			       the demux device, not to the dvr device */ - -/* PES type for filters which write to built-in decoder */ -/* these should be kept identical to the types in dmx.h */ - -enum dmx_ts_pes -{  /* also send packets to decoder (if it exists) */ -	DMX_TS_PES_AUDIO0, -	DMX_TS_PES_VIDEO0, -	DMX_TS_PES_TELETEXT0, -	DMX_TS_PES_SUBTITLE0, -	DMX_TS_PES_PCR0, - -	DMX_TS_PES_AUDIO1, -	DMX_TS_PES_VIDEO1, -	DMX_TS_PES_TELETEXT1, -	DMX_TS_PES_SUBTITLE1, -	DMX_TS_PES_PCR1, - -	DMX_TS_PES_AUDIO2, -	DMX_TS_PES_VIDEO2, -	DMX_TS_PES_TELETEXT2, -	DMX_TS_PES_SUBTITLE2, -	DMX_TS_PES_PCR2, - -	DMX_TS_PES_AUDIO3, -	DMX_TS_PES_VIDEO3, -	DMX_TS_PES_TELETEXT3, -	DMX_TS_PES_SUBTITLE3, -	DMX_TS_PES_PCR3, - -	DMX_TS_PES_OTHER -}; - -#define DMX_TS_PES_AUDIO    DMX_TS_PES_AUDIO0 -#define DMX_TS_PES_VIDEO    DMX_TS_PES_VIDEO0 -#define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0 -#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0 -#define DMX_TS_PES_PCR      DMX_TS_PES_PCR0 - - -struct dmx_ts_feed { -	int is_filtering; /* Set to non-zero when filtering in progress */ -	struct dmx_demux *parent; /* Back-pointer */ -	void *priv; /* Pointer to private data of the API client */ -	int (*set) (struct dmx_ts_feed *feed, -		    u16 pid, -		    int type, -		    enum dmx_ts_pes pes_type, -		    size_t circular_buffer_size, -		    struct timespec timeout); -	int (*start_filtering) (struct dmx_ts_feed* feed); -	int (*stop_filtering) (struct dmx_ts_feed* feed); -}; - -/*--------------------------------------------------------------------------*/ -/* Section reception */ -/*--------------------------------------------------------------------------*/ - -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 { -	int is_filtering; /* Set to non-zero when filtering in progress */ -	struct dmx_demux* parent; /* Back-pointer */ -	void* priv; /* Pointer to private data of the API client */ - -	int check_crc; -	u32 crc_val; - -	u8 *secbuf; -	u8 secbuf_base[DMX_MAX_SECFEED_SIZE]; -	u16 secbufp, seclen, tsfeedp; - -	int (*set) (struct dmx_section_feed* feed, -		    u16 pid, -		    size_t circular_buffer_size, -		    int check_crc); -	int (*allocate_filter) (struct dmx_section_feed* feed, -				struct dmx_section_filter** filter); -	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); -}; - -/*--------------------------------------------------------------------------*/ -/* Callback functions */ -/*--------------------------------------------------------------------------*/ - -typedef int (*dmx_ts_cb) ( const u8 * buffer1, -			   size_t buffer1_length, -			   const u8 * buffer2, -			   size_t buffer2_length, -			   struct dmx_ts_feed* source, -			   enum dmx_success success); - -typedef int (*dmx_section_cb) (	const u8 * buffer1, -				size_t buffer1_len, -				const u8 * buffer2, -				size_t buffer2_len, -				struct dmx_section_filter * source, -				enum dmx_success success); - -/*--------------------------------------------------------------------------*/ -/* DVB Front-End */ -/*--------------------------------------------------------------------------*/ - -enum dmx_frontend_source { -	DMX_MEMORY_FE, -	DMX_FRONTEND_0, -	DMX_FRONTEND_1, -	DMX_FRONTEND_2, -	DMX_FRONTEND_3, -	DMX_STREAM_0,    /* external stream input, e.g. LVDS */ -	DMX_STREAM_1, -	DMX_STREAM_2, -	DMX_STREAM_3 -}; - -struct dmx_frontend { -	struct list_head connectivity_list; /* List of front-ends that can -					       be connected to a particular -					       demux */ -	enum dmx_frontend_source source; -}; - -/*--------------------------------------------------------------------------*/ -/* MPEG-2 TS Demux */ -/*--------------------------------------------------------------------------*/ - -/* - * Flags OR'ed in the capabilities field of struct dmx_demux. - */ - -#define DMX_TS_FILTERING                        1 -#define DMX_PES_FILTERING                       2 -#define DMX_SECTION_FILTERING                   4 -#define DMX_MEMORY_BASED_FILTERING              8    /* write() available */ -#define DMX_CRC_CHECKING                        16 -#define DMX_TS_DESCRAMBLING                     32 - -/* - * 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 - *. -*/ - -#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list) - -struct dmx_demux { -	u32 capabilities;            /* Bitfield of capability flags */ -	struct dmx_frontend* frontend;    /* Front-end connected to the demux */ -	void* priv;                  /* Pointer to private data of the API client */ -	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); - -	int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps); - -	int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src); - -	int (*get_stc) (struct dmx_demux* demux, unsigned int num, -			u64 *stc, unsigned int *base); -}; - -#endif /* #ifndef __DEMUX_H */ diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c deleted file mode 100644 index ad1f61d301e..00000000000 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * dmxdev.c - DVB demultiplexer device - * - * 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. - * - * 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. - * - */ - -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/ioctl.h> -#include <linux/wait.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include "dmxdev.h" - -static int debug; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); - -#define dprintk	if (debug) printk - -static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, -				   const u8 *src, size_t len) -{ -	ssize_t free; - -	if (!len) -		return 0; -	if (!buf->data) -		return 0; - -	free = dvb_ringbuffer_free(buf); -	if (len > free) { -		dprintk("dmxdev: buffer overflow\n"); -		return -EOVERFLOW; -	} - -	return dvb_ringbuffer_write(buf, src, len); -} - -static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, -				      int non_blocking, char __user *buf, -				      size_t count, loff_t *ppos) -{ -	size_t todo; -	ssize_t avail; -	ssize_t ret = 0; - -	if (!src->data) -		return 0; - -	if (src->error) { -		ret = src->error; -		dvb_ringbuffer_flush(src); -		return ret; -	} - -	for (todo = count; todo > 0; todo -= ret) { -		if (non_blocking && dvb_ringbuffer_empty(src)) { -			ret = -EWOULDBLOCK; -			break; -		} - -		ret = wait_event_interruptible(src->queue, -					       !dvb_ringbuffer_empty(src) || -					       (src->error != 0)); -		if (ret < 0) -			break; - -		if (src->error) { -			ret = src->error; -			dvb_ringbuffer_flush(src); -			break; -		} - -		avail = dvb_ringbuffer_avail(src); -		if (avail > todo) -			avail = todo; - -		ret = dvb_ringbuffer_read_user(src, buf, avail); -		if (ret < 0) -			break; - -		buf += ret; -	} - -	return (count - todo) ? (count - todo) : ret; -} - -static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) -{ -	struct list_head *head, *pos; - -	head = demux->get_frontends(demux); -	if (!head) -		return NULL; -	list_for_each(pos, head) -		if (DMX_FE_ENTRY(pos)->source == type) -			return DMX_FE_ENTRY(pos); - -	return NULL; -} - -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; - -	dprintk("function : %s\n", __func__); - -	if (mutex_lock_interruptible(&dmxdev->mutex)) -		return -ERESTARTSYS; - -	if (dmxdev->exit) { -		mutex_unlock(&dmxdev->mutex); -		return -ENODEV; -	} - -	if ((file->f_flags & O_ACCMODE) == O_RDWR) { -		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { -			mutex_unlock(&dmxdev->mutex); -			return -EOPNOTSUPP; -		} -	} - -	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -		void *mem; -		if (!dvbdev->readers) { -			mutex_unlock(&dmxdev->mutex); -			return -EBUSY; -		} -		mem = vmalloc(DVR_BUFFER_SIZE); -		if (!mem) { -			mutex_unlock(&dmxdev->mutex); -			return -ENOMEM; -		} -		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); -		dvbdev->readers--; -	} - -	if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -		dmxdev->dvr_orig_fe = dmxdev->demux->frontend; - -		if (!dmxdev->demux->write) { -			mutex_unlock(&dmxdev->mutex); -			return -EOPNOTSUPP; -		} - -		front = get_fe(dmxdev->demux, DMX_MEMORY_FE); - -		if (!front) { -			mutex_unlock(&dmxdev->mutex); -			return -EINVAL; -		} -		dmxdev->demux->disconnect_frontend(dmxdev->demux); -		dmxdev->demux->connect_frontend(dmxdev->demux, front); -	} -	dvbdev->users++; -	mutex_unlock(&dmxdev->mutex); -	return 0; -} - -static int dvb_dvr_release(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; - -	mutex_lock(&dmxdev->mutex); - -	if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -		dmxdev->demux->disconnect_frontend(dmxdev->demux); -		dmxdev->demux->connect_frontend(dmxdev->demux, -						dmxdev->dvr_orig_fe); -	} -	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -		dvbdev->readers++; -		if (dmxdev->dvr_buffer.data) { -			void *mem = dmxdev->dvr_buffer.data; -			mb(); -			spin_lock_irq(&dmxdev->lock); -			dmxdev->dvr_buffer.data = NULL; -			spin_unlock_irq(&dmxdev->lock); -			vfree(mem); -		} -	} -	/* TODO */ -	dvbdev->users--; -	if (dvbdev->users == 1 && dmxdev->exit == 1) { -		fops_put(file->f_op); -		file->f_op = NULL; -		mutex_unlock(&dmxdev->mutex); -		wake_up(&dvbdev->wait_queue); -	} else -		mutex_unlock(&dmxdev->mutex); - -	return 0; -} - -static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, -			     size_t count, loff_t *ppos) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; -	int ret; - -	if (!dmxdev->demux->write) -		return -EOPNOTSUPP; -	if ((file->f_flags & O_ACCMODE) != O_WRONLY) -		return -EINVAL; -	if (mutex_lock_interruptible(&dmxdev->mutex)) -		return -ERESTARTSYS; - -	if (dmxdev->exit) { -		mutex_unlock(&dmxdev->mutex); -		return -ENODEV; -	} -	ret = dmxdev->demux->write(dmxdev->demux, buf, count); -	mutex_unlock(&dmxdev->mutex); -	return ret; -} - -static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, -			    loff_t *ppos) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; - -	if (dmxdev->exit) -		return -ENODEV; - -	return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, -				      file->f_flags & O_NONBLOCK, -				      buf, count, ppos); -} - -static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, -				      unsigned long size) -{ -	struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer; -	void *newmem; -	void *oldmem; - -	dprintk("function : %s\n", __func__); - -	if (buf->size == size) -		return 0; -	if (!size) -		return -EINVAL; - -	newmem = vmalloc(size); -	if (!newmem) -		return -ENOMEM; - -	oldmem = buf->data; - -	spin_lock_irq(&dmxdev->lock); -	buf->data = newmem; -	buf->size = size; - -	/* reset and not flush in case the buffer shrinks */ -	dvb_ringbuffer_reset(buf); -	spin_unlock_irq(&dmxdev->lock); - -	vfree(oldmem); - -	return 0; -} - -static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter -					       *dmxdevfilter, int state) -{ -	spin_lock_irq(&dmxdevfilter->dev->lock); -	dmxdevfilter->state = state; -	spin_unlock_irq(&dmxdevfilter->dev->lock); -} - -static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, -				      unsigned long size) -{ -	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; -	void *newmem; -	void *oldmem; - -	if (buf->size == size) -		return 0; -	if (!size) -		return -EINVAL; -	if (dmxdevfilter->state >= DMXDEV_STATE_GO) -		return -EBUSY; - -	newmem = vmalloc(size); -	if (!newmem) -		return -ENOMEM; - -	oldmem = buf->data; - -	spin_lock_irq(&dmxdevfilter->dev->lock); -	buf->data = newmem; -	buf->size = size; - -	/* reset and not flush in case the buffer shrinks */ -	dvb_ringbuffer_reset(buf); -	spin_unlock_irq(&dmxdevfilter->dev->lock); - -	vfree(oldmem); - -	return 0; -} - -static void dvb_dmxdev_filter_timeout(unsigned long data) -{ -	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data; - -	dmxdevfilter->buffer.error = -ETIMEDOUT; -	spin_lock_irq(&dmxdevfilter->dev->lock); -	dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; -	spin_unlock_irq(&dmxdevfilter->dev->lock); -	wake_up(&dmxdevfilter->buffer.queue); -} - -static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) -{ -	struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; - -	del_timer(&dmxdevfilter->timer); -	if (para->timeout) { -		dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; -		dmxdevfilter->timer.data = (unsigned long)dmxdevfilter; -		dmxdevfilter->timer.expires = -		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; -		add_timer(&dmxdevfilter->timer); -	} -} - -static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, -				       const u8 *buffer2, size_t buffer2_len, -				       struct dmx_section_filter *filter, -				       enum dmx_success success) -{ -	struct dmxdev_filter *dmxdevfilter = filter->priv; -	int ret; - -	if (dmxdevfilter->buffer.error) { -		wake_up(&dmxdevfilter->buffer.queue); -		return 0; -	} -	spin_lock(&dmxdevfilter->dev->lock); -	if (dmxdevfilter->state != DMXDEV_STATE_GO) { -		spin_unlock(&dmxdevfilter->dev->lock); -		return 0; -	} -	del_timer(&dmxdevfilter->timer); -	dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n", -		buffer1[0], buffer1[1], -		buffer1[2], buffer1[3], buffer1[4], buffer1[5]); -	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) { -		dvb_ringbuffer_flush(&dmxdevfilter->buffer); -		dmxdevfilter->buffer.error = ret; -	} -	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) -		dmxdevfilter->state = DMXDEV_STATE_DONE; -	spin_unlock(&dmxdevfilter->dev->lock); -	wake_up(&dmxdevfilter->buffer.queue); -	return 0; -} - -static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, -				  const u8 *buffer2, size_t buffer2_len, -				  struct dmx_ts_feed *feed, -				  enum dmx_success success) -{ -	struct dmxdev_filter *dmxdevfilter = feed->priv; -	struct dvb_ringbuffer *buffer; -	int ret; - -	spin_lock(&dmxdevfilter->dev->lock); -	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { -		spin_unlock(&dmxdevfilter->dev->lock); -		return 0; -	} - -	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP -	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) -		buffer = &dmxdevfilter->buffer; -	else -		buffer = &dmxdevfilter->dev->dvr_buffer; -	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); -	if (ret < 0) { -		dvb_ringbuffer_flush(buffer); -		buffer->error = ret; -	} -	spin_unlock(&dmxdevfilter->dev->lock); -	wake_up(&buffer->queue); -	return 0; -} - -/* stop feed but only mark the specified filter as stopped (state set) */ -static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) -{ -	struct dmxdev_feed *feed; - -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - -	switch (dmxdevfilter->type) { -	case DMXDEV_TYPE_SEC: -		del_timer(&dmxdevfilter->timer); -		dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); -		break; -	case DMXDEV_TYPE_PES: -		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) -			feed->ts->stop_filtering(feed->ts); -		break; -	default: -		return -EINVAL; -	} -	return 0; -} - -/* start feed associated with the specified filter */ -static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) -{ -	struct dmxdev_feed *feed; -	int ret; - -	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); - -	switch (filter->type) { -	case DMXDEV_TYPE_SEC: -		return filter->feed.sec->start_filtering(filter->feed.sec); -	case DMXDEV_TYPE_PES: -		list_for_each_entry(feed, &filter->feed.ts, next) { -			ret = feed->ts->start_filtering(feed->ts); -			if (ret < 0) { -				dvb_dmxdev_feed_stop(filter); -				return ret; -			} -		} -		break; -	default: -		return -EINVAL; -	} - -	return 0; -} - -/* restart section feed if it has filters left associated with it, -   otherwise release the feed */ -static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) -{ -	int i; -	struct dmxdev *dmxdev = filter->dev; -	u16 pid = filter->params.sec.pid; - -	for (i = 0; i < dmxdev->filternum; i++) -		if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && -		    dmxdev->filter[i].type == DMXDEV_TYPE_SEC && -		    dmxdev->filter[i].params.sec.pid == pid) { -			dvb_dmxdev_feed_start(&dmxdev->filter[i]); -			return 0; -		} - -	filter->dev->demux->release_section_feed(dmxdev->demux, -						 filter->feed.sec); - -	return 0; -} - -static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) -{ -	struct dmxdev_feed *feed; -	struct dmx_demux *demux; - -	if (dmxdevfilter->state < DMXDEV_STATE_GO) -		return 0; - -	switch (dmxdevfilter->type) { -	case DMXDEV_TYPE_SEC: -		if (!dmxdevfilter->feed.sec) -			break; -		dvb_dmxdev_feed_stop(dmxdevfilter); -		if (dmxdevfilter->filter.sec) -			dmxdevfilter->feed.sec-> -			    release_filter(dmxdevfilter->feed.sec, -					   dmxdevfilter->filter.sec); -		dvb_dmxdev_feed_restart(dmxdevfilter); -		dmxdevfilter->feed.sec = NULL; -		break; -	case DMXDEV_TYPE_PES: -		dvb_dmxdev_feed_stop(dmxdevfilter); -		demux = dmxdevfilter->dev->demux; -		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) { -			demux->release_ts_feed(demux, feed->ts); -			feed->ts = NULL; -		} -		break; -	default: -		if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) -			return 0; -		return -EINVAL; -	} - -	dvb_ringbuffer_flush(&dmxdevfilter->buffer); -	return 0; -} - -static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter) -{ -	struct dmxdev_feed *feed, *tmp; - -	/* delete all PIDs */ -	list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) { -		list_del(&feed->next); -		kfree(feed); -	} - -	BUG_ON(!list_empty(&dmxdevfilter->feed.ts)); -} - -static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) -{ -	if (dmxdevfilter->state < DMXDEV_STATE_SET) -		return 0; - -	if (dmxdevfilter->type == DMXDEV_TYPE_PES) -		dvb_dmxdev_delete_pids(dmxdevfilter); - -	dmxdevfilter->type = DMXDEV_TYPE_NONE; -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); -	return 0; -} - -static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, -				 struct dmxdev_filter *filter, -				 struct dmxdev_feed *feed) -{ -	struct timespec timeout = { 0 }; -	struct dmx_pes_filter_params *para = &filter->params.pes; -	dmx_output_t otype; -	int ret; -	int ts_type; -	enum dmx_ts_pes ts_pes; -	struct dmx_ts_feed *tsfeed; - -	feed->ts = NULL; -	otype = para->output; - -	ts_pes = (enum dmx_ts_pes)para->pes_type; - -	if (ts_pes < DMX_PES_OTHER) -		ts_type = TS_DECODER; -	else -		ts_type = 0; - -	if (otype == DMX_OUT_TS_TAP) -		ts_type |= TS_PACKET; -	else if (otype == DMX_OUT_TSDEMUX_TAP) -		ts_type |= TS_PACKET | TS_DEMUX; -	else if (otype == DMX_OUT_TAP) -		ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; - -	ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts, -					      dvb_dmxdev_ts_callback); -	if (ret < 0) -		return ret; - -	tsfeed = feed->ts; -	tsfeed->priv = filter; - -	ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout); -	if (ret < 0) { -		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); -		return ret; -	} - -	ret = tsfeed->start_filtering(tsfeed); -	if (ret < 0) { -		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); -		return ret; -	} - -	return 0; -} - -static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) -{ -	struct dmxdev *dmxdev = filter->dev; -	struct dmxdev_feed *feed; -	void *mem; -	int ret, i; - -	if (filter->state < DMXDEV_STATE_SET) -		return -EINVAL; - -	if (filter->state >= DMXDEV_STATE_GO) -		dvb_dmxdev_filter_stop(filter); - -	if (!filter->buffer.data) { -		mem = vmalloc(filter->buffer.size); -		if (!mem) -			return -ENOMEM; -		spin_lock_irq(&filter->dev->lock); -		filter->buffer.data = mem; -		spin_unlock_irq(&filter->dev->lock); -	} - -	dvb_ringbuffer_flush(&filter->buffer); - -	switch (filter->type) { -	case DMXDEV_TYPE_SEC: -	{ -		struct dmx_sct_filter_params *para = &filter->params.sec; -		struct dmx_section_filter **secfilter = &filter->filter.sec; -		struct dmx_section_feed **secfeed = &filter->feed.sec; - -		*secfilter = NULL; -		*secfeed = NULL; - - -		/* find active filter/feed with same PID */ -		for (i = 0; i < dmxdev->filternum; i++) { -			if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && -			    dmxdev->filter[i].type == DMXDEV_TYPE_SEC && -			    dmxdev->filter[i].params.sec.pid == para->pid) { -				*secfeed = dmxdev->filter[i].feed.sec; -				break; -			} -		} - -		/* if no feed found, try to allocate new one */ -		if (!*secfeed) { -			ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, -								   secfeed, -								   dvb_dmxdev_section_callback); -			if (ret < 0) { -				printk("DVB (%s): could not alloc feed\n", -				       __func__); -				return ret; -			} - -			ret = (*secfeed)->set(*secfeed, para->pid, 32768, -					      (para->flags & DMX_CHECK_CRC) ? 1 : 0); -			if (ret < 0) { -				printk("DVB (%s): could not set feed\n", -				       __func__); -				dvb_dmxdev_feed_restart(filter); -				return ret; -			} -		} else { -			dvb_dmxdev_feed_stop(filter); -		} - -		ret = (*secfeed)->allocate_filter(*secfeed, secfilter); -		if (ret < 0) { -			dvb_dmxdev_feed_restart(filter); -			filter->feed.sec->start_filtering(*secfeed); -			dprintk("could not get filter\n"); -			return ret; -		} - -		(*secfilter)->priv = filter; - -		memcpy(&((*secfilter)->filter_value[3]), -		       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1); -		memcpy(&(*secfilter)->filter_mask[3], -		       ¶->filter.mask[1], DMX_FILTER_SIZE - 1); -		memcpy(&(*secfilter)->filter_mode[3], -		       ¶->filter.mode[1], DMX_FILTER_SIZE - 1); - -		(*secfilter)->filter_value[0] = para->filter.filter[0]; -		(*secfilter)->filter_mask[0] = para->filter.mask[0]; -		(*secfilter)->filter_mode[0] = para->filter.mode[0]; -		(*secfilter)->filter_mask[1] = 0; -		(*secfilter)->filter_mask[2] = 0; - -		filter->todo = 0; - -		ret = filter->feed.sec->start_filtering(filter->feed.sec); -		if (ret < 0) -			return ret; - -		dvb_dmxdev_filter_timer(filter); -		break; -	} -	case DMXDEV_TYPE_PES: -		list_for_each_entry(feed, &filter->feed.ts, next) { -			ret = dvb_dmxdev_start_feed(dmxdev, filter, feed); -			if (ret < 0) { -				dvb_dmxdev_filter_stop(filter); -				return ret; -			} -		} -		break; -	default: -		return -EINVAL; -	} - -	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); -	return 0; -} - -static int dvb_demux_open(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; -	int i; -	struct dmxdev_filter *dmxdevfilter; - -	if (!dmxdev->filter) -		return -EINVAL; - -	if (mutex_lock_interruptible(&dmxdev->mutex)) -		return -ERESTARTSYS; - -	for (i = 0; i < dmxdev->filternum; i++) -		if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) -			break; - -	if (i == dmxdev->filternum) { -		mutex_unlock(&dmxdev->mutex); -		return -EMFILE; -	} - -	dmxdevfilter = &dmxdev->filter[i]; -	mutex_init(&dmxdevfilter->mutex); -	file->private_data = dmxdevfilter; - -	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); -	dmxdevfilter->type = DMXDEV_TYPE_NONE; -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); -	init_timer(&dmxdevfilter->timer); - -	dvbdev->users++; - -	mutex_unlock(&dmxdev->mutex); -	return 0; -} - -static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, -				  struct dmxdev_filter *dmxdevfilter) -{ -	mutex_lock(&dmxdev->mutex); -	mutex_lock(&dmxdevfilter->mutex); - -	dvb_dmxdev_filter_stop(dmxdevfilter); -	dvb_dmxdev_filter_reset(dmxdevfilter); - -	if (dmxdevfilter->buffer.data) { -		void *mem = dmxdevfilter->buffer.data; - -		spin_lock_irq(&dmxdev->lock); -		dmxdevfilter->buffer.data = NULL; -		spin_unlock_irq(&dmxdev->lock); -		vfree(mem); -	} - -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); -	wake_up(&dmxdevfilter->buffer.queue); -	mutex_unlock(&dmxdevfilter->mutex); -	mutex_unlock(&dmxdev->mutex); -	return 0; -} - -static inline void invert_mode(dmx_filter_t *filter) -{ -	int i; - -	for (i = 0; i < DMX_FILTER_SIZE; i++) -		filter->mode[i] ^= 0xff; -} - -static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev, -			      struct dmxdev_filter *filter, u16 pid) -{ -	struct dmxdev_feed *feed; - -	if ((filter->type != DMXDEV_TYPE_PES) || -	    (filter->state < DMXDEV_STATE_SET)) -		return -EINVAL; - -	/* only TS packet filters may have multiple PIDs */ -	if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) && -	    (!list_empty(&filter->feed.ts))) -		return -EINVAL; - -	feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL); -	if (feed == NULL) -		return -ENOMEM; - -	feed->pid = pid; -	list_add(&feed->next, &filter->feed.ts); - -	if (filter->state >= DMXDEV_STATE_GO) -		return dvb_dmxdev_start_feed(dmxdev, filter, feed); - -	return 0; -} - -static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev, -				  struct dmxdev_filter *filter, u16 pid) -{ -	struct dmxdev_feed *feed, *tmp; - -	if ((filter->type != DMXDEV_TYPE_PES) || -	    (filter->state < DMXDEV_STATE_SET)) -		return -EINVAL; - -	list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) { -		if ((feed->pid == pid) && (feed->ts != NULL)) { -			feed->ts->stop_filtering(feed->ts); -			filter->dev->demux->release_ts_feed(filter->dev->demux, -							    feed->ts); -			list_del(&feed->next); -			kfree(feed); -		} -	} - -	return 0; -} - -static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, -				 struct dmxdev_filter *dmxdevfilter, -				 struct dmx_sct_filter_params *params) -{ -	dprintk("function : %s\n", __func__); - -	dvb_dmxdev_filter_stop(dmxdevfilter); - -	dmxdevfilter->type = DMXDEV_TYPE_SEC; -	memcpy(&dmxdevfilter->params.sec, -	       params, sizeof(struct dmx_sct_filter_params)); -	invert_mode(&dmxdevfilter->params.sec.filter); -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - -	if (params->flags & DMX_IMMEDIATE_START) -		return dvb_dmxdev_filter_start(dmxdevfilter); - -	return 0; -} - -static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, -				     struct dmxdev_filter *dmxdevfilter, -				     struct dmx_pes_filter_params *params) -{ -	int ret; - -	dvb_dmxdev_filter_stop(dmxdevfilter); -	dvb_dmxdev_filter_reset(dmxdevfilter); - -	if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) -		return -EINVAL; - -	dmxdevfilter->type = DMXDEV_TYPE_PES; -	memcpy(&dmxdevfilter->params, params, -	       sizeof(struct dmx_pes_filter_params)); -	INIT_LIST_HEAD(&dmxdevfilter->feed.ts); - -	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - -	ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, -				 dmxdevfilter->params.pes.pid); -	if (ret < 0) -		return ret; - -	if (params->flags & DMX_IMMEDIATE_START) -		return dvb_dmxdev_filter_start(dmxdevfilter); - -	return 0; -} - -static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, -				   struct file *file, char __user *buf, -				   size_t count, loff_t *ppos) -{ -	int result, hcount; -	int done = 0; - -	if (dfil->todo <= 0) { -		hcount = 3 + dfil->todo; -		if (hcount > count) -			hcount = count; -		result = dvb_dmxdev_buffer_read(&dfil->buffer, -						file->f_flags & O_NONBLOCK, -						buf, hcount, ppos); -		if (result < 0) { -			dfil->todo = 0; -			return result; -		} -		if (copy_from_user(dfil->secheader - dfil->todo, buf, result)) -			return -EFAULT; -		buf += result; -		done = result; -		count -= result; -		dfil->todo -= result; -		if (dfil->todo > -3) -			return done; -		dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff; -		if (!count) -			return done; -	} -	if (count > dfil->todo) -		count = dfil->todo; -	result = dvb_dmxdev_buffer_read(&dfil->buffer, -					file->f_flags & O_NONBLOCK, -					buf, count, ppos); -	if (result < 0) -		return result; -	dfil->todo -= result; -	return (result + done); -} - -static ssize_t -dvb_demux_read(struct file *file, char __user *buf, size_t count, -	       loff_t *ppos) -{ -	struct dmxdev_filter *dmxdevfilter = file->private_data; -	int ret; - -	if (mutex_lock_interruptible(&dmxdevfilter->mutex)) -		return -ERESTARTSYS; - -	if (dmxdevfilter->type == DMXDEV_TYPE_SEC) -		ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); -	else -		ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, -					     file->f_flags & O_NONBLOCK, -					     buf, count, ppos); - -	mutex_unlock(&dmxdevfilter->mutex); -	return ret; -} - -static int dvb_demux_do_ioctl(struct file *file, -			      unsigned int cmd, void *parg) -{ -	struct dmxdev_filter *dmxdevfilter = file->private_data; -	struct dmxdev *dmxdev = dmxdevfilter->dev; -	unsigned long arg = (unsigned long)parg; -	int ret = 0; - -	if (mutex_lock_interruptible(&dmxdev->mutex)) -		return -ERESTARTSYS; - -	switch (cmd) { -	case DMX_START: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			mutex_unlock(&dmxdev->mutex); -			return -ERESTARTSYS; -		} -		if (dmxdevfilter->state < DMXDEV_STATE_SET) -			ret = -EINVAL; -		else -			ret = dvb_dmxdev_filter_start(dmxdevfilter); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_STOP: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			mutex_unlock(&dmxdev->mutex); -			return -ERESTARTSYS; -		} -		ret = dvb_dmxdev_filter_stop(dmxdevfilter); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_SET_FILTER: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			mutex_unlock(&dmxdev->mutex); -			return -ERESTARTSYS; -		} -		ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_SET_PES_FILTER: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			mutex_unlock(&dmxdev->mutex); -			return -ERESTARTSYS; -		} -		ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_SET_BUFFER_SIZE: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			mutex_unlock(&dmxdev->mutex); -			return -ERESTARTSYS; -		} -		ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_GET_PES_PIDS: -		if (!dmxdev->demux->get_pes_pids) { -			ret = -EINVAL; -			break; -		} -		dmxdev->demux->get_pes_pids(dmxdev->demux, parg); -		break; - -	case DMX_GET_CAPS: -		if (!dmxdev->demux->get_caps) { -			ret = -EINVAL; -			break; -		} -		ret = dmxdev->demux->get_caps(dmxdev->demux, parg); -		break; - -	case DMX_SET_SOURCE: -		if (!dmxdev->demux->set_source) { -			ret = -EINVAL; -			break; -		} -		ret = dmxdev->demux->set_source(dmxdev->demux, parg); -		break; - -	case DMX_GET_STC: -		if (!dmxdev->demux->get_stc) { -			ret = -EINVAL; -			break; -		} -		ret = dmxdev->demux->get_stc(dmxdev->demux, -					     ((struct dmx_stc *)parg)->num, -					     &((struct dmx_stc *)parg)->stc, -					     &((struct dmx_stc *)parg)->base); -		break; - -	case DMX_ADD_PID: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			ret = -ERESTARTSYS; -			break; -		} -		ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	case DMX_REMOVE_PID: -		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { -			ret = -ERESTARTSYS; -			break; -		} -		ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg); -		mutex_unlock(&dmxdevfilter->mutex); -		break; - -	default: -		ret = -EINVAL; -		break; -	} -	mutex_unlock(&dmxdev->mutex); -	return ret; -} - -static long dvb_demux_ioctl(struct file *file, unsigned int cmd, -			    unsigned long arg) -{ -	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); -} - -static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) -{ -	struct dmxdev_filter *dmxdevfilter = file->private_data; -	unsigned int mask = 0; - -	if (!dmxdevfilter) -		return -EINVAL; - -	poll_wait(file, &dmxdevfilter->buffer.queue, wait); - -	if (dmxdevfilter->state != DMXDEV_STATE_GO && -	    dmxdevfilter->state != DMXDEV_STATE_DONE && -	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) -		return 0; - -	if (dmxdevfilter->buffer.error) -		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - -	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) -		mask |= (POLLIN | POLLRDNORM | POLLPRI); - -	return mask; -} - -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); - -	mutex_lock(&dmxdev->mutex); -	dmxdev->dvbdev->users--; -	if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) { -		fops_put(file->f_op); -		file->f_op = NULL; -		mutex_unlock(&dmxdev->mutex); -		wake_up(&dmxdev->dvbdev->wait_queue); -	} else -		mutex_unlock(&dmxdev->mutex); - -	return ret; -} - -static const struct file_operations dvb_demux_fops = { -	.owner = THIS_MODULE, -	.read = dvb_demux_read, -	.unlocked_ioctl = dvb_demux_ioctl, -	.open = dvb_demux_open, -	.release = dvb_demux_release, -	.poll = dvb_demux_poll, -	.llseek = default_llseek, -}; - -static struct dvb_device dvbdev_demux = { -	.priv = NULL, -	.users = 1, -	.writers = 1, -	.fops = &dvb_demux_fops -}; - -static int dvb_dvr_do_ioctl(struct file *file, -			    unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; -	unsigned long arg = (unsigned long)parg; -	int ret; - -	if (mutex_lock_interruptible(&dmxdev->mutex)) -		return -ERESTARTSYS; - -	switch (cmd) { -	case DMX_SET_BUFFER_SIZE: -		ret = dvb_dvr_set_buffer_size(dmxdev, arg); -		break; - -	default: -		ret = -EINVAL; -		break; -	} -	mutex_unlock(&dmxdev->mutex); -	return ret; -} - -static long dvb_dvr_ioctl(struct file *file, -			 unsigned int cmd, unsigned long arg) -{ -	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); -} - -static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dmxdev *dmxdev = dvbdev->priv; -	unsigned int mask = 0; - -	dprintk("function : %s\n", __func__); - -	poll_wait(file, &dmxdev->dvr_buffer.queue, wait); - -	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -		if (dmxdev->dvr_buffer.error) -			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - -		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) -			mask |= (POLLIN | POLLRDNORM | POLLPRI); -	} else -		mask |= (POLLOUT | POLLWRNORM | POLLPRI); - -	return mask; -} - -static const struct file_operations dvb_dvr_fops = { -	.owner = THIS_MODULE, -	.read = dvb_dvr_read, -	.write = dvb_dvr_write, -	.unlocked_ioctl = dvb_dvr_ioctl, -	.open = dvb_dvr_open, -	.release = dvb_dvr_release, -	.poll = dvb_dvr_poll, -	.llseek = default_llseek, -}; - -static struct dvb_device dvbdev_dvr = { -	.priv = NULL, -	.readers = 1, -	.users = 1, -	.fops = &dvb_dvr_fops -}; - -int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) -{ -	int i; - -	if (dmxdev->demux->open(dmxdev->demux) < 0) -		return -EUSERS; - -	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); -	if (!dmxdev->filter) -		return -ENOMEM; - -	mutex_init(&dmxdev->mutex); -	spin_lock_init(&dmxdev->lock); -	for (i = 0; i < dmxdev->filternum; i++) { -		dmxdev->filter[i].dev = dmxdev; -		dmxdev->filter[i].buffer.data = NULL; -		dvb_dmxdev_filter_state_set(&dmxdev->filter[i], -					    DMXDEV_STATE_FREE); -	} - -	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, -			    DVB_DEVICE_DEMUX); -	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, -			    dmxdev, DVB_DEVICE_DVR); - -	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); - -	return 0; -} - -EXPORT_SYMBOL(dvb_dmxdev_init); - -void dvb_dmxdev_release(struct dmxdev *dmxdev) -{ -	dmxdev->exit=1; -	if (dmxdev->dvbdev->users > 1) { -		wait_event(dmxdev->dvbdev->wait_queue, -				dmxdev->dvbdev->users==1); -	} -	if (dmxdev->dvr_dvbdev->users > 1) { -		wait_event(dmxdev->dvr_dvbdev->wait_queue, -				dmxdev->dvr_dvbdev->users==1); -	} - -	dvb_unregister_device(dmxdev->dvbdev); -	dvb_unregister_device(dmxdev->dvr_dvbdev); - -	vfree(dmxdev->filter); -	dmxdev->filter = NULL; -	dmxdev->demux->close(dmxdev->demux); -} - -EXPORT_SYMBOL(dvb_dmxdev_release); diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h deleted file mode 100644 index 02ebe28f830..00000000000 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ /dev/null @@ -1,118 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#ifndef _DMXDEV_H_ -#define _DMXDEV_H_ - -#include <linux/types.h> -#include <linux/spinlock.h> -#include <linux/kernel.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 { -	DMXDEV_TYPE_NONE, -	DMXDEV_TYPE_SEC, -	DMXDEV_TYPE_PES, -}; - -enum dmxdev_state { -	DMXDEV_STATE_FREE, -	DMXDEV_STATE_ALLOCATED, -	DMXDEV_STATE_SET, -	DMXDEV_STATE_GO, -	DMXDEV_STATE_DONE, -	DMXDEV_STATE_TIMEDOUT -}; - -struct dmxdev_feed { -	u16 pid; -	struct dmx_ts_feed *ts; -	struct list_head next; -}; - -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 { -	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; -}; - - -int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *); -void dvb_dmxdev_release(struct dmxdev *dmxdev); - -#endif /* _DMXDEV_H_ */ diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c deleted file mode 100644 index 4d0646da608..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ /dev/null @@ -1,1750 +0,0 @@ -/* - * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces - * - * Copyright (C) 2004 Andrew de Quincey - * - * Parts of this file were based on sources as follows: - * - * Copyright (C) 2003 Ralph Metzler <rjkm@metzlerbros.de> - * - * based on code: - * - * Copyright (C) 1999-2002 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 Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/smp_lock.h> -#include <linux/kthread.h> - -#include "dvb_ca_en50221.h" -#include "dvb_ringbuffer.h" - -static int dvb_ca_en50221_debug; - -module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); -MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); - -#define dprintk if (dvb_ca_en50221_debug) printk - -#define INIT_TIMEOUT_SECS 10 - -#define HOST_LINK_BUF_SIZE 0x200 - -#define RX_BUFFER_SIZE 65535 - -#define MAX_RX_PACKETS_PER_ITERATION 10 - -#define CTRLIF_DATA      0 -#define CTRLIF_COMMAND   1 -#define CTRLIF_STATUS    1 -#define CTRLIF_SIZE_LOW  2 -#define CTRLIF_SIZE_HIGH 3 - -#define CMDREG_HC        1	/* Host control */ -#define CMDREG_SW        2	/* Size write */ -#define CMDREG_SR        4	/* Size read */ -#define CMDREG_RS        8	/* Reset interface */ -#define CMDREG_FRIE   0x40	/* Enable FR interrupt */ -#define CMDREG_DAIE   0x80	/* Enable DA interrupt */ -#define IRQEN (CMDREG_DAIE) - -#define STATUSREG_RE     1	/* read error */ -#define STATUSREG_WE     2	/* write error */ -#define STATUSREG_FR  0x40	/* module free */ -#define STATUSREG_DA  0x80	/* data available */ -#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)	/* general transfer error */ - - -#define DVB_CA_SLOTSTATE_NONE           0 -#define DVB_CA_SLOTSTATE_UNINITIALISED  1 -#define DVB_CA_SLOTSTATE_RUNNING        2 -#define DVB_CA_SLOTSTATE_INVALID        3 -#define DVB_CA_SLOTSTATE_WAITREADY      4 -#define DVB_CA_SLOTSTATE_VALIDATE       5 -#define DVB_CA_SLOTSTATE_WAITFR         6 -#define DVB_CA_SLOTSTATE_LINKINIT       7 - - -/* Information on a CA slot */ -struct dvb_ca_slot { - -	/* current state of the CAM */ -	int slot_state; - -	/* mutex used for serializing access to one CI slot */ -	struct mutex slot_lock; - -	/* Number of CAMCHANGES that have occurred since last processing */ -	atomic_t camchange_count; - -	/* Type of last CAMCHANGE */ -	int camchange_type; - -	/* base address of CAM config */ -	u32 config_base; - -	/* value to write into Config Control register */ -	u8 config_option; - -	/* if 1, the CAM supports DA IRQs */ -	u8 da_irq_supported:1; - -	/* size of the buffer to use when talking to the CAM */ -	int link_buf_size; - -	/* buffer for incoming packets */ -	struct dvb_ringbuffer rx_buffer; - -	/* timer used during various states of the slot */ -	unsigned long timeout; -}; - -/* Private CA-interface information */ -struct dvb_ca_private { - -	/* pointer back to the public data structure */ -	struct dvb_ca_en50221 *pub; - -	/* the DVB device */ -	struct dvb_device *dvbdev; - -	/* Flags describing the interface (DVB_CA_FLAG_*) */ -	u32 flags; - -	/* number of slots supported by this CA interface */ -	unsigned int slot_count; - -	/* information on each slot */ -	struct dvb_ca_slot *slot_info; - -	/* wait queues for read() and write() operations */ -	wait_queue_head_t wait_queue; - -	/* PID of the monitoring thread */ -	struct task_struct *thread; - -	/* Flag indicating if the CA device is open */ -	unsigned int open:1; - -	/* Flag indicating the thread should wake up now */ -	unsigned int wakeup:1; - -	/* Delay the main thread should use */ -	unsigned long delay; - -	/* Slot to start looking for data to read from in the next user-space read operation */ -	int next_read_slot; -}; - -static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); -static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); -static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); - - -/** - * Safely find needle in haystack. - * - * @param haystack Buffer to look in. - * @param hlen Number of bytes in haystack. - * @param needle Buffer to find. - * @param nlen Number of bytes in needle. - * @return Pointer into haystack needle was found at, or NULL if not found. - */ -static char *findstr(char * haystack, int hlen, char * needle, int nlen) -{ -	int i; - -	if (hlen < nlen) -		return NULL; - -	for (i = 0; i <= hlen - nlen; i++) { -		if (!strncmp(haystack + i, needle, nlen)) -			return haystack + i; -	} - -	return NULL; -} - - - -/* ******************************************************************************** */ -/* EN50221 physical interface functions */ - - -/** - * Check CAM status. - */ -static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) -{ -	int slot_status; -	int cam_present_now; -	int cam_changed; - -	/* IRQ mode */ -	if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) { -		return (atomic_read(&ca->slot_info[slot].camchange_count) != 0); -	} - -	/* poll mode */ -	slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); - -	cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0; -	cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0; -	if (!cam_changed) { -		int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE); -		cam_changed = (cam_present_now != cam_present_old); -	} - -	if (cam_changed) { -		if (!cam_present_now) { -			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; -		} else { -			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED; -		} -		atomic_set(&ca->slot_info[slot].camchange_count, 1); -	} else { -		if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) && -		    (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) { -			// move to validate state if reset is completed -			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; -		} -	} - -	return cam_changed; -} - - -/** - * Wait for flags to become set on the STATUS register on a CAM interface, - * checking for errors and timeout. - * - * @param ca CA instance. - * @param slot Slot on interface. - * @param waitfor Flags to wait for. - * @param timeout_ms Timeout in milliseconds. - * - * @return 0 on success, nonzero on error. - */ -static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, -					 u8 waitfor, int timeout_hz) -{ -	unsigned long timeout; -	unsigned long start; - -	dprintk("%s\n", __func__); - -	/* loop until timeout elapsed */ -	start = jiffies; -	timeout = jiffies + timeout_hz; -	while (1) { -		/* read the status and check for error */ -		int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); -		if (res < 0) -			return -EIO; - -		/* if we got the flags, it was successful! */ -		if (res & waitfor) { -			dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start); -			return 0; -		} - -		/* check for timeout */ -		if (time_after(jiffies, timeout)) { -			break; -		} - -		/* wait for a bit */ -		msleep(1); -	} - -	dprintk("%s failed timeout:%lu\n", __func__, jiffies - start); - -	/* if we get here, we've timed out */ -	return -ETIMEDOUT; -} - - -/** - * Initialise the link layer connection to a CAM. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, nonzero on failure. - */ -static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) -{ -	int ret; -	int buf_size; -	u8 buf[2]; - -	dprintk("%s\n", __func__); - -	/* we'll be determining these during this function */ -	ca->slot_info[slot].da_irq_supported = 0; - -	/* set the host link buffer size temporarily. it will be overwritten with the -	 * real negotiated size later. */ -	ca->slot_info[slot].link_buf_size = 2; - -	/* read the buffer size from the CAM */ -	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) -		return ret; -	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) -		return ret; -	if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) -		return -EIO; -	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) -		return ret; - -	/* store it, and choose the minimum of our buffer and the CAM's buffer size */ -	buf_size = (buf[0] << 8) | buf[1]; -	if (buf_size > HOST_LINK_BUF_SIZE) -		buf_size = HOST_LINK_BUF_SIZE; -	ca->slot_info[slot].link_buf_size = buf_size; -	buf[0] = buf_size >> 8; -	buf[1] = buf_size & 0xff; -	dprintk("Chosen link buffer size of %i\n", buf_size); - -	/* write the buffer size to the CAM */ -	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) -		return ret; -	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) -		return ret; -	if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) -		return -EIO; -	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) -		return ret; - -	/* success */ -	return 0; -} - -/** - * Read a tuple from attribute memory. - * - * @param ca CA instance. - * @param slot Slot id. - * @param address Address to read from. Updated. - * @param tupleType Tuple id byte. Updated. - * @param tupleLength Tuple length. Updated. - * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. - * - * @return 0 on success, nonzero on error. - */ -static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, -				     int *address, int *tupleType, int *tupleLength, u8 * tuple) -{ -	int i; -	int _tupleType; -	int _tupleLength; -	int _address = *address; - -	/* grab the next tuple length and type */ -	if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) -		return _tupleType; -	if (_tupleType == 0xff) { -		dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); -		*address += 2; -		*tupleType = _tupleType; -		*tupleLength = 0; -		return 0; -	} -	if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0) -		return _tupleLength; -	_address += 4; - -	dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); - -	/* read in the whole tuple */ -	for (i = 0; i < _tupleLength; i++) { -		tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i * 2)); -		dprintk("  0x%02x: 0x%02x %c\n", -			i, tuple[i] & 0xff, -			((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); -	} -	_address += (_tupleLength * 2); - -	// success -	*tupleType = _tupleType; -	*tupleLength = _tupleLength; -	*address = _address; -	return 0; -} - - -/** - * Parse attribute memory of a CAM module, extracting Config register, and checking - * it is a DVB CAM module. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) -{ -	int address = 0; -	int tupleLength; -	int tupleType; -	u8 tuple[257]; -	char *dvb_str; -	int rasz; -	int status; -	int got_cftableentry = 0; -	int end_chain = 0; -	int i; -	u16 manfid = 0; -	u16 devid = 0; - - -	// CISTPL_DEVICE_0A -	if ((status = -	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) -		return status; -	if (tupleType != 0x1D) -		return -EINVAL; - - - -	// CISTPL_DEVICE_0C -	if ((status = -	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) -		return status; -	if (tupleType != 0x1C) -		return -EINVAL; - - - -	// CISTPL_VERS_1 -	if ((status = -	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) -		return status; -	if (tupleType != 0x15) -		return -EINVAL; - - - -	// CISTPL_MANFID -	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, -						&tupleLength, tuple)) < 0) -		return status; -	if (tupleType != 0x20) -		return -EINVAL; -	if (tupleLength != 4) -		return -EINVAL; -	manfid = (tuple[1] << 8) | tuple[0]; -	devid = (tuple[3] << 8) | tuple[2]; - - - -	// CISTPL_CONFIG -	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, -						&tupleLength, tuple)) < 0) -		return status; -	if (tupleType != 0x1A) -		return -EINVAL; -	if (tupleLength < 3) -		return -EINVAL; - -	/* extract the configbase */ -	rasz = tuple[0] & 3; -	if (tupleLength < (3 + rasz + 14)) -		return -EINVAL; -	ca->slot_info[slot].config_base = 0; -	for (i = 0; i < rasz + 1; i++) { -		ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i)); -	} - -	/* check it contains the correct DVB string */ -	dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); -	if (dvb_str == NULL) -		return -EINVAL; -	if (tupleLength < ((dvb_str - (char *) tuple) + 12)) -		return -EINVAL; - -	/* is it a version we support? */ -	if (strncmp(dvb_str + 8, "1.00", 4)) { -		printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n", -		       ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); -		return -EINVAL; -	} - -	/* process the CFTABLE_ENTRY tuples, and any after those */ -	while ((!end_chain) && (address < 0x1000)) { -		if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, -							&tupleLength, tuple)) < 0) -			return status; -		switch (tupleType) { -		case 0x1B:	// CISTPL_CFTABLE_ENTRY -			if (tupleLength < (2 + 11 + 17)) -				break; - -			/* if we've already parsed one, just use it */ -			if (got_cftableentry) -				break; - -			/* get the config option */ -			ca->slot_info[slot].config_option = tuple[0] & 0x3f; - -			/* OK, check it contains the correct strings */ -			if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) == NULL) || -			    (findstr((char *)tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) -				break; - -			got_cftableentry = 1; -			break; - -		case 0x14:	// CISTPL_NO_LINK -			break; - -		case 0xFF:	// CISTPL_END -			end_chain = 1; -			break; - -		default:	/* Unknown tuple type - just skip this tuple and move to the next one */ -			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, -				tupleLength); -			break; -		} -	} - -	if ((address > 0x1000) || (!got_cftableentry)) -		return -EINVAL; - -	dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", -		manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); - -	// success! -	return 0; -} - - -/** - * Set CAM's configoption correctly. - * - * @param ca CA instance. - * @param slot Slot containing the CAM. - */ -static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) -{ -	int configoption; - -	dprintk("%s\n", __func__); - -	/* set the config option */ -	ca->pub->write_attribute_mem(ca->pub, slot, -				     ca->slot_info[slot].config_base, -				     ca->slot_info[slot].config_option); - -	/* check it */ -	configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base); -	dprintk("Set configoption 0x%x, read configoption 0x%x\n", -		ca->slot_info[slot].config_option, configoption & 0x3f); - -	/* fine! */ -	return 0; - -} - - -/** - * This function talks to an EN50221 CAM control interface. It reads a buffer of - * data from the CAM. The data can either be stored in a supplied buffer, or - * automatically be added to the slot's rx_buffer. - * - * @param ca CA instance. - * @param slot Slot to read from. - * @param ebuf If non-NULL, the data will be written to this buffer. If NULL, - * the data will be added into the buffering system as a normal fragment. - * @param ecount Size of ebuf. Ignored if ebuf is NULL. - * - * @return Number of bytes read, or < 0 on error - */ -static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount) -{ -	int bytes_read; -	int status; -	u8 buf[HOST_LINK_BUF_SIZE]; -	int i; - -	dprintk("%s\n", __func__); - -	/* check if we have space for a link buf in the rx_buffer */ -	if (ebuf == NULL) { -		int buf_free; - -		if (ca->slot_info[slot].rx_buffer.data == NULL) { -			status = -EIO; -			goto exit; -		} -		buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); - -		if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { -			status = -EAGAIN; -			goto exit; -		} -	} - -	/* check if there is data available */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -		goto exit; -	if (!(status & STATUSREG_DA)) { -		/* no data */ -		status = 0; -		goto exit; -	} - -	/* read the amount of data */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) -		goto exit; -	bytes_read = status << 8; -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) -		goto exit; -	bytes_read |= status; - -	/* check it will fit */ -	if (ebuf == NULL) { -		if (bytes_read > ca->slot_info[slot].link_buf_size) { -			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", -			       ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); -			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -			status = -EIO; -			goto exit; -		} -		if (bytes_read < 2) { -			printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", -			       ca->dvbdev->adapter->num); -			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -			status = -EIO; -			goto exit; -		} -	} else { -		if (bytes_read > ecount) { -			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", -			       ca->dvbdev->adapter->num); -			status = -EIO; -			goto exit; -		} -	} - -	/* fill the buffer */ -	for (i = 0; i < bytes_read; i++) { -		/* read byte and check */ -		if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) -			goto exit; - -		/* OK, store it in the buffer */ -		buf[i] = status; -	} - -	/* check for read error (RE should now be 0) */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -		goto exit; -	if (status & STATUSREG_RE) { -		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -		status = -EIO; -		goto exit; -	} - -	/* OK, add it to the receive buffer, or copy into external buffer if supplied */ -	if (ebuf == NULL) { -		if (ca->slot_info[slot].rx_buffer.data == NULL) { -			status = -EIO; -			goto exit; -		} -		dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); -	} else { -		memcpy(ebuf, buf, bytes_read); -	} - -	dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, -		buf[0], (buf[1] & 0x80) == 0, bytes_read); - -	/* wake up readers when a last_fragment is received */ -	if ((buf[1] & 0x80) == 0x00) { -		wake_up_interruptible(&ca->wait_queue); -	} -	status = bytes_read; - -exit: -	return status; -} - - -/** - * This function talks to an EN50221 CAM control interface. It writes a buffer of data - * to a CAM. - * - * @param ca CA instance. - * @param slot Slot to write to. - * @param ebuf The data in this buffer is treated as a complete link-level packet to - * be written. - * @param count Size of ebuf. - * - * @return Number of bytes written, or < 0 on error. - */ -static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write) -{ -	int status; -	int i; - -	dprintk("%s\n", __func__); - - -	/* sanity check */ -	if (bytes_write > ca->slot_info[slot].link_buf_size) -		return -EINVAL; - -	/* it is possible we are dealing with a single buffer implementation, -	   thus if there is data available for read or if there is even a read -	   already in progress, we do nothing but awake the kernel thread to -	   process the data if necessary. */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -		goto exitnowrite; -	if (status & (STATUSREG_DA | STATUSREG_RE)) { -		if (status & STATUSREG_DA) -			dvb_ca_en50221_thread_wakeup(ca); - -		status = -EAGAIN; -		goto exitnowrite; -	} - -	/* OK, set HC bit */ -	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, -						 IRQEN | CMDREG_HC)) != 0) -		goto exit; - -	/* check if interface is still free */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -		goto exit; -	if (!(status & STATUSREG_FR)) { -		/* it wasn't free => try again later */ -		status = -EAGAIN; -		goto exit; -	} - -	/* send the amount of data */ -	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) -		goto exit; -	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, -						 bytes_write & 0xff)) != 0) -		goto exit; - -	/* send the buffer */ -	for (i = 0; i < bytes_write; i++) { -		if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) -			goto exit; -	} - -	/* check for write error (WE should now be 0) */ -	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) -		goto exit; -	if (status & STATUSREG_WE) { -		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -		status = -EIO; -		goto exit; -	} -	status = bytes_write; - -	dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, -		buf[0], (buf[1] & 0x80) == 0, bytes_write); - -exit: -	ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); - -exitnowrite: -	return status; -} -EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); - - - -/* ******************************************************************************** */ -/* EN50221 higher level functions */ - - -/** - * A CAM has been removed => shut it down. - * - * @param ca CA instance. - * @param slot Slot to shut down. - */ -static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) -{ -	dprintk("%s\n", __func__); - -	ca->pub->slot_shutdown(ca->pub, slot); -	ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; - -	/* need to wake up all processes to check if they're now -	   trying to write to a defunct CAM */ -	wake_up_interruptible(&ca->wait_queue); - -	dprintk("Slot %i shutdown\n", slot); - -	/* success */ -	return 0; -} -EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); - - -/** - * A CAMCHANGE IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - * @param 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) -{ -	struct dvb_ca_private *ca = pubca->private; - -	dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type); - -	switch (change_type) { -	case DVB_CA_EN50221_CAMCHANGE_REMOVED: -	case DVB_CA_EN50221_CAMCHANGE_INSERTED: -		break; - -	default: -		return; -	} - -	ca->slot_info[slot].camchange_type = change_type; -	atomic_inc(&ca->slot_info[slot].camchange_count); -	dvb_ca_en50221_thread_wakeup(ca); -} -EXPORT_SYMBOL(dvb_ca_en50221_frda_irq); - - -/** - * A CAMREADY IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot) -{ -	struct dvb_ca_private *ca = pubca->private; - -	dprintk("CAMREADY IRQ slot:%i\n", slot); - -	if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) { -		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; -		dvb_ca_en50221_thread_wakeup(ca); -	} -} - - -/** - * An FR or DA IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot) -{ -	struct dvb_ca_private *ca = pubca->private; -	int flags; - -	dprintk("FR/DA IRQ slot:%i\n", slot); - -	switch (ca->slot_info[slot].slot_state) { -	case DVB_CA_SLOTSTATE_LINKINIT: -		flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS); -		if (flags & STATUSREG_DA) { -			dprintk("CAM supports DA IRQ\n"); -			ca->slot_info[slot].da_irq_supported = 1; -		} -		break; - -	case DVB_CA_SLOTSTATE_RUNNING: -		if (ca->open) -			dvb_ca_en50221_thread_wakeup(ca); -		break; -	} -} - - - -/* ******************************************************************************** */ -/* EN50221 thread functions */ - -/** - * Wake up the DVB CA thread - * - * @param ca CA instance. - */ -static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) -{ - -	dprintk("%s\n", __func__); - -	ca->wakeup = 1; -	mb(); -	wake_up_process(ca->thread); -} - -/** - * Update the delay used by the thread. - * - * @param ca CA instance. - */ -static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) -{ -	int delay; -	int curdelay = 100000000; -	int slot; - -	/* Beware of too high polling frequency, because one polling -	 * call might take several hundred milliseconds until timeout! -	 */ -	for (slot = 0; slot < ca->slot_count; slot++) { -		switch (ca->slot_info[slot].slot_state) { -		default: -		case DVB_CA_SLOTSTATE_NONE: -			delay = HZ * 60;  /* 60s */ -			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) -				delay = HZ * 5;  /* 5s */ -			break; -		case DVB_CA_SLOTSTATE_INVALID: -			delay = HZ * 60;  /* 60s */ -			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) -				delay = HZ / 10;  /* 100ms */ -			break; - -		case DVB_CA_SLOTSTATE_UNINITIALISED: -		case DVB_CA_SLOTSTATE_WAITREADY: -		case DVB_CA_SLOTSTATE_VALIDATE: -		case DVB_CA_SLOTSTATE_WAITFR: -		case DVB_CA_SLOTSTATE_LINKINIT: -			delay = HZ / 10;  /* 100ms */ -			break; - -		case DVB_CA_SLOTSTATE_RUNNING: -			delay = HZ * 60;  /* 60s */ -			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) -				delay = HZ / 10;  /* 100ms */ -			if (ca->open) { -				if ((!ca->slot_info[slot].da_irq_supported) || -				    (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) -					delay = HZ / 10;  /* 100ms */ -			} -			break; -		} - -		if (delay < curdelay) -			curdelay = delay; -	} - -	ca->delay = curdelay; -} - - - -/** - * Kernel thread which monitors CA slots for CAM changes, and performs data transfers. - */ -static int dvb_ca_en50221_thread(void *data) -{ -	struct dvb_ca_private *ca = data; -	int slot; -	int flags; -	int status; -	int pktcount; -	void *rxbuf; - -	dprintk("%s\n", __func__); - -	/* choose the correct initial delay */ -	dvb_ca_en50221_thread_update_delay(ca); - -	/* main loop */ -	while (!kthread_should_stop()) { -		/* sleep for a bit */ -		if (!ca->wakeup) { -			set_current_state(TASK_INTERRUPTIBLE); -			schedule_timeout(ca->delay); -			if (kthread_should_stop()) -				return 0; -		} -		ca->wakeup = 0; - -		/* go through all the slots processing them */ -		for (slot = 0; slot < ca->slot_count; slot++) { - -			mutex_lock(&ca->slot_info[slot].slot_lock); - -			// check the cam status + deal with CAMCHANGEs -			while (dvb_ca_en50221_check_camstatus(ca, slot)) { -				/* clear down an old CI slot if necessary */ -				if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) -					dvb_ca_en50221_slot_shutdown(ca, slot); - -				/* if a CAM is NOW present, initialise it */ -				if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED; -				} - -				/* we've handled one CAMCHANGE */ -				dvb_ca_en50221_thread_update_delay(ca); -				atomic_dec(&ca->slot_info[slot].camchange_count); -			} - -			// CAM state machine -			switch (ca->slot_info[slot].slot_state) { -			case DVB_CA_SLOTSTATE_NONE: -			case DVB_CA_SLOTSTATE_INVALID: -				// no action needed -				break; - -			case DVB_CA_SLOTSTATE_UNINITIALISED: -				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; -				ca->pub->slot_reset(ca->pub, slot); -				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); -				break; - -			case DVB_CA_SLOTSTATE_WAITREADY: -				if (time_after(jiffies, ca->slot_info[slot].timeout)) { -					printk("dvb_ca adaptor %d: PC card did not respond :(\n", -					       ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} -				// no other action needed; will automatically change state when ready -				break; - -			case DVB_CA_SLOTSTATE_VALIDATE: -				if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { -					/* we need this extra check for annoying interfaces like the budget-av */ -					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && -					    (ca->pub->poll_slot_status)) { -						status = ca->pub->poll_slot_status(ca->pub, slot, 0); -						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { -							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; -							dvb_ca_en50221_thread_update_delay(ca); -							break; -						} -					} - -					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", -					       ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} -				if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { -					printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", -					       ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} -				if (ca->pub->write_cam_control(ca->pub, slot, -							       CTRLIF_COMMAND, CMDREG_RS) != 0) { -					printk("dvb_ca adapter %d: Unable to reset CAM IF\n", -					       ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} -				dprintk("DVB CAM validated successfully\n"); - -				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); -				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; -				ca->wakeup = 1; -				break; - -			case DVB_CA_SLOTSTATE_WAITFR: -				if (time_after(jiffies, ca->slot_info[slot].timeout)) { -					printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", -					       ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} - -				flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); -				if (flags & STATUSREG_FR) { -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; -					ca->wakeup = 1; -				} -				break; - -			case DVB_CA_SLOTSTATE_LINKINIT: -				if (dvb_ca_en50221_link_init(ca, slot) != 0) { -					/* we need this extra check for annoying interfaces like the budget-av */ -					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && -					    (ca->pub->poll_slot_status)) { -						status = ca->pub->poll_slot_status(ca->pub, slot, 0); -						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { -							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; -							dvb_ca_en50221_thread_update_delay(ca); -							break; -						} -					} - -					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); -					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -					dvb_ca_en50221_thread_update_delay(ca); -					break; -				} - -				if (ca->slot_info[slot].rx_buffer.data == NULL) { -					rxbuf = vmalloc(RX_BUFFER_SIZE); -					if (rxbuf == NULL) { -						printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); -						ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; -						dvb_ca_en50221_thread_update_delay(ca); -						break; -					} -					dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); -				} - -				ca->pub->slot_ts_enable(ca->pub, slot); -				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; -				dvb_ca_en50221_thread_update_delay(ca); -				printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num); -				break; - -			case DVB_CA_SLOTSTATE_RUNNING: -				if (!ca->open) -					break; - -				// poll slots for data -				pktcount = 0; -				while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { -					if (!ca->open) -						break; - -					/* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ -					if (dvb_ca_en50221_check_camstatus(ca, slot)) { -						// we dont want to sleep on the next iteration so we can handle the cam change -						ca->wakeup = 1; -						break; -					} - -					/* check if we've hit our limit this time */ -					if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { -						// dont sleep; there is likely to be more data to read -						ca->wakeup = 1; -						break; -					} -				} -				break; -			} - -			mutex_unlock(&ca->slot_info[slot].slot_lock); -		} -	} - -	return 0; -} - - - -/* ******************************************************************************** */ -/* EN50221 IO interface functions */ - -/** - * Real ioctl implementation. - * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. - * - * @param inode Inode concerned. - * @param file File concerned. - * @param cmd IOCTL command. - * @param arg Associated argument. - * - * @return 0 on success, <0 on error. - */ -static int dvb_ca_en50221_io_do_ioctl(struct file *file, -				      unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	int err = 0; -	int slot; - -	dprintk("%s\n", __func__); - -	switch (cmd) { -	case CA_RESET: -		for (slot = 0; slot < ca->slot_count; slot++) { -			mutex_lock(&ca->slot_info[slot].slot_lock); -			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { -				dvb_ca_en50221_slot_shutdown(ca, slot); -				if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) -					dvb_ca_en50221_camchange_irq(ca->pub, -								     slot, -								     DVB_CA_EN50221_CAMCHANGE_INSERTED); -			} -			mutex_unlock(&ca->slot_info[slot].slot_lock); -		} -		ca->next_read_slot = 0; -		dvb_ca_en50221_thread_wakeup(ca); -		break; - -	case CA_GET_CAP: { -		struct ca_caps *caps = parg; - -		caps->slot_num = ca->slot_count; -		caps->slot_type = CA_CI_LINK; -		caps->descr_num = 0; -		caps->descr_type = 0; -		break; -	} - -	case CA_GET_SLOT_INFO: { -		struct ca_slot_info *info = parg; - -		if ((info->num > ca->slot_count) || (info->num < 0)) -			return -EINVAL; - -		info->type = CA_CI_LINK; -		info->flags = 0; -		if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) -			&& (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { -			info->flags = CA_CI_MODULE_PRESENT; -		} -		if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) { -			info->flags |= CA_CI_MODULE_READY; -		} -		break; -	} - -	default: -		err = -EINVAL; -		break; -	} - -	return err; -} - - -/** - * Wrapper for ioctl implementation. - * - * @param inode Inode concerned. - * @param file File concerned. - * @param cmd IOCTL command. - * @param arg Associated argument. - * - * @return 0 on success, <0 on error. - */ -static long dvb_ca_en50221_io_ioctl(struct file *file, -				    unsigned int cmd, unsigned long arg) -{ -	return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); -} - - -/** - * Implementation of write() syscall. - * - * @param file File structure. - * @param buf Source buffer. - * @param count Size of source buffer. - * @param ppos Position in file (ignored). - * - * @return Number of bytes read, or <0 on error. - */ -static ssize_t dvb_ca_en50221_io_write(struct file *file, -				       const char __user * buf, size_t count, loff_t * ppos) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	u8 slot, connection_id; -	int status; -	u8 fragbuf[HOST_LINK_BUF_SIZE]; -	int fragpos = 0; -	int fraglen; -	unsigned long timeout; -	int written; - -	dprintk("%s\n", __func__); - -	/* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ -	if (count < 2) -		return -EINVAL; - -	/* extract slot & connection id */ -	if (copy_from_user(&slot, buf, 1)) -		return -EFAULT; -	if (copy_from_user(&connection_id, buf + 1, 1)) -		return -EFAULT; -	buf += 2; -	count -= 2; - -	/* check if the slot is actually running */ -	if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) -		return -EINVAL; - -	/* fragment the packets & store in the buffer */ -	while (fragpos < count) { -		fraglen = ca->slot_info[slot].link_buf_size - 2; -		if ((count - fragpos) < fraglen) -			fraglen = count - fragpos; - -		fragbuf[0] = connection_id; -		fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; -		status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); -		if (status) { -			status = -EFAULT; -			goto exit; -		} - -		timeout = jiffies + HZ / 2; -		written = 0; -		while (!time_after(jiffies, timeout)) { -			/* check the CAM hasn't been removed/reset in the meantime */ -			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) { -				status = -EIO; -				goto exit; -			} - -			mutex_lock(&ca->slot_info[slot].slot_lock); -			status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); -			mutex_unlock(&ca->slot_info[slot].slot_lock); -			if (status == (fraglen + 2)) { -				written = 1; -				break; -			} -			if (status != -EAGAIN) -				goto exit; - -			msleep(1); -		} -		if (!written) { -			status = -EIO; -			goto exit; -		} - -		fragpos += fraglen; -	} -	status = count + 2; - -exit: -	return status; -} - - -/** - * Condition for waking up in dvb_ca_en50221_io_read_condition - */ -static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, -					    int *result, int *_slot) -{ -	int slot; -	int slot_count = 0; -	int idx; -	size_t fraglen; -	int connection_id = -1; -	int found = 0; -	u8 hdr[2]; - -	slot = ca->next_read_slot; -	while ((slot_count < ca->slot_count) && (!found)) { -		if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) -			goto nextslot; - -		if (ca->slot_info[slot].rx_buffer.data == NULL) { -			return 0; -		} - -		idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); -		while (idx != -1) { -			dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); -			if (connection_id == -1) -				connection_id = hdr[0]; -			if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { -				*_slot = slot; -				found = 1; -				break; -			} - -			idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); -		} - -nextslot: -		slot = (slot + 1) % ca->slot_count; -		slot_count++; -	} - -	ca->next_read_slot = slot; -	return found; -} - - -/** - * Implementation of read() syscall. - * - * @param file File structure. - * @param buf Destination buffer. - * @param count Size of destination buffer. - * @param ppos Position in file (ignored). - * - * @return Number of bytes read, or <0 on error. - */ -static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, -				      size_t count, loff_t * ppos) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	int status; -	int result = 0; -	u8 hdr[2]; -	int slot; -	int connection_id = -1; -	size_t idx, idx2; -	int last_fragment = 0; -	size_t fraglen; -	int pktlen; -	int dispose = 0; - -	dprintk("%s\n", __func__); - -	/* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ -	if (count < 2) -		return -EINVAL; - -	/* wait for some data */ -	if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { - -		/* if we're in nonblocking mode, exit immediately */ -		if (file->f_flags & O_NONBLOCK) -			return -EWOULDBLOCK; - -		/* wait for some data */ -		status = wait_event_interruptible(ca->wait_queue, -						  dvb_ca_en50221_io_read_condition -						  (ca, &result, &slot)); -	} -	if ((status < 0) || (result < 0)) { -		if (result) -			return result; -		return status; -	} - -	idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); -	pktlen = 2; -	do { -		if (idx == -1) { -			printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num); -			status = -EIO; -			goto exit; -		} - -		dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); -		if (connection_id == -1) -			connection_id = hdr[0]; -		if (hdr[0] == connection_id) { -			if (pktlen < count) { -				if ((pktlen + fraglen - 2) > count) { -					fraglen = count - pktlen; -				} else { -					fraglen -= 2; -				} - -				if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2, -								      buf + pktlen, fraglen)) < 0) { -					goto exit; -				} -				pktlen += fraglen; -			} - -			if ((hdr[1] & 0x80) == 0) -				last_fragment = 1; -			dispose = 1; -		} - -		idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); -		if (dispose) -			dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); -		idx = idx2; -		dispose = 0; -	} while (!last_fragment); - -	hdr[0] = slot; -	hdr[1] = connection_id; -	status = copy_to_user(buf, hdr, 2); -	if (status) { -		status = -EFAULT; -		goto exit; -	} -	status = pktlen; - -exit: -	return status; -} - - -/** - * Implementation of file open syscall. - * - * @param inode Inode concerned. - * @param file File concerned. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	int err; -	int i; - -	dprintk("%s\n", __func__); - -	if (!try_module_get(ca->pub->owner)) -		return -EIO; - -	err = dvb_generic_open(inode, file); -	if (err < 0) { -		module_put(ca->pub->owner); -		return err; -	} - -	for (i = 0; i < ca->slot_count; i++) { - -		if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { -			if (ca->slot_info[i].rx_buffer.data != NULL) { -				/* it is safe to call this here without locks because -				 * ca->open == 0. Data is not read in this case */ -				dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); -			} -		} -	} - -	ca->open = 1; -	dvb_ca_en50221_thread_update_delay(ca); -	dvb_ca_en50221_thread_wakeup(ca); - -	return 0; -} - - -/** - * Implementation of file close syscall. - * - * @param inode Inode concerned. - * @param file File concerned. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	int err; - -	dprintk("%s\n", __func__); - -	/* mark the CA device as closed */ -	ca->open = 0; -	dvb_ca_en50221_thread_update_delay(ca); - -	err = dvb_generic_release(inode, file); - -	module_put(ca->pub->owner); - -	return err; -} - - -/** - * Implementation of poll() syscall. - * - * @param file File concerned. - * @param wait poll wait table. - * - * @return Standard poll mask. - */ -static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_ca_private *ca = dvbdev->priv; -	unsigned int mask = 0; -	int slot; -	int result = 0; - -	dprintk("%s\n", __func__); - -	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { -		mask |= POLLIN; -	} - -	/* if there is something, return now */ -	if (mask) -		return mask; - -	/* wait for something to happen */ -	poll_wait(file, &ca->wait_queue, wait); - -	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { -		mask |= POLLIN; -	} - -	return mask; -} -EXPORT_SYMBOL(dvb_ca_en50221_init); - - -static const struct file_operations dvb_ca_fops = { -	.owner = THIS_MODULE, -	.read = dvb_ca_en50221_io_read, -	.write = dvb_ca_en50221_io_write, -	.unlocked_ioctl = dvb_ca_en50221_io_ioctl, -	.open = dvb_ca_en50221_io_open, -	.release = dvb_ca_en50221_io_release, -	.poll = dvb_ca_en50221_io_poll, -	.llseek = noop_llseek, -}; - -static struct dvb_device dvbdev_ca = { -	.priv = NULL, -	.users = 1, -	.readers = 1, -	.writers = 1, -	.fops = &dvb_ca_fops, -}; - - -/* ******************************************************************************** */ -/* Initialisation/shutdown functions */ - - -/** - * Initialise a new DVB CA EN50221 interface device. - * - * @param dvb_adapter DVB adapter to attach the new CA device to. - * @param ca The dvb_ca instance. - * @param flags Flags describing the CA device (DVB_CA_FLAG_*). - * @param 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 *pubca, int flags, int slot_count) -{ -	int ret; -	struct dvb_ca_private *ca = NULL; -	int i; - -	dprintk("%s\n", __func__); - -	if (slot_count < 1) -		return -EINVAL; - -	/* initialise the system data */ -	if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) { -		ret = -ENOMEM; -		goto error; -	} -	ca->pub = pubca; -	ca->flags = flags; -	ca->slot_count = slot_count; -	if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) { -		ret = -ENOMEM; -		goto error; -	} -	init_waitqueue_head(&ca->wait_queue); -	ca->open = 0; -	ca->wakeup = 0; -	ca->next_read_slot = 0; -	pubca->private = ca; - -	/* register the DVB device */ -	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); -	if (ret) -		goto error; - -	/* now initialise each slot */ -	for (i = 0; i < slot_count; i++) { -		memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); -		ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; -		atomic_set(&ca->slot_info[i].camchange_count, 0); -		ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; -		mutex_init(&ca->slot_info[i].slot_lock); -	} - -	if (signal_pending(current)) { -		ret = -EINTR; -		goto error; -	} -	mb(); - -	/* create a kthread for monitoring this CA device */ -	ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", -				 ca->dvbdev->adapter->num, ca->dvbdev->id); -	if (IS_ERR(ca->thread)) { -		ret = PTR_ERR(ca->thread); -		printk("dvb_ca_init: failed to start kernel_thread (%d)\n", -			ret); -		goto error; -	} -	return 0; - -error: -	if (ca != NULL) { -		if (ca->dvbdev != NULL) -			dvb_unregister_device(ca->dvbdev); -		kfree(ca->slot_info); -		kfree(ca); -	} -	pubca->private = NULL; -	return ret; -} -EXPORT_SYMBOL(dvb_ca_en50221_release); - - - -/** - * Release a DVB CA EN50221 interface device. - * - * @param ca_dev The dvb_device_t instance for the CA device. - * @param ca The associated dvb_ca instance. - */ -void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) -{ -	struct dvb_ca_private *ca = pubca->private; -	int i; - -	dprintk("%s\n", __func__); - -	/* shutdown the thread if there was one */ -	kthread_stop(ca->thread); - -	for (i = 0; i < ca->slot_count; i++) { -		dvb_ca_en50221_slot_shutdown(ca, i); -		vfree(ca->slot_info[i].rx_buffer.data); -	} -	kfree(ca->slot_info); -	dvb_unregister_device(ca->dvbdev); -	kfree(ca); -	pubca->private = NULL; -} diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h deleted file mode 100644 index 7df2e141187..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ /dev/null @@ -1,136 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#ifndef _DVB_CA_EN50221_H_ -#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 - - - -/* Structure describing a CA interface */ -struct dvb_ca_en50221 { - -	/* the module owning this structure */ -	struct module* owner; - -	/* NOTE: the read_*, write_* and poll_slot_status functions will be -	 * called for different slots concurrently and need to use locks where -	 * and if appropriate. There will be no concurrent access to one slot. -	 */ - -	/* functions for accessing attribute memory on the CAM */ -	int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); -	int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value); - -	/* functions for accessing the control interface on the CAM */ -	int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address); -	int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value); - -	/* Functions for controlling slots */ -	int (*slot_reset)(struct dvb_ca_en50221* ca, int slot); -	int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot); -	int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot); - -	/* -	* Poll slot status. -	* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set -	*/ -	int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open); - -	/* private data, used by caller */ -	void* data; - -	/* Opaque data used by the dvb_ca core. Do not modify! */ -	void* private; -}; - - - - -/* ******************************************************************************** */ -/* Functions for reporting IRQ events */ - -/** - * A CAMCHANGE IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - * @param change_type One of the DVB_CA_CAMCHANGE_* values - */ -void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type); - -/** - * A CAMREADY IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot); - -/** - * An FR or a DA IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot); - - - -/* ******************************************************************************** */ -/* Initialisation/shutdown functions */ - -/** - * Initialise a new DVB CA device. - * - * @param dvb_adapter DVB adapter to attach the new CA device to. - * @param ca The dvb_ca instance. - * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*). - * @param slot_count Number of slots supported. - * - * @return 0 on success, nonzero on failure - */ -extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count); - -/** - * Release a DVB CA device. - * - * @param ca The associated dvb_ca instance. - */ -extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca); - - - -#endif diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c deleted file mode 100644 index 4a88a3e4db2..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ /dev/null @@ -1,1302 +0,0 @@ -/* - * dvb_demux.c - DVB kernel demux API - * - * Copyright (C) 2000-2001 Ralph  Metzler <ralph@convergence.de> - *		       & Marcus Metzler <marcus@convergence.de> - *			 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. - * - * 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. - * - */ - -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/string.h> -#include <linux/crc32.h> -#include <asm/uaccess.h> -#include <asm/div64.h> - -#include "dvb_demux.h" - -#define NOBUFS -/* -** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog -*/ -// #define DVB_DEMUX_SECTION_LOSS_LOG - -static int dvb_demux_tscheck; -module_param(dvb_demux_tscheck, int, 0644); -MODULE_PARM_DESC(dvb_demux_tscheck, -		"enable transport stream continuity and TEI check"); - -static int dvb_demux_speedcheck; -module_param(dvb_demux_speedcheck, int, 0644); -MODULE_PARM_DESC(dvb_demux_speedcheck, -		"enable transport stream speed check"); - -#define dprintk_tscheck(x...) do {                              \ -		if (dvb_demux_tscheck && printk_ratelimit())    \ -			printk(x);                              \ -	} while (0) - -/****************************************************************************** - * static inlined helper functions - ******************************************************************************/ - -static inline u16 section_length(const u8 *buf) -{ -	return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; -} - -static inline u16 ts_pid(const u8 *buf) -{ -	return ((buf[1] & 0x1f) << 8) + buf[2]; -} - -static inline u8 payload(const u8 *tsp) -{ -	if (!(tsp[3] & 0x10))	// no payload? -		return 0; - -	if (tsp[3] & 0x20) {	// adaptation field? -		if (tsp[4] > 183)	// corrupted data? -			return 0; -		else -			return 184 - 1 - tsp[4]; -	} - -	return 184; -} - -static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len) -{ -	return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len)); -} - -static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s, -			    size_t len) -{ -	memcpy(d, s, len); -} - -/****************************************************************************** - * Software filter functions - ******************************************************************************/ - -static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, -					   const u8 *buf) -{ -	int count = payload(buf); -	int p; -	//int ccok; -	//u8 cc; - -	if (count == 0) -		return -1; - -	p = 188 - count; - -	/* -	cc = buf[3] & 0x0f; -	ccok = ((feed->cc + 1) & 0x0f) == cc; -	feed->cc = cc; -	if (!ccok) -		printk("missed packet!\n"); -	*/ - -	if (buf[1] & 0x40)	// PUSI ? -		feed->peslen = 0xfffa; - -	feed->peslen += count; - -	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); -} - -static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, -					  struct dvb_demux_filter *f) -{ -	u8 neq = 0; -	int i; - -	for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { -		u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i]; - -		if (f->maskandmode[i] & xor) -			return 0; - -		neq |= f->maskandnotmode[i] & xor; -	} - -	if (f->doneq && !neq) -		return 0; - -	return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, -			    NULL, 0, &f->filter, DMX_OK); -} - -static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) -{ -	struct dvb_demux *demux = feed->demux; -	struct dvb_demux_filter *f = feed->filter; -	struct dmx_section_feed *sec = &feed->feed.sec; -	int section_syntax_indicator; - -	if (!sec->is_filtering) -		return 0; - -	if (!f) -		return 0; - -	if (sec->check_crc) { -		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); -		if (section_syntax_indicator && -		    demux->check_crc32(feed, sec->secbuf, sec->seclen)) -			return -1; -	} - -	do { -		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0) -			return -1; -	} while ((f = f->next) && sec->is_filtering); - -	sec->seclen = 0; - -	return 0; -} - -static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) -{ -	struct dmx_section_feed *sec = &feed->feed.sec; - -#ifdef DVB_DEMUX_SECTION_LOSS_LOG -	if (sec->secbufp < sec->tsfeedp) { -		int i, n = sec->tsfeedp - sec->secbufp; - -		/* -		 * Section padding is done with 0xff bytes entirely. -		 * Due to speed reasons, we won't check all of them -		 * but just first and last. -		 */ -		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { -			printk("dvb_demux.c section ts padding loss: %d/%d\n", -			       n, sec->tsfeedp); -			printk("dvb_demux.c pad data:"); -			for (i = 0; i < n; i++) -				printk(" %02x", sec->secbuf[i]); -			printk("\n"); -		} -	} -#endif - -	sec->tsfeedp = sec->secbufp = sec->seclen = 0; -	sec->secbuf = sec->secbuf_base; -} - -/* - * Losless Section Demux 1.4.1 by Emard - * Valsecchi Patrick: - *  - middle of section A  (no PUSI) - *  - end of section A and start of section B - *    (with PUSI pointing to the start of the second section) - * - *  In this case, without feed->pusi_seen you'll receive a garbage section - *  consisting of the end of section A. Basically because tsfeedp - *  is incemented and the use=0 condition is not raised - *  when the second packet arrives. - * - * Fix: - * when demux is started, let feed->pusi_seen = 0 to - * prevent initial feeding of garbage from the end of - * previous section. When you for the first time see PUSI=1 - * then set feed->pusi_seen = 1 - */ -static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, -					      const u8 *buf, u8 len) -{ -	struct dvb_demux *demux = feed->demux; -	struct dmx_section_feed *sec = &feed->feed.sec; -	u16 limit, seclen, n; - -	if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) -		return 0; - -	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { -#ifdef DVB_DEMUX_SECTION_LOSS_LOG -		printk("dvb_demux.c section buffer full loss: %d/%d\n", -		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, -		       DMX_MAX_SECFEED_SIZE); -#endif -		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; -	} - -	if (len <= 0) -		return 0; - -	demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len); -	sec->tsfeedp += len; - -	/* -	 * Dump all the sections we can find in the data (Emard) -	 */ -	limit = sec->tsfeedp; -	if (limit > DMX_MAX_SECFEED_SIZE) -		return -1;	/* internal error should never happen */ - -	/* to be sure always set secbuf */ -	sec->secbuf = sec->secbuf_base + sec->secbufp; - -	for (n = 0; sec->secbufp + 2 < limit; n++) { -		seclen = section_length(sec->secbuf); -		if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE -		    || seclen + sec->secbufp > limit) -			return 0; -		sec->seclen = seclen; -		sec->crc_val = ~0; -		/* dump [secbuf .. secbuf+seclen) */ -		if (feed->pusi_seen) -			dvb_dmx_swfilter_section_feed(feed); -#ifdef DVB_DEMUX_SECTION_LOSS_LOG -		else -			printk("dvb_demux.c pusi not seen, discarding section data\n"); -#endif -		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */ -		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */ -	} - -	return 0; -} - -static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, -					   const u8 *buf) -{ -	u8 p, count; -	int ccok, dc_i = 0; -	u8 cc; - -	count = payload(buf); - -	if (count == 0)		/* count == 0 if no payload or out of range */ -		return -1; - -	p = 188 - count;	/* payload start */ - -	cc = buf[3] & 0x0f; -	ccok = ((feed->cc + 1) & 0x0f) == cc; -	feed->cc = cc; - -	if (buf[3] & 0x20) { -		/* adaption field present, check for discontinuity_indicator */ -		if ((buf[4] > 0) && (buf[5] & 0x80)) -			dc_i = 1; -	} - -	if (!ccok || dc_i) { -#ifdef DVB_DEMUX_SECTION_LOSS_LOG -		printk("dvb_demux.c discontinuity detected %d bytes lost\n", -		       count); -		/* -		 * those bytes under sume circumstances will again be reported -		 * in the following dvb_dmx_swfilter_section_new -		 */ -#endif -		/* -		 * Discontinuity detected. Reset pusi_seen = 0 to -		 * stop feeding of suspicious data until next PUSI=1 arrives -		 */ -		feed->pusi_seen = 0; -		dvb_dmx_swfilter_section_new(feed); -	} - -	if (buf[1] & 0x40) { -		/* PUSI=1 (is set), section boundary is here */ -		if (count > 1 && buf[p] < count) { -			const u8 *before = &buf[p + 1]; -			u8 before_len = buf[p]; -			const u8 *after = &before[before_len]; -			u8 after_len = count - 1 - before_len; - -			dvb_dmx_swfilter_section_copy_dump(feed, before, -							   before_len); -			/* before start of new section, set pusi_seen = 1 */ -			feed->pusi_seen = 1; -			dvb_dmx_swfilter_section_new(feed); -			dvb_dmx_swfilter_section_copy_dump(feed, after, -							   after_len); -		} -#ifdef DVB_DEMUX_SECTION_LOSS_LOG -		else if (count > 0) -			printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count); -#endif -	} else { -		/* PUSI=0 (is not set), no section boundary */ -		dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); -	} - -	return 0; -} - -static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, -						const u8 *buf) -{ -	switch (feed->type) { -	case DMX_TYPE_TS: -		if (!feed->feed.ts.is_filtering) -			break; -		if (feed->ts_type & TS_PACKET) { -			if (feed->ts_type & TS_PAYLOAD_ONLY) -				dvb_dmx_swfilter_payload(feed, buf); -			else -				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, -					    DMX_OK); -		} -		if (feed->ts_type & TS_DECODER) -			if (feed->demux->write_to_decoder) -				feed->demux->write_to_decoder(feed, buf, 188); -		break; - -	case DMX_TYPE_SEC: -		if (!feed->feed.sec.is_filtering) -			break; -		if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) -			feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; -		break; - -	default: -		break; -	} -} - -#define DVR_FEED(f)							\ -	(((f)->type == DMX_TYPE_TS) &&					\ -	((f)->feed.ts.is_filtering) &&					\ -	(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET)) - -static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) -{ -	struct dvb_demux_feed *feed; -	u16 pid = ts_pid(buf); -	int dvr_done = 0; - -	if (dvb_demux_speedcheck) { -		struct timespec cur_time, delta_time; -		u64 speed_bytes, speed_timedelta; - -		demux->speed_pkts_cnt++; - -		/* show speed every SPEED_PKTS_INTERVAL packets */ -		if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) { -			cur_time = current_kernel_time(); - -			if (demux->speed_last_time.tv_sec != 0 && -					demux->speed_last_time.tv_nsec != 0) { -				delta_time = timespec_sub(cur_time, -						demux->speed_last_time); -				speed_bytes = (u64)demux->speed_pkts_cnt -					* 188 * 8; -				/* convert to 1024 basis */ -				speed_bytes = 1000 * div64_u64(speed_bytes, -						1024); -				speed_timedelta = -					(u64)timespec_to_ns(&delta_time); -				speed_timedelta = div64_u64(speed_timedelta, -						1000000); /* nsec -> usec */ -				printk(KERN_INFO "TS speed %llu Kbits/sec \n", -						div64_u64(speed_bytes, -							speed_timedelta)); -			}; - -			demux->speed_last_time = cur_time; -			demux->speed_pkts_cnt = 0; -		}; -	}; - -	if (demux->cnt_storage && dvb_demux_tscheck) { -		/* check pkt counter */ -		if (pid < MAX_PID) { -			if (buf[1] & 0x80) -				dprintk_tscheck("TEI detected. " -						"PID=0x%x data1=0x%x\n", -						pid, buf[1]); - -			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); - -			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf; -		}; -		/* end check */ -	}; - -	list_for_each_entry(feed, &demux->feed_list, list_head) { -		if ((feed->pid != pid) && (feed->pid != 0x2000)) -			continue; - -		/* copy each packet only once to the dvr device, even -		 * if a PID is in multiple filters (e.g. video + PCR) */ -		if ((DVR_FEED(feed)) && (dvr_done++)) -			continue; - -		if (feed->pid == pid) -			dvb_dmx_swfilter_packet_type(feed, buf); -		else if (feed->pid == 0x2000) -			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); -	} -} - -void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, -			      size_t count) -{ -	spin_lock(&demux->lock); - -	while (count--) { -		if (buf[0] == 0x47) -			dvb_dmx_swfilter_packet(demux, buf); -		buf += 188; -	} - -	spin_unlock(&demux->lock); -} - -EXPORT_SYMBOL(dvb_dmx_swfilter_packets); - -void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) -{ -	int p = 0, i, j; - -	spin_lock(&demux->lock); - -	if (demux->tsbufp) { -		i = demux->tsbufp; -		j = 188 - i; -		if (count < j) { -			memcpy(&demux->tsbuf[i], buf, count); -			demux->tsbufp += count; -			goto bailout; -		} -		memcpy(&demux->tsbuf[i], buf, j); -		if (demux->tsbuf[0] == 0x47) -			dvb_dmx_swfilter_packet(demux, demux->tsbuf); -		demux->tsbufp = 0; -		p += j; -	} - -	while (p < count) { -		if (buf[p] == 0x47) { -			if (count - p >= 188) { -				dvb_dmx_swfilter_packet(demux, &buf[p]); -				p += 188; -			} else { -				i = count - p; -				memcpy(demux->tsbuf, &buf[p], i); -				demux->tsbufp = i; -				goto bailout; -			} -		} else -			p++; -	} - -bailout: -	spin_unlock(&demux->lock); -} - -EXPORT_SYMBOL(dvb_dmx_swfilter); - -void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) -{ -	int p = 0, i, j; -	u8 tmppack[188]; - -	spin_lock(&demux->lock); - -	if (demux->tsbufp) { -		i = demux->tsbufp; -		j = 204 - i; -		if (count < j) { -			memcpy(&demux->tsbuf[i], buf, count); -			demux->tsbufp += count; -			goto bailout; -		} -		memcpy(&demux->tsbuf[i], buf, j); -		if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { -			memcpy(tmppack, demux->tsbuf, 188); -			if (tmppack[0] == 0xB8) -				tmppack[0] = 0x47; -			dvb_dmx_swfilter_packet(demux, tmppack); -		} -		demux->tsbufp = 0; -		p += j; -	} - -	while (p < count) { -		if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { -			if (count - p >= 204) { -				memcpy(tmppack, &buf[p], 188); -				if (tmppack[0] == 0xB8) -					tmppack[0] = 0x47; -				dvb_dmx_swfilter_packet(demux, tmppack); -				p += 204; -			} else { -				i = count - p; -				memcpy(demux->tsbuf, &buf[p], i); -				demux->tsbufp = i; -				goto bailout; -			} -		} else { -			p++; -		} -	} - -bailout: -	spin_unlock(&demux->lock); -} - -EXPORT_SYMBOL(dvb_dmx_swfilter_204); - -static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) -{ -	int i; - -	for (i = 0; i < demux->filternum; i++) -		if (demux->filter[i].state == DMX_STATE_FREE) -			break; - -	if (i == demux->filternum) -		return NULL; - -	demux->filter[i].state = DMX_STATE_ALLOCATED; - -	return &demux->filter[i]; -} - -static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux) -{ -	int i; - -	for (i = 0; i < demux->feednum; i++) -		if (demux->feed[i].state == DMX_STATE_FREE) -			break; - -	if (i == demux->feednum) -		return NULL; - -	demux->feed[i].state = DMX_STATE_ALLOCATED; - -	return &demux->feed[i]; -} - -static int dvb_demux_feed_find(struct dvb_demux_feed *feed) -{ -	struct dvb_demux_feed *entry; - -	list_for_each_entry(entry, &feed->demux->feed_list, list_head) -		if (entry == feed) -			return 1; - -	return 0; -} - -static void dvb_demux_feed_add(struct dvb_demux_feed *feed) -{ -	spin_lock_irq(&feed->demux->lock); -	if (dvb_demux_feed_find(feed)) { -		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", -		       __func__, feed->type, feed->state, feed->pid); -		goto out; -	} - -	list_add(&feed->list_head, &feed->demux->feed_list); -out: -	spin_unlock_irq(&feed->demux->lock); -} - -static void dvb_demux_feed_del(struct dvb_demux_feed *feed) -{ -	spin_lock_irq(&feed->demux->lock); -	if (!(dvb_demux_feed_find(feed))) { -		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", -		       __func__, feed->type, feed->state, feed->pid); -		goto out; -	} - -	list_del(&feed->list_head); -out: -	spin_unlock_irq(&feed->demux->lock); -} - -static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, -			   enum dmx_ts_pes pes_type, -			   size_t circular_buffer_size, struct timespec timeout) -{ -	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; -	struct dvb_demux *demux = feed->demux; - -	if (pid > DMX_MAX_PID) -		return -EINVAL; - -	if (mutex_lock_interruptible(&demux->mutex)) -		return -ERESTARTSYS; - -	if (ts_type & TS_DECODER) { -		if (pes_type >= DMX_TS_PES_OTHER) { -			mutex_unlock(&demux->mutex); -			return -EINVAL; -		} - -		if (demux->pesfilter[pes_type] && -		    demux->pesfilter[pes_type] != feed) { -			mutex_unlock(&demux->mutex); -			return -EINVAL; -		} - -		demux->pesfilter[pes_type] = feed; -		demux->pids[pes_type] = pid; -	} - -	dvb_demux_feed_add(feed); - -	feed->pid = pid; -	feed->buffer_size = circular_buffer_size; -	feed->timeout = timeout; -	feed->ts_type = ts_type; -	feed->pes_type = pes_type; - -	if (feed->buffer_size) { -#ifdef NOBUFS -		feed->buffer = NULL; -#else -		feed->buffer = vmalloc(feed->buffer_size); -		if (!feed->buffer) { -			mutex_unlock(&demux->mutex); -			return -ENOMEM; -		} -#endif -	} - -	feed->state = DMX_STATE_READY; -	mutex_unlock(&demux->mutex); - -	return 0; -} - -static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) -{ -	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; -	struct dvb_demux *demux = feed->demux; -	int ret; - -	if (mutex_lock_interruptible(&demux->mutex)) -		return -ERESTARTSYS; - -	if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { -		mutex_unlock(&demux->mutex); -		return -EINVAL; -	} - -	if (!demux->start_feed) { -		mutex_unlock(&demux->mutex); -		return -ENODEV; -	} - -	if ((ret = demux->start_feed(feed)) < 0) { -		mutex_unlock(&demux->mutex); -		return ret; -	} - -	spin_lock_irq(&demux->lock); -	ts_feed->is_filtering = 1; -	feed->state = DMX_STATE_GO; -	spin_unlock_irq(&demux->lock); -	mutex_unlock(&demux->mutex); - -	return 0; -} - -static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) -{ -	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; -	struct dvb_demux *demux = feed->demux; -	int ret; - -	mutex_lock(&demux->mutex); - -	if (feed->state < DMX_STATE_GO) { -		mutex_unlock(&demux->mutex); -		return -EINVAL; -	} - -	if (!demux->stop_feed) { -		mutex_unlock(&demux->mutex); -		return -ENODEV; -	} - -	ret = demux->stop_feed(feed); - -	spin_lock_irq(&demux->lock); -	ts_feed->is_filtering = 0; -	feed->state = DMX_STATE_ALLOCATED; -	spin_unlock_irq(&demux->lock); -	mutex_unlock(&demux->mutex); - -	return ret; -} - -static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, -				   struct dmx_ts_feed **ts_feed, -				   dmx_ts_cb callback) -{ -	struct dvb_demux *demux = (struct dvb_demux *)dmx; -	struct dvb_demux_feed *feed; - -	if (mutex_lock_interruptible(&demux->mutex)) -		return -ERESTARTSYS; - -	if (!(feed = dvb_dmx_feed_alloc(demux))) { -		mutex_unlock(&demux->mutex); -		return -EBUSY; -	} - -	feed->type = DMX_TYPE_TS; -	feed->cb.ts = callback; -	feed->demux = demux; -	feed->pid = 0xffff; -	feed->peslen = 0xfffa; -	feed->buffer = NULL; - -	(*ts_feed) = &feed->feed.ts; -	(*ts_feed)->parent = dmx; -	(*ts_feed)->priv = NULL; -	(*ts_feed)->is_filtering = 0; -	(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; -	(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; -	(*ts_feed)->set = dmx_ts_feed_set; - -	if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { -		feed->state = DMX_STATE_FREE; -		mutex_unlock(&demux->mutex); -		return -EBUSY; -	} - -	feed->filter->type = DMX_TYPE_TS; -	feed->filter->feed = feed; -	feed->filter->state = DMX_STATE_READY; - -	mutex_unlock(&demux->mutex); - -	return 0; -} - -static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, -				  struct dmx_ts_feed *ts_feed) -{ -	struct dvb_demux *demux = (struct dvb_demux *)dmx; -	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; - -	mutex_lock(&demux->mutex); - -	if (feed->state == DMX_STATE_FREE) { -		mutex_unlock(&demux->mutex); -		return -EINVAL; -	} -#ifndef NOBUFS -	vfree(feed->buffer); -	feed->buffer = NULL; -#endif - -	feed->state = DMX_STATE_FREE; -	feed->filter->state = DMX_STATE_FREE; - -	dvb_demux_feed_del(feed); - -	feed->pid = 0xffff; - -	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) -		demux->pesfilter[feed->pes_type] = NULL; - -	mutex_unlock(&demux->mutex); -	return 0; -} - -/****************************************************************************** - * dmx_section_feed API calls - ******************************************************************************/ - -static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, -					    struct dmx_section_filter **filter) -{ -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdemux = dvbdmxfeed->demux; -	struct dvb_demux_filter *dvbdmxfilter; - -	if (mutex_lock_interruptible(&dvbdemux->mutex)) -		return -ERESTARTSYS; - -	dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); -	if (!dvbdmxfilter) { -		mutex_unlock(&dvbdemux->mutex); -		return -EBUSY; -	} - -	spin_lock_irq(&dvbdemux->lock); -	*filter = &dvbdmxfilter->filter; -	(*filter)->parent = feed; -	(*filter)->priv = NULL; -	dvbdmxfilter->feed = dvbdmxfeed; -	dvbdmxfilter->type = DMX_TYPE_SEC; -	dvbdmxfilter->state = DMX_STATE_READY; -	dvbdmxfilter->next = dvbdmxfeed->filter; -	dvbdmxfeed->filter = dvbdmxfilter; -	spin_unlock_irq(&dvbdemux->lock); - -	mutex_unlock(&dvbdemux->mutex); -	return 0; -} - -static int dmx_section_feed_set(struct dmx_section_feed *feed, -				u16 pid, size_t circular_buffer_size, -				int check_crc) -{ -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - -	if (pid > 0x1fff) -		return -EINVAL; - -	if (mutex_lock_interruptible(&dvbdmx->mutex)) -		return -ERESTARTSYS; - -	dvb_demux_feed_add(dvbdmxfeed); - -	dvbdmxfeed->pid = pid; -	dvbdmxfeed->buffer_size = circular_buffer_size; -	dvbdmxfeed->feed.sec.check_crc = check_crc; - -#ifdef NOBUFS -	dvbdmxfeed->buffer = NULL; -#else -	dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); -	if (!dvbdmxfeed->buffer) { -		mutex_unlock(&dvbdmx->mutex); -		return -ENOMEM; -	} -#endif - -	dvbdmxfeed->state = DMX_STATE_READY; -	mutex_unlock(&dvbdmx->mutex); -	return 0; -} - -static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) -{ -	int i; -	struct dvb_demux_filter *f; -	struct dmx_section_filter *sf; -	u8 mask, mode, doneq; - -	if (!(f = dvbdmxfeed->filter)) -		return; -	do { -		sf = &f->filter; -		doneq = 0; -		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { -			mode = sf->filter_mode[i]; -			mask = sf->filter_mask[i]; -			f->maskandmode[i] = mask & mode; -			doneq |= f->maskandnotmode[i] = mask & ~mode; -		} -		f->doneq = doneq ? 1 : 0; -	} while ((f = f->next)); -} - -static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) -{ -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -	int ret; - -	if (mutex_lock_interruptible(&dvbdmx->mutex)) -		return -ERESTARTSYS; - -	if (feed->is_filtering) { -		mutex_unlock(&dvbdmx->mutex); -		return -EBUSY; -	} - -	if (!dvbdmxfeed->filter) { -		mutex_unlock(&dvbdmx->mutex); -		return -EINVAL; -	} - -	dvbdmxfeed->feed.sec.tsfeedp = 0; -	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; -	dvbdmxfeed->feed.sec.secbufp = 0; -	dvbdmxfeed->feed.sec.seclen = 0; - -	if (!dvbdmx->start_feed) { -		mutex_unlock(&dvbdmx->mutex); -		return -ENODEV; -	} - -	prepare_secfilters(dvbdmxfeed); - -	if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { -		mutex_unlock(&dvbdmx->mutex); -		return ret; -	} - -	spin_lock_irq(&dvbdmx->lock); -	feed->is_filtering = 1; -	dvbdmxfeed->state = DMX_STATE_GO; -	spin_unlock_irq(&dvbdmx->lock); - -	mutex_unlock(&dvbdmx->mutex); -	return 0; -} - -static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) -{ -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -	int ret; - -	mutex_lock(&dvbdmx->mutex); - -	if (!dvbdmx->stop_feed) { -		mutex_unlock(&dvbdmx->mutex); -		return -ENODEV; -	} - -	ret = dvbdmx->stop_feed(dvbdmxfeed); - -	spin_lock_irq(&dvbdmx->lock); -	dvbdmxfeed->state = DMX_STATE_READY; -	feed->is_filtering = 0; -	spin_unlock_irq(&dvbdmx->lock); - -	mutex_unlock(&dvbdmx->mutex); -	return ret; -} - -static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, -					   struct dmx_section_filter *filter) -{ -	struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f; -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - -	mutex_lock(&dvbdmx->mutex); - -	if (dvbdmxfilter->feed != dvbdmxfeed) { -		mutex_unlock(&dvbdmx->mutex); -		return -EINVAL; -	} - -	if (feed->is_filtering) -		feed->stop_filtering(feed); - -	spin_lock_irq(&dvbdmx->lock); -	f = dvbdmxfeed->filter; - -	if (f == dvbdmxfilter) { -		dvbdmxfeed->filter = dvbdmxfilter->next; -	} else { -		while (f->next != dvbdmxfilter) -			f = f->next; -		f->next = f->next->next; -	} - -	dvbdmxfilter->state = DMX_STATE_FREE; -	spin_unlock_irq(&dvbdmx->lock); -	mutex_unlock(&dvbdmx->mutex); -	return 0; -} - -static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, -					struct dmx_section_feed **feed, -					dmx_section_cb callback) -{ -	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; -	struct dvb_demux_feed *dvbdmxfeed; - -	if (mutex_lock_interruptible(&dvbdmx->mutex)) -		return -ERESTARTSYS; - -	if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { -		mutex_unlock(&dvbdmx->mutex); -		return -EBUSY; -	} - -	dvbdmxfeed->type = DMX_TYPE_SEC; -	dvbdmxfeed->cb.sec = callback; -	dvbdmxfeed->demux = dvbdmx; -	dvbdmxfeed->pid = 0xffff; -	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; -	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; -	dvbdmxfeed->feed.sec.tsfeedp = 0; -	dvbdmxfeed->filter = NULL; -	dvbdmxfeed->buffer = NULL; - -	(*feed) = &dvbdmxfeed->feed.sec; -	(*feed)->is_filtering = 0; -	(*feed)->parent = demux; -	(*feed)->priv = NULL; - -	(*feed)->set = dmx_section_feed_set; -	(*feed)->allocate_filter = dmx_section_feed_allocate_filter; -	(*feed)->start_filtering = dmx_section_feed_start_filtering; -	(*feed)->stop_filtering = dmx_section_feed_stop_filtering; -	(*feed)->release_filter = dmx_section_feed_release_filter; - -	mutex_unlock(&dvbdmx->mutex); -	return 0; -} - -static int dvbdmx_release_section_feed(struct dmx_demux *demux, -				       struct dmx_section_feed *feed) -{ -	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; -	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; - -	mutex_lock(&dvbdmx->mutex); - -	if (dvbdmxfeed->state == DMX_STATE_FREE) { -		mutex_unlock(&dvbdmx->mutex); -		return -EINVAL; -	} -#ifndef NOBUFS -	vfree(dvbdmxfeed->buffer); -	dvbdmxfeed->buffer = NULL; -#endif -	dvbdmxfeed->state = DMX_STATE_FREE; - -	dvb_demux_feed_del(dvbdmxfeed); - -	dvbdmxfeed->pid = 0xffff; - -	mutex_unlock(&dvbdmx->mutex); -	return 0; -} - -/****************************************************************************** - * dvb_demux kernel data API calls - ******************************************************************************/ - -static int dvbdmx_open(struct dmx_demux *demux) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) -		return -EUSERS; - -	dvbdemux->users++; -	return 0; -} - -static int dvbdmx_close(struct dmx_demux *demux) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	if (dvbdemux->users == 0) -		return -ENODEV; - -	dvbdemux->users--; -	//FIXME: release any unneeded resources if users==0 -	return 0; -} - -static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; -	void *p; - -	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) -		return -EINVAL; - -	p = memdup_user(buf, count); -	if (IS_ERR(p)) -		return PTR_ERR(p); -	if (mutex_lock_interruptible(&dvbdemux->mutex)) { -		kfree(p); -		return -ERESTARTSYS; -	} -	dvb_dmx_swfilter(dvbdemux, p, count); -	kfree(p); -	mutex_unlock(&dvbdemux->mutex); - -	if (signal_pending(current)) -		return -EINTR; -	return count; -} - -static int dvbdmx_add_frontend(struct dmx_demux *demux, -			       struct dmx_frontend *frontend) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; -	struct list_head *head = &dvbdemux->frontend_list; - -	list_add(&(frontend->connectivity_list), head); - -	return 0; -} - -static int dvbdmx_remove_frontend(struct dmx_demux *demux, -				  struct dmx_frontend *frontend) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; -	struct list_head *pos, *n, *head = &dvbdemux->frontend_list; - -	list_for_each_safe(pos, n, head) { -		if (DMX_FE_ENTRY(pos) == frontend) { -			list_del(pos); -			return 0; -		} -	} - -	return -ENODEV; -} - -static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	if (list_empty(&dvbdemux->frontend_list)) -		return NULL; - -	return &dvbdemux->frontend_list; -} - -static int dvbdmx_connect_frontend(struct dmx_demux *demux, -				   struct dmx_frontend *frontend) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	if (demux->frontend) -		return -EINVAL; - -	mutex_lock(&dvbdemux->mutex); - -	demux->frontend = frontend; -	mutex_unlock(&dvbdemux->mutex); -	return 0; -} - -static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	mutex_lock(&dvbdemux->mutex); - -	demux->frontend = NULL; -	mutex_unlock(&dvbdemux->mutex); -	return 0; -} - -static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids) -{ -	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - -	memcpy(pids, dvbdemux->pids, 5 * sizeof(u16)); -	return 0; -} - -int dvb_dmx_init(struct dvb_demux *dvbdemux) -{ -	int i; -	struct dmx_demux *dmx = &dvbdemux->dmx; - -	dvbdemux->cnt_storage = NULL; -	dvbdemux->users = 0; -	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); - -	if (!dvbdemux->filter) -		return -ENOMEM; - -	dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); -	if (!dvbdemux->feed) { -		vfree(dvbdemux->filter); -		dvbdemux->filter = NULL; -		return -ENOMEM; -	} -	for (i = 0; i < dvbdemux->filternum; i++) { -		dvbdemux->filter[i].state = DMX_STATE_FREE; -		dvbdemux->filter[i].index = i; -	} -	for (i = 0; i < dvbdemux->feednum; i++) { -		dvbdemux->feed[i].state = DMX_STATE_FREE; -		dvbdemux->feed[i].index = i; -	} - -	dvbdemux->cnt_storage = vmalloc(MAX_PID + 1); -	if (!dvbdemux->cnt_storage) -		printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); - -	INIT_LIST_HEAD(&dvbdemux->frontend_list); - -	for (i = 0; i < DMX_TS_PES_OTHER; i++) { -		dvbdemux->pesfilter[i] = NULL; -		dvbdemux->pids[i] = 0xffff; -	} - -	INIT_LIST_HEAD(&dvbdemux->feed_list); - -	dvbdemux->playing = 0; -	dvbdemux->recording = 0; -	dvbdemux->tsbufp = 0; - -	if (!dvbdemux->check_crc32) -		dvbdemux->check_crc32 = dvb_dmx_crc32; - -	if (!dvbdemux->memcopy) -		dvbdemux->memcopy = dvb_dmx_memcopy; - -	dmx->frontend = NULL; -	dmx->priv = dvbdemux; -	dmx->open = dvbdmx_open; -	dmx->close = dvbdmx_close; -	dmx->write = dvbdmx_write; -	dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; -	dmx->release_ts_feed = dvbdmx_release_ts_feed; -	dmx->allocate_section_feed = dvbdmx_allocate_section_feed; -	dmx->release_section_feed = dvbdmx_release_section_feed; - -	dmx->add_frontend = dvbdmx_add_frontend; -	dmx->remove_frontend = dvbdmx_remove_frontend; -	dmx->get_frontends = dvbdmx_get_frontends; -	dmx->connect_frontend = dvbdmx_connect_frontend; -	dmx->disconnect_frontend = dvbdmx_disconnect_frontend; -	dmx->get_pes_pids = dvbdmx_get_pes_pids; - -	mutex_init(&dvbdemux->mutex); -	spin_lock_init(&dvbdemux->lock); - -	return 0; -} - -EXPORT_SYMBOL(dvb_dmx_init); - -void dvb_dmx_release(struct dvb_demux *dvbdemux) -{ -	vfree(dvbdemux->cnt_storage); -	vfree(dvbdemux->filter); -	vfree(dvbdemux->feed); -} - -EXPORT_SYMBOL(dvb_dmx_release); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h deleted file mode 100644 index a7d876fd02d..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ /dev/null @@ -1,149 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#ifndef _DVB_DEMUX_H_ -#define _DVB_DEMUX_H_ - -#include <linux/time.h> -#include <linux/timer.h> -#include <linux/spinlock.h> -#include <linux/mutex.h> - -#include "demux.h" - -#define DMX_TYPE_TS  0 -#define DMX_TYPE_SEC 1 -#define DMX_TYPE_PES 2 - -#define DMX_STATE_FREE      0 -#define DMX_STATE_ALLOCATED 1 -#define DMX_STATE_SET       2 -#define DMX_STATE_READY     3 -#define DMX_STATE_GO        4 - -#define DVB_DEMUX_MASK_MAX 18 - -#define MAX_PID 0x1fff - -#define SPEED_PKTS_INTERVAL 50000 - -struct dvb_demux_filter { -	struct dmx_section_filter filter; -	u8 maskandmode[DMX_MAX_FILTER_SIZE]; -	u8 maskandnotmode[DMX_MAX_FILTER_SIZE]; -	int doneq; - -	struct dvb_demux_filter *next; -	struct dvb_demux_feed *feed; -	int index; -	int state; -	int type; - -	u16 hw_handle; -	struct timer_list timer; -}; - -#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head) - -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; -	int type; -	int state; -	u16 pid; -	u8 *buffer; -	int buffer_size; - -	struct timespec timeout; -	struct dvb_demux_filter *filter; - -	int ts_type; -	enum dmx_ts_pes pes_type; - -	int cc; -	int pusi_seen;		/* prevents feeding of garbage from previous section */ - -	u16 peslen; - -	struct list_head list_head; -	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */ -}; - -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_TS_PES_OTHER]; -	u16 pids[DMX_TS_PES_OTHER]; -	int playing; -	int recording; - -#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 */ - -	struct timespec speed_last_time; /* for TS speed check */ -	uint32_t speed_pkts_cnt; /* for TS speed check */ -}; - -int dvb_dmx_init(struct dvb_demux *dvbdemux); -void dvb_dmx_release(struct dvb_demux *dvbdemux); -void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, -			      size_t count); -void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); -void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, -			  size_t count); - -#endif /* _DVB_DEMUX_H_ */ diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c deleted file mode 100644 index 772003fb182..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_filter.c +++ /dev/null @@ -1,603 +0,0 @@ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/string.h> -#include "dvb_filter.h" - -#if 0 -static unsigned int bitrates[3][16] = -{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, - {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, - {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; -#endif - -static u32 freq[4] = {480, 441, 320, 0}; - -static unsigned int ac3_bitrates[32] = -    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, -     0,0,0,0,0,0,0,0,0,0,0,0,0}; - -static u32 ac3_frames[3][32] = -    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, -      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, -     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, -      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0}, -     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344, -      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}}; - - - -#if 0 -static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, -		  void (*pes_write)(u8 *buf, int count, void *data), -		  void *priv) -{ -	dvb_filter_ipack_init(pa, IPACKS, pes_write); -	dvb_filter_ipack_init(pv, IPACKS, pes_write); -	pa->pid = pida; -	pv->pid = pidv; -	pa->data = priv; -	pv->data = priv; -} -#endif - -#if 0 -static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) -{ -	u8 off = 0; - -	if (!buf || !p ){ -		printk("NULL POINTER IDIOT\n"); -		return; -	} -	if (buf[1]&PAY_START) { -		if (p->plength == MMAX_PLENGTH-6 && p->found>6){ -			p->plength = p->found-6; -			p->found = 0; -			send_ipack(p); -			dvb_filter_ipack_reset(p); -		} -	} -	if (buf[3] & ADAPT_FIELD) {  // adaptation field? -		off = buf[4] + 1; -		if (off+4 > 187) return; -	} -	dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p); -} -#endif - -#if 0 -/* needs 5 byte input, returns picture coding type*/ -static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr) -{ -	u8 pct; - -	if (pr) printk( "Pic header: "); -	pic->temporal_reference[field] = (( headr[0] << 2 ) | -					  (headr[1] & 0x03) )& 0x03ff; -	if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]); - -	pct = ( headr[1] >> 2 ) & 0x07; -	pic->picture_coding_type[field] = pct; -	if (pr) { -		switch(pct){ -			case I_FRAME: -				printk( "  I-FRAME"); -				break; -			case B_FRAME: -				printk( "  B-FRAME"); -				break; -			case P_FRAME: -				printk( "  P-FRAME"); -				break; -		} -	} - - -	pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) | -				 ( (headr[3] & 0x1F) << 11) ) & 0xffff; - -	if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay); - -	pic->picture_header_parameter = ( headr[3] & 0xe0 ) | -		((headr[4] & 0x80) >> 3); - -	if ( pct == B_FRAME ){ -		pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f; -	} -	if (pr) printk( " pic head param: 0x%x", -			pic->picture_header_parameter); - -	return pct; -} -#endif - -#if 0 -/* needs 4 byte input */ -static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr) -{ -	if (pr) printk("GOP header: "); - -	pic->time_code  = (( headr[0] << 17 ) | ( headr[1] << 9) | -			   ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff; - -	if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F, -		       ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F), -		       ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F)); - -	if ( ( headr[3] & 0x40 ) != 0 ){ -		pic->closed_gop = 1; -	} else { -		pic->closed_gop = 0; -	} -	if (pr) printk("closed: %d", pic->closed_gop); - -	if ( ( headr[3] & 0x20 ) != 0 ){ -		pic->broken_link = 1; -	} else { -		pic->broken_link = 0; -	} -	if (pr) printk(" broken: %d\n", pic->broken_link); - -	return 0; -} -#endif - -#if 0 -/* needs 8 byte input */ -static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr) -{ -	int sw; -	int form = -1; - -	if (pr) printk("Reading sequence header\n"); - -	vi->horizontal_size	= ((headr[1] &0xF0) >> 4) | (headr[0] << 4); -	vi->vertical_size	= ((headr[1] &0x0F) << 8) | (headr[2]); - -	sw = (int)((headr[3]&0xF0) >> 4) ; - -	switch( sw ){ -	case 1: -		if (pr) -			printk("Videostream: ASPECT: 1:1"); -		vi->aspect_ratio = 100; -		break; -	case 2: -		if (pr) -			printk("Videostream: ASPECT: 4:3"); -		vi->aspect_ratio = 133; -		break; -	case 3: -		if (pr) -			printk("Videostream: ASPECT: 16:9"); -		vi->aspect_ratio = 177; -		break; -	case 4: -		if (pr) -			printk("Videostream: ASPECT: 2.21:1"); -		vi->aspect_ratio = 221; -		break; - -	case 5 ... 15: -		if (pr) -			printk("Videostream: ASPECT: reserved"); -		vi->aspect_ratio = 0; -		break; - -	default: -		vi->aspect_ratio = 0; -		return -1; -	} - -	if (pr) -		printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size); - -	sw = (int)(headr[3]&0x0F); - -	switch ( sw ) { -	case 1: -		if (pr) -			printk("  FRate: 23.976 fps"); -		vi->framerate = 23976; -		form = -1; -		break; -	case 2: -		if (pr) -			printk("  FRate: 24 fps"); -		vi->framerate = 24000; -		form = -1; -		break; -	case 3: -		if (pr) -			printk("  FRate: 25 fps"); -		vi->framerate = 25000; -		form = VIDEO_MODE_PAL; -		break; -	case 4: -		if (pr) -			printk("  FRate: 29.97 fps"); -		vi->framerate = 29970; -		form = VIDEO_MODE_NTSC; -		break; -	case 5: -		if (pr) -			printk("  FRate: 30 fps"); -		vi->framerate = 30000; -		form = VIDEO_MODE_NTSC; -		break; -	case 6: -		if (pr) -			printk("  FRate: 50 fps"); -		vi->framerate = 50000; -		form = VIDEO_MODE_PAL; -		break; -	case 7: -		if (pr) -			printk("  FRate: 60 fps"); -		vi->framerate = 60000; -		form = VIDEO_MODE_NTSC; -		break; -	} - -	vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03); - -	vi->vbv_buffer_size -		= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5); - -	if (pr){ -		printk("  BRate: %d Mbit/s",4*(vi->bit_rate)/10000); -		printk("  vbvbuffer %d",16*1024*(vi->vbv_buffer_size)); -		printk("\n"); -	} - -	vi->video_format = form; - -	return 0; -} -#endif - - -#if 0 -static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr) -{ -	u8 *headr; -	int found = 0; -	int c = 0; - -	while (found < 4 && c+4 < count){ -		u8 *b; - -		b = mbuf+c; -		if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 -		     && b[3] == 0xb3) found = 4; -		else { -			c++; -		} -	} - -	if (! found) return -1; -	c += 4; -	if (c+12 >= count) return -1; -	headr = mbuf+c; -	if (read_sequence_header(headr, vi, pr) < 0) return -1; -	vi->off = c-4; -	return 0; -} -#endif - - -#if 0 -static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) -{ -	u8 *headr; -	int found = 0; -	int c = 0; -	int fr = 0; - -	while (found < 2 && c < count){ -		u8 b[2]; -		memcpy( b, mbuf+c, 2); - -		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) -			found = 2; -		else { -			c++; -		} -	} - -	if (!found) return -1; - -	if (c+3 >= count) return -1; -	headr = mbuf+c; - -	ai->layer = (headr[1] & 0x06) >> 1; - -	if (pr) -		printk("Audiostream: Layer: %d", 4-ai->layer); - - -	ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; - -	if (pr){ -		if (ai->bit_rate == 0) -			printk("  Bit rate: free"); -		else if (ai->bit_rate == 0xf) -			printk("  BRate: reserved"); -		else -			printk("  BRate: %d kb/s", ai->bit_rate/1000); -	} - -	fr = (headr[2] & 0x0c ) >> 2; -	ai->frequency = freq[fr]*100; -	if (pr){ -		if (ai->frequency == 3) -			printk("  Freq: reserved\n"); -		else -			printk("  Freq: %d kHz\n",ai->frequency); - -	} -	ai->off = c; -	return 0; -} -#endif - - -int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) -{ -	u8 *headr; -	int found = 0; -	int c = 0; -	u8 frame = 0; -	int fr = 0; - -	while ( !found  && c < count){ -		u8 *b = mbuf+c; - -		if ( b[0] == 0x0b &&  b[1] == 0x77 ) -			found = 1; -		else { -			c++; -		} -	} - -	if (!found) return -1; -	if (pr) -		printk("Audiostream: AC3"); - -	ai->off = c; -	if (c+5 >= count) return -1; - -	ai->layer = 0;  // 0 for AC3 -	headr = mbuf+c+2; - -	frame = (headr[2]&0x3f); -	ai->bit_rate = ac3_bitrates[frame >> 1]*1000; - -	if (pr) -		printk("  BRate: %d kb/s", (int) ai->bit_rate/1000); - -	ai->frequency = (headr[2] & 0xc0 ) >> 6; -	fr = (headr[2] & 0xc0 ) >> 6; -	ai->frequency = freq[fr]*100; -	if (pr) printk ("  Freq: %d Hz\n", (int) ai->frequency); - - -	ai->framesize = ac3_frames[fr][frame >> 1]; -	if ((frame & 1) &&  (fr == 1)) ai->framesize++; -	ai->framesize = ai->framesize << 1; -	if (pr) printk ("  Framesize %d\n",(int) ai->framesize); - - -	return 0; -} -EXPORT_SYMBOL(dvb_filter_get_ac3info); - - -#if 0 -static u8 *skip_pes_header(u8 **bufp) -{ -	u8 *inbuf = *bufp; -	u8 *buf = inbuf; -	u8 *pts = NULL; -	int skip = 0; - -	static const int mpeg1_skip_table[16] = { -		1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff, -		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff -	}; - - -	if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ -		if (buf[7] & PTS_ONLY) -			pts = buf+9; -		else pts = NULL; -		buf = inbuf + 9 + inbuf[8]; -	} else {        /* mpeg1 */ -		for (buf = inbuf + 6; *buf == 0xff; buf++) -			if (buf == inbuf + 6 + 16) { -				break; -			} -		if ((*buf & 0xc0) == 0x40) -			buf += 2; -		skip = mpeg1_skip_table [*buf >> 4]; -		if (skip == 5 || skip == 10) pts = buf; -		else pts = NULL; - -		buf += mpeg1_skip_table [*buf >> 4]; -	} - -	*bufp = buf; -	return pts; -} -#endif - -#if 0 -static void initialize_quant_matrix( u32 *matrix ) -{ -	int i; - -	matrix[0]  = 0x08101013; -	matrix[1]  = 0x10131616; -	matrix[2]  = 0x16161616; -	matrix[3]  = 0x1a181a1b; -	matrix[4]  = 0x1b1b1a1a; -	matrix[5]  = 0x1a1a1b1b; -	matrix[6]  = 0x1b1d1d1d; -	matrix[7]  = 0x2222221d; -	matrix[8]  = 0x1d1d1b1b; -	matrix[9]  = 0x1d1d2020; -	matrix[10] = 0x22222526; -	matrix[11] = 0x25232322; -	matrix[12] = 0x23262628; -	matrix[13] = 0x28283030; -	matrix[14] = 0x2e2e3838; -	matrix[15] = 0x3a454553; - -	for ( i = 16 ; i < 32 ; i++ ) -		matrix[i] = 0x10101010; -} -#endif - -#if 0 -static void initialize_mpg_picture(struct mpg_picture *pic) -{ -	int i; - -	/* set MPEG1 */ -	pic->mpeg1_flag = 1; -	pic->profile_and_level = 0x4A ;        /* MP@LL */ -	pic->progressive_sequence = 1; -	pic->low_delay = 0; - -	pic->sequence_display_extension_flag = 0; -	for ( i = 0 ; i < 4 ; i++ ){ -		pic->frame_centre_horizontal_offset[i] = 0; -		pic->frame_centre_vertical_offset[i] = 0; -	} -	pic->last_frame_centre_horizontal_offset = 0; -	pic->last_frame_centre_vertical_offset = 0; - -	pic->picture_display_extension_flag[0] = 0; -	pic->picture_display_extension_flag[1] = 0; -	pic->sequence_header_flag = 0; -	pic->gop_flag = 0; -	pic->sequence_end_flag = 0; -} -#endif - -#if 0 -static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic ) -{ -	int16_t last_h_offset; -	int16_t last_v_offset; - -	int16_t *p_h_offset; -	int16_t *p_v_offset; - -	if ( pic->mpeg1_flag ){ -		pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE; -		pic->top_field_first = 0; -		pic->repeat_first_field = 0; -		pic->progressive_frame = 1; -		pic->picture_coding_parameter = 0x000010; -	} - -	/* Reset flag */ -	pic->picture_display_extension_flag[field_type] = 0; - -	last_h_offset = pic->last_frame_centre_horizontal_offset; -	last_v_offset = pic->last_frame_centre_vertical_offset; -	if ( field_type == FIRST_FIELD ){ -		p_h_offset = pic->frame_centre_horizontal_offset; -		p_v_offset = pic->frame_centre_vertical_offset; -		*p_h_offset = last_h_offset; -		*(p_h_offset + 1) = last_h_offset; -		*(p_h_offset + 2) = last_h_offset; -		*p_v_offset = last_v_offset; -		*(p_v_offset + 1) = last_v_offset; -		*(p_v_offset + 2) = last_v_offset; -	} else { -		pic->frame_centre_horizontal_offset[3] = last_h_offset; -		pic->frame_centre_vertical_offset[3] = last_v_offset; -	} -} -#endif - -#if 0 -static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type) -{ -	pic->picture_header = 0; -	pic->sequence_header_data -		= ( INIT_HORIZONTAL_SIZE << 20 ) -			| ( INIT_VERTICAL_SIZE << 8 ) -			| ( INIT_ASPECT_RATIO << 4 ) -			| ( INIT_FRAME_RATE ); -	pic->mpeg1_flag = 0; -	pic->vinfo.horizontal_size -		= INIT_DISP_HORIZONTAL_SIZE; -	pic->vinfo.vertical_size -		= INIT_DISP_VERTICAL_SIZE; -	pic->picture_display_extension_flag[field_type] -		= 0; -	pic->pts_flag[field_type] = 0; - -	pic->sequence_gop_header = 0; -	pic->picture_header = 0; -	pic->sequence_header_flag = 0; -	pic->gop_flag = 0; -	pic->sequence_end_flag = 0; -	pic->sequence_display_extension_flag = 0; -	pic->last_frame_centre_horizontal_offset = 0; -	pic->last_frame_centre_vertical_offset = 0; -	pic->channel = chan; -} -#endif - -void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, -			    dvb_filter_pes2ts_cb_t *cb, void *priv) -{ -	unsigned char *buf=p2ts->buf; - -	buf[0]=0x47; -	buf[1]=(pid>>8); -	buf[2]=pid&0xff; -	p2ts->cc=0; -	p2ts->cb=cb; -	p2ts->priv=priv; -} -EXPORT_SYMBOL(dvb_filter_pes2ts_init); - -int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, -		      int len, int payload_start) -{ -	unsigned char *buf=p2ts->buf; -	int ret=0, rest; - -	//len=6+((pes[4]<<8)|pes[5]); - -	if (payload_start) -		buf[1]|=0x40; -	else -		buf[1]&=~0x40; -	while (len>=184) { -		buf[3]=0x10|((p2ts->cc++)&0x0f); -		memcpy(buf+4, pes, 184); -		if ((ret=p2ts->cb(p2ts->priv, buf))) -			return ret; -		len-=184; pes+=184; -		buf[1]&=~0x40; -	} -	if (!len) -		return 0; -	buf[3]=0x30|((p2ts->cc++)&0x0f); -	rest=183-len; -	if (rest) { -		buf[5]=0x00; -		if (rest-1) -			memset(buf+6, 0xff, rest-1); -	} -	buf[4]=rest; -	memcpy(buf+5+rest, pes, len); -	return p2ts->cb(p2ts->priv, buf); -} -EXPORT_SYMBOL(dvb_filter_pes2ts); diff --git a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h deleted file mode 100644 index 375e3be184b..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_filter.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * dvb_filter.h - * - * Copyright (C) 2003 Convergence 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. - * - * 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_FILTER_H_ -#define _DVB_FILTER_H_ - -#include <linux/slab.h> - -#include "demux.h" - -typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); - -struct dvb_filter_pes2ts { -	unsigned char buf[188]; -	unsigned char cc; -	dvb_filter_pes2ts_cb_t *cb; -	void *priv; -}; - -void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, -			    dvb_filter_pes2ts_cb_t *cb, void *priv); - -int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, -		      int len, int payload_start); - - -#define PROG_STREAM_MAP  0xBC -#define PRIVATE_STREAM1  0xBD -#define PADDING_STREAM   0xBE -#define PRIVATE_STREAM2  0xBF -#define AUDIO_STREAM_S   0xC0 -#define AUDIO_STREAM_E   0xDF -#define VIDEO_STREAM_S   0xE0 -#define VIDEO_STREAM_E   0xEF -#define ECM_STREAM       0xF0 -#define EMM_STREAM       0xF1 -#define DSM_CC_STREAM    0xF2 -#define ISO13522_STREAM  0xF3 -#define PROG_STREAM_DIR  0xFF - -#define DVB_PICTURE_START    0x00 -#define DVB_USER_START       0xb2 -#define DVB_SEQUENCE_HEADER  0xb3 -#define DVB_SEQUENCE_ERROR   0xb4 -#define DVB_EXTENSION_START  0xb5 -#define DVB_SEQUENCE_END     0xb7 -#define DVB_GOP_START        0xb8 -#define DVB_EXCEPT_SLICE     0xb0 - -#define SEQUENCE_EXTENSION           0x01 -#define SEQUENCE_DISPLAY_EXTENSION   0x02 -#define PICTURE_CODING_EXTENSION     0x08 -#define QUANT_MATRIX_EXTENSION       0x03 -#define PICTURE_DISPLAY_EXTENSION    0x07 - -#define I_FRAME 0x01 -#define B_FRAME 0x02 -#define P_FRAME 0x03 - -/* Initialize sequence_data */ -#define INIT_HORIZONTAL_SIZE        720 -#define INIT_VERTICAL_SIZE          576 -#define INIT_ASPECT_RATIO          0x02 -#define INIT_FRAME_RATE            0x03 -#define INIT_DISP_HORIZONTAL_SIZE   540 -#define INIT_DISP_VERTICAL_SIZE     576 - - -//flags2 -#define PTS_DTS_FLAGS    0xC0 -#define ESCR_FLAG        0x20 -#define ES_RATE_FLAG     0x10 -#define DSM_TRICK_FLAG   0x08 -#define ADD_CPY_FLAG     0x04 -#define PES_CRC_FLAG     0x02 -#define PES_EXT_FLAG     0x01 - -//pts_dts flags -#define PTS_ONLY         0x80 -#define PTS_DTS          0xC0 - -#define TS_SIZE        188 -#define TRANS_ERROR    0x80 -#define PAY_START      0x40 -#define TRANS_PRIO     0x20 -#define PID_MASK_HI    0x1F -//flags -#define TRANS_SCRMBL1  0x80 -#define TRANS_SCRMBL2  0x40 -#define ADAPT_FIELD    0x20 -#define PAYLOAD        0x10 -#define COUNT_MASK     0x0F - -// adaptation flags -#define DISCON_IND     0x80 -#define RAND_ACC_IND   0x40 -#define ES_PRI_IND     0x20 -#define PCR_FLAG       0x10 -#define OPCR_FLAG      0x08 -#define SPLICE_FLAG    0x04 -#define TRANS_PRIV     0x02 -#define ADAP_EXT_FLAG  0x01 - -// adaptation extension flags -#define LTW_FLAG       0x80 -#define PIECE_RATE     0x40 -#define SEAM_SPLICE    0x20 - - -#define MAX_PLENGTH 0xFFFF -#define MMAX_PLENGTH (256*MAX_PLENGTH) - -#ifndef IPACKS -#define IPACKS 2048 -#endif - -struct ipack { -	int size; -	int found; -	u8 *buf; -	u8 cid; -	u32 plength; -	u8 plen[2]; -	u8 flag1; -	u8 flag2; -	u8 hlength; -	u8 pts[5]; -	u16 *pid; -	int mpeg; -	u8 check; -	int which; -	int done; -	void *data; -	void (*func)(u8 *buf,  int size, void *priv); -	int count; -	int repack_subids; -}; - -struct dvb_video_info { -	u32 horizontal_size; -	u32 vertical_size; -	u32 aspect_ratio; -	u32 framerate; -	u32 video_format; -	u32 bit_rate; -	u32 comp_bit_rate; -	u32 vbv_buffer_size; -	s16 vbv_delay; -	u32 CSPF; -	u32 off; -}; - -#define OFF_SIZE 4 -#define FIRST_FIELD 0 -#define SECOND_FIELD 1 -#define VIDEO_FRAME_PICTURE 0x03 - -struct mpg_picture { -	int       channel; -	struct dvb_video_info vinfo; -	u32      *sequence_gop_header; -	u32      *picture_header; -	s32       time_code; -	int       low_delay; -	int       closed_gop; -	int       broken_link; -	int       sequence_header_flag; -	int       gop_flag; -	int       sequence_end_flag; - -	u8        profile_and_level; -	s32       picture_coding_parameter; -	u32       matrix[32]; -	s8        matrix_change_flag; - -	u8        picture_header_parameter; -  /* bit 0 - 2: bwd f code -     bit 3    : fpb vector -     bit 4 - 6: fwd f code -     bit 7    : fpf vector */ - -	int       mpeg1_flag; -	int       progressive_sequence; -	int       sequence_display_extension_flag; -	u32       sequence_header_data; -	s16       last_frame_centre_horizontal_offset; -	s16       last_frame_centre_vertical_offset; - -	u32       pts[2]; /* [0] 1st field, [1] 2nd field */ -	int       top_field_first; -	int       repeat_first_field; -	int       progressive_frame; -	int       bank; -	int       forward_bank; -	int       backward_bank; -	int       compress; -	s16       frame_centre_horizontal_offset[OFF_SIZE]; -		  /* [0-2] 1st field, [3] 2nd field */ -	s16       frame_centre_vertical_offset[OFF_SIZE]; -		  /* [0-2] 1st field, [3] 2nd field */ -	s16       temporal_reference[2]; -		  /* [0] 1st field, [1] 2nd field */ - -	s8        picture_coding_type[2]; -		  /* [0] 1st field, [1] 2nd field */ -	s8        picture_structure[2]; -		  /* [0] 1st field, [1] 2nd field */ -	s8        picture_display_extension_flag[2]; -		  /* [0] 1st field, [1] 2nd field */ -		  /* picture_display_extenion() 0:no 1:exit*/ -	s8        pts_flag[2]; -		  /* [0] 1st field, [1] 2nd field */ -}; - -struct dvb_audio_info { -	int layer; -	u32 bit_rate; -	u32 frequency; -	u32 mode; -	u32 mode_extension ; -	u32 emphasis; -	u32 framesize; -	u32 off; -}; - -int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr); - - -#endif diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c deleted file mode 100644 index 1589d5a5cb4..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ /dev/null @@ -1,2144 +0,0 @@ -/* - * dvb_frontend.c: DVB frontend tuning interface/thread - * - * - * Copyright (C) 1999-2001 Ralph  Metzler - *			   Marcus Metzler - *			   Holger Waechtler - *				      for convergence integrated media GmbH - * - * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup) - * - * 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; either version 2 - * 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 General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/poll.h> -#include <linux/semaphore.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/freezer.h> -#include <linux/jiffies.h> -#include <linux/smp_lock.h> -#include <linux/kthread.h> -#include <asm/processor.h> - -#include "dvb_frontend.h" -#include "dvbdev.h" -#include <linux/dvb/version.h> - -static int dvb_frontend_debug; -static int dvb_shutdown_timeout; -static int dvb_force_auto_inversion; -static int dvb_override_tune_delay; -static int dvb_powerdown_on_sleep = 1; -static int dvb_mfe_wait_time = 5; - -module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); -MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); -module_param(dvb_shutdown_timeout, int, 0644); -MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware"); -module_param(dvb_force_auto_inversion, int, 0644); -MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); -module_param(dvb_override_tune_delay, int, 0644); -MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); -module_param(dvb_powerdown_on_sleep, int, 0644); -MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); -module_param(dvb_mfe_wait_time, int, 0644); -MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); - -#define dprintk if (dvb_frontend_debug) printk - -#define FESTATE_IDLE 1 -#define FESTATE_RETUNE 2 -#define FESTATE_TUNING_FAST 4 -#define FESTATE_TUNING_SLOW 8 -#define FESTATE_TUNED 16 -#define FESTATE_ZIGZAG_FAST 32 -#define FESTATE_ZIGZAG_SLOW 64 -#define FESTATE_DISEQC 128 -#define FESTATE_ERROR 256 -#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) -#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) -#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) -#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW) - -#define FE_ALGO_HW		1 -/* - * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling. - * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune. - * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress. - * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower. - * FESTATE_TUNED. The frontend has successfully locked on. - * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it. - * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower. - * FESTATE_DISEQC. A DISEQC command has just been issued. - * FESTATE_WAITFORLOCK. When we're waiting for a lock. - * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan. - * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan. - * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. - */ - -#define DVB_FE_NO_EXIT	0 -#define DVB_FE_NORMAL_EXIT	1 -#define DVB_FE_DEVICE_REMOVED	2 - -static DEFINE_MUTEX(frontend_mutex); - -struct dvb_frontend_private { - -	/* thread/frontend values */ -	struct dvb_device *dvbdev; -	struct dvb_frontend_parameters parameters; -	struct dvb_fe_events events; -	struct semaphore sem; -	struct list_head list_head; -	wait_queue_head_t wait_queue; -	struct task_struct *thread; -	unsigned long release_jiffies; -	unsigned int exit; -	unsigned int wakeup; -	fe_status_t status; -	unsigned long tune_mode_flags; -	unsigned int delay; -	unsigned int reinitialise; -	int tone; -	int voltage; - -	/* swzigzag values */ -	unsigned int state; -	unsigned int bending; -	int lnb_drift; -	unsigned int inversion; -	unsigned int auto_step; -	unsigned int auto_sub_step; -	unsigned int started_auto_step; -	unsigned int min_delay; -	unsigned int max_drift; -	unsigned int step_size; -	int quality; -	unsigned int check_wrapped; -	enum dvbfe_search algo_status; -}; - -static void dvb_frontend_wakeup(struct dvb_frontend *fe); - -static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct dvb_fe_events *events = &fepriv->events; -	struct dvb_frontend_event *e; -	int wp; - -	dprintk ("%s\n", __func__); - -	if (mutex_lock_interruptible (&events->mtx)) -		return; - -	wp = (events->eventw + 1) % MAX_EVENT; - -	if (wp == events->eventr) { -		events->overflow = 1; -		events->eventr = (events->eventr + 1) % MAX_EVENT; -	} - -	e = &events->events[events->eventw]; - -	memcpy (&e->parameters, &fepriv->parameters, -		sizeof (struct dvb_frontend_parameters)); - -	if (status & FE_HAS_LOCK) -		if (fe->ops.get_frontend) -			fe->ops.get_frontend(fe, &e->parameters); - -	events->eventw = wp; - -	mutex_unlock(&events->mtx); - -	e->status = status; - -	wake_up_interruptible (&events->wait_queue); -} - -static int dvb_frontend_get_event(struct dvb_frontend *fe, -			    struct dvb_frontend_event *event, int flags) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct dvb_fe_events *events = &fepriv->events; - -	dprintk ("%s\n", __func__); - -	if (events->overflow) { -		events->overflow = 0; -		return -EOVERFLOW; -	} - -	if (events->eventw == events->eventr) { -		int ret; - -		if (flags & O_NONBLOCK) -			return -EWOULDBLOCK; - -		up(&fepriv->sem); - -		ret = wait_event_interruptible (events->wait_queue, -						events->eventw != events->eventr); - -		if (down_interruptible (&fepriv->sem)) -			return -ERESTARTSYS; - -		if (ret < 0) -			return ret; -	} - -	if (mutex_lock_interruptible (&events->mtx)) -		return -ERESTARTSYS; - -	memcpy (event, &events->events[events->eventr], -		sizeof(struct dvb_frontend_event)); - -	events->eventr = (events->eventr + 1) % MAX_EVENT; - -	mutex_unlock(&events->mtx); - -	return 0; -} - -static void dvb_frontend_init(struct dvb_frontend *fe) -{ -	dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", -		 fe->dvb->num, -		 fe->id, -		 fe->ops.info.name); - -	if (fe->ops.init) -		fe->ops.init(fe); -	if (fe->ops.tuner_ops.init) { -		if (fe->ops.i2c_gate_ctrl) -			fe->ops.i2c_gate_ctrl(fe, 1); -		fe->ops.tuner_ops.init(fe); -		if (fe->ops.i2c_gate_ctrl) -			fe->ops.i2c_gate_ctrl(fe, 0); -	} -} - -void dvb_frontend_reinitialise(struct dvb_frontend *fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	fepriv->reinitialise = 1; -	dvb_frontend_wakeup(fe); -} -EXPORT_SYMBOL(dvb_frontend_reinitialise); - -static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) -{ -	int q2; - -	dprintk ("%s\n", __func__); - -	if (locked) -		(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; -	else -		(fepriv->quality) = (fepriv->quality * 220 + 0) / 256; - -	q2 = fepriv->quality - 128; -	q2 *= q2; - -	fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); -} - -/** - * Performs automatic twiddling of frontend parameters. - * - * @param fe The frontend concerned. - * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT - * @returns Number of complete iterations that have been performed. - */ -static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) -{ -	int autoinversion; -	int ready = 0; -	int fe_set_err = 0; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	int original_inversion = fepriv->parameters.inversion; -	u32 original_frequency = fepriv->parameters.frequency; - -	/* are we using autoinversion? */ -	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && -			 (fepriv->parameters.inversion == INVERSION_AUTO)); - -	/* setup parameters correctly */ -	while(!ready) { -		/* calculate the lnb_drift */ -		fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size; - -		/* wrap the auto_step if we've exceeded the maximum drift */ -		if (fepriv->lnb_drift > fepriv->max_drift) { -			fepriv->auto_step = 0; -			fepriv->auto_sub_step = 0; -			fepriv->lnb_drift = 0; -		} - -		/* perform inversion and +/- zigzag */ -		switch(fepriv->auto_sub_step) { -		case 0: -			/* try with the current inversion and current drift setting */ -			ready = 1; -			break; - -		case 1: -			if (!autoinversion) break; - -			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; -			ready = 1; -			break; - -		case 2: -			if (fepriv->lnb_drift == 0) break; - -			fepriv->lnb_drift = -fepriv->lnb_drift; -			ready = 1; -			break; - -		case 3: -			if (fepriv->lnb_drift == 0) break; -			if (!autoinversion) break; - -			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; -			fepriv->lnb_drift = -fepriv->lnb_drift; -			ready = 1; -			break; - -		default: -			fepriv->auto_step++; -			fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ -			break; -		} - -		if (!ready) fepriv->auto_sub_step++; -	} - -	/* if this attempt would hit where we started, indicate a complete -	 * iteration has occurred */ -	if ((fepriv->auto_step == fepriv->started_auto_step) && -	    (fepriv->auto_sub_step == 0) && check_wrapped) { -		return 1; -	} - -	dprintk("%s: drift:%i inversion:%i auto_step:%i " -		"auto_sub_step:%i started_auto_step:%i\n", -		__func__, fepriv->lnb_drift, fepriv->inversion, -		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); - -	/* set the frontend itself */ -	fepriv->parameters.frequency += fepriv->lnb_drift; -	if (autoinversion) -		fepriv->parameters.inversion = fepriv->inversion; -	if (fe->ops.set_frontend) -		fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); -	if (fe_set_err < 0) { -		fepriv->state = FESTATE_ERROR; -		return fe_set_err; -	} - -	fepriv->parameters.frequency = original_frequency; -	fepriv->parameters.inversion = original_inversion; - -	fepriv->auto_sub_step++; -	return 0; -} - -static void dvb_frontend_swzigzag(struct dvb_frontend *fe) -{ -	fe_status_t s = 0; -	int retval = 0; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	/* if we've got no parameters, just keep idling */ -	if (fepriv->state & FESTATE_IDLE) { -		fepriv->delay = 3*HZ; -		fepriv->quality = 0; -		return; -	} - -	/* in SCAN mode, we just set the frontend when asked and leave it alone */ -	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { -		if (fepriv->state & FESTATE_RETUNE) { -			if (fe->ops.set_frontend) -				retval = fe->ops.set_frontend(fe, -							&fepriv->parameters); -			if (retval < 0) -				fepriv->state = FESTATE_ERROR; -			else -				fepriv->state = FESTATE_TUNED; -		} -		fepriv->delay = 3*HZ; -		fepriv->quality = 0; -		return; -	} - -	/* get the frontend status */ -	if (fepriv->state & FESTATE_RETUNE) { -		s = 0; -	} else { -		if (fe->ops.read_status) -			fe->ops.read_status(fe, &s); -		if (s != fepriv->status) { -			dvb_frontend_add_event(fe, s); -			fepriv->status = s; -		} -	} - -	/* if we're not tuned, and we have a lock, move to the TUNED state */ -	if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { -		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); -		fepriv->state = FESTATE_TUNED; - -		/* if we're tuned, then we have determined the correct inversion */ -		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && -		    (fepriv->parameters.inversion == INVERSION_AUTO)) { -			fepriv->parameters.inversion = fepriv->inversion; -		} -		return; -	} - -	/* if we are tuned already, check we're still locked */ -	if (fepriv->state & FESTATE_TUNED) { -		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); - -		/* we're tuned, and the lock is still good... */ -		if (s & FE_HAS_LOCK) { -			return; -		} else { /* if we _WERE_ tuned, but now don't have a lock */ -			fepriv->state = FESTATE_ZIGZAG_FAST; -			fepriv->started_auto_step = fepriv->auto_step; -			fepriv->check_wrapped = 0; -		} -	} - -	/* don't actually do anything if we're in the LOSTLOCK state, -	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ -	if ((fepriv->state & FESTATE_LOSTLOCK) && -	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { -		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); -		return; -	} - -	/* don't do anything if we're in the DISEQC state, since this -	 * might be someone with a motorized dish controlled by DISEQC. -	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/ -	if (fepriv->state & FESTATE_DISEQC) { -		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); -		return; -	} - -	/* if we're in the RETUNE state, set everything up for a brand -	 * new scan, keeping the current inversion setting, as the next -	 * tune is _very_ likely to require the same */ -	if (fepriv->state & FESTATE_RETUNE) { -		fepriv->lnb_drift = 0; -		fepriv->auto_step = 0; -		fepriv->auto_sub_step = 0; -		fepriv->started_auto_step = 0; -		fepriv->check_wrapped = 0; -	} - -	/* fast zigzag. */ -	if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { -		fepriv->delay = fepriv->min_delay; - -		/* perform a tune */ -		retval = dvb_frontend_swzigzag_autotune(fe, -							fepriv->check_wrapped); -		if (retval < 0) { -			return; -		} else if (retval) { -			/* OK, if we've run out of trials at the fast speed. -			 * Drop back to slow for the _next_ attempt */ -			fepriv->state = FESTATE_SEARCHING_SLOW; -			fepriv->started_auto_step = fepriv->auto_step; -			return; -		} -		fepriv->check_wrapped = 1; - -		/* if we've just retuned, enter the ZIGZAG_FAST state. -		 * This ensures we cannot return from an -		 * FE_SET_FRONTEND ioctl before the first frontend tune -		 * occurs */ -		if (fepriv->state & FESTATE_RETUNE) { -			fepriv->state = FESTATE_TUNING_FAST; -		} -	} - -	/* slow zigzag */ -	if (fepriv->state & FESTATE_SEARCHING_SLOW) { -		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); - -		/* Note: don't bother checking for wrapping; we stay in this -		 * state until we get a lock */ -		dvb_frontend_swzigzag_autotune(fe, 0); -	} -} - -static int dvb_frontend_is_exiting(struct dvb_frontend *fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	if (fepriv->exit != DVB_FE_NO_EXIT) -		return 1; - -	if (fepriv->dvbdev->writers == 1) -		if (time_after(jiffies, fepriv->release_jiffies + -				  dvb_shutdown_timeout * HZ)) -			return 1; - -	return 0; -} - -static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	if (fepriv->wakeup) { -		fepriv->wakeup = 0; -		return 1; -	} -	return dvb_frontend_is_exiting(fe); -} - -static void dvb_frontend_wakeup(struct dvb_frontend *fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	fepriv->wakeup = 1; -	wake_up_interruptible(&fepriv->wait_queue); -} - -static int dvb_frontend_thread(void *data) -{ -	struct dvb_frontend *fe = data; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	unsigned long timeout; -	fe_status_t s; -	enum dvbfe_algo algo; - -	struct dvb_frontend_parameters *params; - -	dprintk("%s\n", __func__); - -	fepriv->check_wrapped = 0; -	fepriv->quality = 0; -	fepriv->delay = 3*HZ; -	fepriv->status = 0; -	fepriv->wakeup = 0; -	fepriv->reinitialise = 0; - -	dvb_frontend_init(fe); - -	set_freezable(); -	while (1) { -		up(&fepriv->sem);	    /* is locked when we enter the thread... */ -restart: -		timeout = wait_event_interruptible_timeout(fepriv->wait_queue, -			dvb_frontend_should_wakeup(fe) || kthread_should_stop() -				|| freezing(current), -			fepriv->delay); - -		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { -			/* got signal or quitting */ -			fepriv->exit = DVB_FE_NORMAL_EXIT; -			break; -		} - -		if (try_to_freeze()) -			goto restart; - -		if (down_interruptible(&fepriv->sem)) -			break; - -		if (fepriv->reinitialise) { -			dvb_frontend_init(fe); -			if (fepriv->tone != -1) { -				fe->ops.set_tone(fe, fepriv->tone); -			} -			if (fepriv->voltage != -1) { -				fe->ops.set_voltage(fe, fepriv->voltage); -			} -			fepriv->reinitialise = 0; -		} - -		/* do an iteration of the tuning loop */ -		if (fe->ops.get_frontend_algo) { -			algo = fe->ops.get_frontend_algo(fe); -			switch (algo) { -			case DVBFE_ALGO_HW: -				dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); -				params = NULL; /* have we been asked to RETUNE ? */ - -				if (fepriv->state & FESTATE_RETUNE) { -					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); -					params = &fepriv->parameters; -					fepriv->state = FESTATE_TUNED; -				} - -				if (fe->ops.tune) -					fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); - -				if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { -					dprintk("%s: state changed, adding current state\n", __func__); -					dvb_frontend_add_event(fe, s); -					fepriv->status = s; -				} -				break; -			case DVBFE_ALGO_SW: -				dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); -				dvb_frontend_swzigzag(fe); -				break; -			case DVBFE_ALGO_CUSTOM: -				params = NULL; /* have we been asked to RETUNE ?	*/ -				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); -				if (fepriv->state & FESTATE_RETUNE) { -					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); -					params = &fepriv->parameters; -					fepriv->state = FESTATE_TUNED; -				} -				/* Case where we are going to search for a carrier -				 * User asked us to retune again for some reason, possibly -				 * requesting a search with a new set of parameters -				 */ -				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { -					if (fe->ops.search) { -						fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters); -						/* We did do a search as was requested, the flags are -						 * now unset as well and has the flags wrt to search. -						 */ -					} else { -						fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN; -					} -				} -				/* Track the carrier if the search was successful */ -				if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { -					if (fe->ops.track) -						fe->ops.track(fe, &fepriv->parameters); -				} else { -					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; -					fepriv->delay = HZ / 2; -				} -				fe->ops.read_status(fe, &s); -				if (s != fepriv->status) { -					dvb_frontend_add_event(fe, s); /* update event list */ -					fepriv->status = s; -					if (!(s & FE_HAS_LOCK)) { -						fepriv->delay = HZ / 10; -						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; -					} else { -						fepriv->delay = 60 * HZ; -					} -				} -				break; -			default: -				dprintk("%s: UNDEFINED ALGO !\n", __func__); -				break; -			} -		} else { -			dvb_frontend_swzigzag(fe); -		} -	} - -	if (dvb_powerdown_on_sleep) { -		if (fe->ops.set_voltage) -			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); -		if (fe->ops.tuner_ops.sleep) { -			if (fe->ops.i2c_gate_ctrl) -				fe->ops.i2c_gate_ctrl(fe, 1); -			fe->ops.tuner_ops.sleep(fe); -			if (fe->ops.i2c_gate_ctrl) -				fe->ops.i2c_gate_ctrl(fe, 0); -		} -		if (fe->ops.sleep) -			fe->ops.sleep(fe); -	} - -	fepriv->thread = NULL; -	if (kthread_should_stop()) -		fepriv->exit = DVB_FE_DEVICE_REMOVED; -	else -		fepriv->exit = DVB_FE_NO_EXIT; -	mb(); - -	dvb_frontend_wakeup(fe); -	return 0; -} - -static void dvb_frontend_stop(struct dvb_frontend *fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	dprintk ("%s\n", __func__); - -	fepriv->exit = DVB_FE_NORMAL_EXIT; -	mb(); - -	if (!fepriv->thread) -		return; - -	kthread_stop(fepriv->thread); - -	sema_init(&fepriv->sem, 1); -	fepriv->state = FESTATE_IDLE; - -	/* paranoia check in case a signal arrived */ -	if (fepriv->thread) -		printk("dvb_frontend_stop: warning: thread %p won't exit\n", -				fepriv->thread); -} - -s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) -{ -	return ((curtime.tv_usec < lasttime.tv_usec) ? -		1000000 - lasttime.tv_usec + curtime.tv_usec : -		curtime.tv_usec - lasttime.tv_usec); -} -EXPORT_SYMBOL(timeval_usec_diff); - -static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec) -{ -	curtime->tv_usec += add_usec; -	if (curtime->tv_usec >= 1000000) { -		curtime->tv_usec -= 1000000; -		curtime->tv_sec++; -	} -} - -/* - * Sleep until gettimeofday() > waketime + add_usec - * This needs to be as precise as possible, but as the delay is - * usually between 2ms and 32ms, it is done using a scheduled msleep - * followed by usleep (normally a busy-wait loop) for the remainder - */ -void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec) -{ -	struct timeval lasttime; -	s32 delta, newdelta; - -	timeval_usec_add(waketime, add_usec); - -	do_gettimeofday(&lasttime); -	delta = timeval_usec_diff(lasttime, *waketime); -	if (delta > 2500) { -		msleep((delta - 1500) / 1000); -		do_gettimeofday(&lasttime); -		newdelta = timeval_usec_diff(lasttime, *waketime); -		delta = (newdelta > delta) ? 0 : newdelta; -	} -	if (delta > 0) -		udelay(delta); -} -EXPORT_SYMBOL(dvb_frontend_sleep_until); - -static int dvb_frontend_start(struct dvb_frontend *fe) -{ -	int ret; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct task_struct *fe_thread; - -	dprintk ("%s\n", __func__); - -	if (fepriv->thread) { -		if (fepriv->exit == DVB_FE_NO_EXIT) -			return 0; -		else -			dvb_frontend_stop (fe); -	} - -	if (signal_pending(current)) -		return -EINTR; -	if (down_interruptible (&fepriv->sem)) -		return -EINTR; - -	fepriv->state = FESTATE_IDLE; -	fepriv->exit = DVB_FE_NO_EXIT; -	fepriv->thread = NULL; -	mb(); - -	fe_thread = kthread_run(dvb_frontend_thread, fe, -		"kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); -	if (IS_ERR(fe_thread)) { -		ret = PTR_ERR(fe_thread); -		printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); -		up(&fepriv->sem); -		return ret; -	} -	fepriv->thread = fe_thread; -	return 0; -} - -static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, -					u32 *freq_min, u32 *freq_max) -{ -	*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); - -	if (fe->ops.info.frequency_max == 0) -		*freq_max = fe->ops.tuner_ops.info.frequency_max; -	else if (fe->ops.tuner_ops.info.frequency_max == 0) -		*freq_max = fe->ops.info.frequency_max; -	else -		*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); - -	if (*freq_min == 0 || *freq_max == 0) -		printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", -		       fe->dvb->num,fe->id); -} - -static int dvb_frontend_check_parameters(struct dvb_frontend *fe, -				struct dvb_frontend_parameters *parms) -{ -	u32 freq_min; -	u32 freq_max; - -	/* range check: frequency */ -	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); -	if ((freq_min && parms->frequency < freq_min) || -	    (freq_max && parms->frequency > freq_max)) { -		printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", -		       fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); -		return -EINVAL; -	} - -	/* range check: symbol rate */ -	if (fe->ops.info.type == FE_QPSK) { -		if ((fe->ops.info.symbol_rate_min && -		     parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || -		    (fe->ops.info.symbol_rate_max && -		     parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { -			printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", -			       fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, -			       fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); -			return -EINVAL; -		} - -	} else if (fe->ops.info.type == FE_QAM) { -		if ((fe->ops.info.symbol_rate_min && -		     parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || -		    (fe->ops.info.symbol_rate_max && -		     parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { -			printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", -			       fe->dvb->num, fe->id, parms->u.qam.symbol_rate, -			       fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); -			return -EINVAL; -		} -	} - -	/* check for supported modulation */ -	if (fe->ops.info.type == FE_QAM && -	    (parms->u.qam.modulation > QAM_AUTO || -	     !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) { -		printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n", -		       fe->dvb->num, fe->id, parms->u.qam.modulation); -			return -EINVAL; -	} - -	return 0; -} - -static int dvb_frontend_clear_cache(struct dvb_frontend *fe) -{ -	int i; - -	memset(&(fe->dtv_property_cache), 0, -			sizeof(struct dtv_frontend_properties)); - -	fe->dtv_property_cache.state = DTV_CLEAR; -	fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; -	fe->dtv_property_cache.inversion = INVERSION_AUTO; -	fe->dtv_property_cache.fec_inner = FEC_AUTO; -	fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; -	fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO; -	fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; -	fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO; -	fe->dtv_property_cache.symbol_rate = QAM_AUTO; -	fe->dtv_property_cache.code_rate_HP = FEC_AUTO; -	fe->dtv_property_cache.code_rate_LP = FEC_AUTO; - -	fe->dtv_property_cache.isdbt_partial_reception = -1; -	fe->dtv_property_cache.isdbt_sb_mode = -1; -	fe->dtv_property_cache.isdbt_sb_subchannel = -1; -	fe->dtv_property_cache.isdbt_sb_segment_idx = -1; -	fe->dtv_property_cache.isdbt_sb_segment_count = -1; -	fe->dtv_property_cache.isdbt_layer_enabled = 0x7; -	for (i = 0; i < 3; i++) { -		fe->dtv_property_cache.layer[i].fec = FEC_AUTO; -		fe->dtv_property_cache.layer[i].modulation = QAM_AUTO; -		fe->dtv_property_cache.layer[i].interleaving = -1; -		fe->dtv_property_cache.layer[i].segment_count = -1; -	} - -	return 0; -} - -#define _DTV_CMD(n, s, b) \ -[n] = { \ -	.name = #n, \ -	.cmd  = n, \ -	.set  = s,\ -	.buffer = b \ -} - -static struct dtv_cmds_h dtv_cmds[] = { -	_DTV_CMD(DTV_TUNE, 1, 0), -	_DTV_CMD(DTV_CLEAR, 1, 0), - -	/* Set */ -	_DTV_CMD(DTV_FREQUENCY, 1, 0), -	_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), -	_DTV_CMD(DTV_MODULATION, 1, 0), -	_DTV_CMD(DTV_INVERSION, 1, 0), -	_DTV_CMD(DTV_DISEQC_MASTER, 1, 1), -	_DTV_CMD(DTV_SYMBOL_RATE, 1, 0), -	_DTV_CMD(DTV_INNER_FEC, 1, 0), -	_DTV_CMD(DTV_VOLTAGE, 1, 0), -	_DTV_CMD(DTV_TONE, 1, 0), -	_DTV_CMD(DTV_PILOT, 1, 0), -	_DTV_CMD(DTV_ROLLOFF, 1, 0), -	_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), -	_DTV_CMD(DTV_HIERARCHY, 1, 0), -	_DTV_CMD(DTV_CODE_RATE_HP, 1, 0), -	_DTV_CMD(DTV_CODE_RATE_LP, 1, 0), -	_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), -	_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), - -	_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), -	_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), -	_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), -	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), -	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), - -	_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0), -	_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0), -	_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0), -	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0), -	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0), -	_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0), - -	_DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), - -	/* Get */ -	_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), -	_DTV_CMD(DTV_API_VERSION, 0, 0), -	_DTV_CMD(DTV_CODE_RATE_HP, 0, 0), -	_DTV_CMD(DTV_CODE_RATE_LP, 0, 0), -	_DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), -	_DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), -	_DTV_CMD(DTV_HIERARCHY, 0, 0), -}; - -static void dtv_property_dump(struct dtv_property *tvp) -{ -	int i; - -	if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { -		printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n", -			__func__, tvp->cmd); -		return; -	} - -	dprintk("%s() tvp.cmd    = 0x%08x (%s)\n" -		,__func__ -		,tvp->cmd -		,dtv_cmds[ tvp->cmd ].name); - -	if(dtv_cmds[ tvp->cmd ].buffer) { - -		dprintk("%s() tvp.u.buffer.len = 0x%02x\n" -			,__func__ -			,tvp->u.buffer.len); - -		for(i = 0; i < tvp->u.buffer.len; i++) -			dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" -				,__func__ -				,i -				,tvp->u.buffer.data[i]); - -	} else -		dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); -} - -static int is_legacy_delivery_system(fe_delivery_system_t s) -{ -	if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || -	   (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || -	   (s == SYS_ATSC)) -		return 1; - -	return 0; -} - -/* Synchronise the legacy tuning parameters into the cache, so that demodulator - * drivers can use a single set_frontend tuning function, regardless of whether - * it's being used for the legacy or new API, reducing code and complexity. - */ -static void dtv_property_cache_sync(struct dvb_frontend *fe, -				    struct dvb_frontend_parameters *p) -{ -	struct dtv_frontend_properties *c = &fe->dtv_property_cache; - -	c->frequency = p->frequency; -	c->inversion = p->inversion; - -	switch (fe->ops.info.type) { -	case FE_QPSK: -		c->modulation = QPSK;   /* implied for DVB-S in legacy API */ -		c->rolloff = ROLLOFF_35;/* implied for DVB-S */ -		c->symbol_rate = p->u.qpsk.symbol_rate; -		c->fec_inner = p->u.qpsk.fec_inner; -		c->delivery_system = SYS_DVBS; -		break; -	case FE_QAM: -		c->symbol_rate = p->u.qam.symbol_rate; -		c->fec_inner = p->u.qam.fec_inner; -		c->modulation = p->u.qam.modulation; -		c->delivery_system = SYS_DVBC_ANNEX_AC; -		break; -	case FE_OFDM: -		if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) -			c->bandwidth_hz = 6000000; -		else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) -			c->bandwidth_hz = 7000000; -		else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) -			c->bandwidth_hz = 8000000; -		else -			/* Including BANDWIDTH_AUTO */ -			c->bandwidth_hz = 0; -		c->code_rate_HP = p->u.ofdm.code_rate_HP; -		c->code_rate_LP = p->u.ofdm.code_rate_LP; -		c->modulation = p->u.ofdm.constellation; -		c->transmission_mode = p->u.ofdm.transmission_mode; -		c->guard_interval = p->u.ofdm.guard_interval; -		c->hierarchy = p->u.ofdm.hierarchy_information; -		c->delivery_system = SYS_DVBT; -		break; -	case FE_ATSC: -		c->modulation = p->u.vsb.modulation; -		if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) -			c->delivery_system = SYS_ATSC; -		else -			c->delivery_system = SYS_DVBC_ANNEX_B; -		break; -	} -} - -/* Ensure the cached values are set correctly in the frontend - * legacy tuning structures, for the advanced tuning API. - */ -static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) -{ -	struct dtv_frontend_properties *c = &fe->dtv_property_cache; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct dvb_frontend_parameters *p = &fepriv->parameters; - -	p->frequency = c->frequency; -	p->inversion = c->inversion; - -	switch (fe->ops.info.type) { -	case FE_QPSK: -		dprintk("%s() Preparing QPSK req\n", __func__); -		p->u.qpsk.symbol_rate = c->symbol_rate; -		p->u.qpsk.fec_inner = c->fec_inner; -		c->delivery_system = SYS_DVBS; -		break; -	case FE_QAM: -		dprintk("%s() Preparing QAM req\n", __func__); -		p->u.qam.symbol_rate = c->symbol_rate; -		p->u.qam.fec_inner = c->fec_inner; -		p->u.qam.modulation = c->modulation; -		c->delivery_system = SYS_DVBC_ANNEX_AC; -		break; -	case FE_OFDM: -		dprintk("%s() Preparing OFDM req\n", __func__); -		if (c->bandwidth_hz == 6000000) -			p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; -		else if (c->bandwidth_hz == 7000000) -			p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; -		else if (c->bandwidth_hz == 8000000) -			p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; -		else -			p->u.ofdm.bandwidth = BANDWIDTH_AUTO; -		p->u.ofdm.code_rate_HP = c->code_rate_HP; -		p->u.ofdm.code_rate_LP = c->code_rate_LP; -		p->u.ofdm.constellation = c->modulation; -		p->u.ofdm.transmission_mode = c->transmission_mode; -		p->u.ofdm.guard_interval = c->guard_interval; -		p->u.ofdm.hierarchy_information = c->hierarchy; -		c->delivery_system = SYS_DVBT; -		break; -	case FE_ATSC: -		dprintk("%s() Preparing VSB req\n", __func__); -		p->u.vsb.modulation = c->modulation; -		if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) -			c->delivery_system = SYS_ATSC; -		else -			c->delivery_system = SYS_DVBC_ANNEX_B; -		break; -	} -} - -/* Ensure the cached values are set correctly in the frontend - * legacy tuning structures, for the legacy tuning API. - */ -static void dtv_property_adv_params_sync(struct dvb_frontend *fe) -{ -	struct dtv_frontend_properties *c = &fe->dtv_property_cache; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct dvb_frontend_parameters *p = &fepriv->parameters; - -	p->frequency = c->frequency; -	p->inversion = c->inversion; - -	switch(c->modulation) { -	case PSK_8: -	case APSK_16: -	case APSK_32: -	case QPSK: -		p->u.qpsk.symbol_rate = c->symbol_rate; -		p->u.qpsk.fec_inner = c->fec_inner; -		break; -	default: -		break; -	} - -	if(c->delivery_system == SYS_ISDBT) { -		/* Fake out a generic DVB-T request so we pass validation in the ioctl */ -		p->frequency = c->frequency; -		p->inversion = c->inversion; -		p->u.ofdm.constellation = QAM_AUTO; -		p->u.ofdm.code_rate_HP = FEC_AUTO; -		p->u.ofdm.code_rate_LP = FEC_AUTO; -		p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; -		p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; -		p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; -		if (c->bandwidth_hz == 8000000) -			p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; -		else if (c->bandwidth_hz == 7000000) -			p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; -		else if (c->bandwidth_hz == 6000000) -			p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; -		else -			p->u.ofdm.bandwidth = BANDWIDTH_AUTO; -	} -} - -static void dtv_property_cache_submit(struct dvb_frontend *fe) -{ -	struct dtv_frontend_properties *c = &fe->dtv_property_cache; - -	/* For legacy delivery systems we don't need the delivery_system to -	 * be specified, but we populate the older structures from the cache -	 * so we can call set_frontend on older drivers. -	 */ -	if(is_legacy_delivery_system(c->delivery_system)) { - -		dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation); -		dtv_property_legacy_params_sync(fe); - -	} else { -		dprintk("%s() adv, modulation = %d\n", __func__, c->modulation); - -		/* For advanced delivery systems / modulation types ... -		 * we seed the lecacy dvb_frontend_parameters structure -		 * so that the sanity checking code later in the IOCTL processing -		 * can validate our basic frequency ranges, symbolrates, modulation -		 * etc. -		 */ -		dtv_property_adv_params_sync(fe); -	} -} - -static int dvb_frontend_ioctl_legacy(struct file *file, -			unsigned int cmd, void *parg); -static int dvb_frontend_ioctl_properties(struct file *file, -			unsigned int cmd, void *parg); - -static int dtv_property_process_get(struct dvb_frontend *fe, -				    struct dtv_property *tvp, -				    struct file *file) -{ -	int r = 0; - -	/* Allow the frontend to validate incoming properties */ -	if (fe->ops.get_property) -		r = fe->ops.get_property(fe, tvp); - -	if (r < 0) -		return r; - -	switch(tvp->cmd) { -	case DTV_FREQUENCY: -		tvp->u.data = fe->dtv_property_cache.frequency; -		break; -	case DTV_MODULATION: -		tvp->u.data = fe->dtv_property_cache.modulation; -		break; -	case DTV_BANDWIDTH_HZ: -		tvp->u.data = fe->dtv_property_cache.bandwidth_hz; -		break; -	case DTV_INVERSION: -		tvp->u.data = fe->dtv_property_cache.inversion; -		break; -	case DTV_SYMBOL_RATE: -		tvp->u.data = fe->dtv_property_cache.symbol_rate; -		break; -	case DTV_INNER_FEC: -		tvp->u.data = fe->dtv_property_cache.fec_inner; -		break; -	case DTV_PILOT: -		tvp->u.data = fe->dtv_property_cache.pilot; -		break; -	case DTV_ROLLOFF: -		tvp->u.data = fe->dtv_property_cache.rolloff; -		break; -	case DTV_DELIVERY_SYSTEM: -		tvp->u.data = fe->dtv_property_cache.delivery_system; -		break; -	case DTV_VOLTAGE: -		tvp->u.data = fe->dtv_property_cache.voltage; -		break; -	case DTV_TONE: -		tvp->u.data = fe->dtv_property_cache.sectone; -		break; -	case DTV_API_VERSION: -		tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; -		break; -	case DTV_CODE_RATE_HP: -		tvp->u.data = fe->dtv_property_cache.code_rate_HP; -		break; -	case DTV_CODE_RATE_LP: -		tvp->u.data = fe->dtv_property_cache.code_rate_LP; -		break; -	case DTV_GUARD_INTERVAL: -		tvp->u.data = fe->dtv_property_cache.guard_interval; -		break; -	case DTV_TRANSMISSION_MODE: -		tvp->u.data = fe->dtv_property_cache.transmission_mode; -		break; -	case DTV_HIERARCHY: -		tvp->u.data = fe->dtv_property_cache.hierarchy; -		break; - -	/* ISDB-T Support here */ -	case DTV_ISDBT_PARTIAL_RECEPTION: -		tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception; -		break; -	case DTV_ISDBT_SOUND_BROADCASTING: -		tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode; -		break; -	case DTV_ISDBT_SB_SUBCHANNEL_ID: -		tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel; -		break; -	case DTV_ISDBT_SB_SEGMENT_IDX: -		tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx; -		break; -	case DTV_ISDBT_SB_SEGMENT_COUNT: -		tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count; -		break; -	case DTV_ISDBT_LAYER_ENABLED: -		tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled; -		break; -	case DTV_ISDBT_LAYERA_FEC: -		tvp->u.data = fe->dtv_property_cache.layer[0].fec; -		break; -	case DTV_ISDBT_LAYERA_MODULATION: -		tvp->u.data = fe->dtv_property_cache.layer[0].modulation; -		break; -	case DTV_ISDBT_LAYERA_SEGMENT_COUNT: -		tvp->u.data = fe->dtv_property_cache.layer[0].segment_count; -		break; -	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: -		tvp->u.data = fe->dtv_property_cache.layer[0].interleaving; -		break; -	case DTV_ISDBT_LAYERB_FEC: -		tvp->u.data = fe->dtv_property_cache.layer[1].fec; -		break; -	case DTV_ISDBT_LAYERB_MODULATION: -		tvp->u.data = fe->dtv_property_cache.layer[1].modulation; -		break; -	case DTV_ISDBT_LAYERB_SEGMENT_COUNT: -		tvp->u.data = fe->dtv_property_cache.layer[1].segment_count; -		break; -	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: -		tvp->u.data = fe->dtv_property_cache.layer[1].interleaving; -		break; -	case DTV_ISDBT_LAYERC_FEC: -		tvp->u.data = fe->dtv_property_cache.layer[2].fec; -		break; -	case DTV_ISDBT_LAYERC_MODULATION: -		tvp->u.data = fe->dtv_property_cache.layer[2].modulation; -		break; -	case DTV_ISDBT_LAYERC_SEGMENT_COUNT: -		tvp->u.data = fe->dtv_property_cache.layer[2].segment_count; -		break; -	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: -		tvp->u.data = fe->dtv_property_cache.layer[2].interleaving; -		break; -	case DTV_ISDBS_TS_ID: -		tvp->u.data = fe->dtv_property_cache.isdbs_ts_id; -		break; -	default: -		r = -1; -	} - -	dtv_property_dump(tvp); - -	return r; -} - -static int dtv_property_process_set(struct dvb_frontend *fe, -				    struct dtv_property *tvp, -				    struct file *file) -{ -	int r = 0; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	dtv_property_dump(tvp); - -	/* Allow the frontend to validate incoming properties */ -	if (fe->ops.set_property) -		r = fe->ops.set_property(fe, tvp); - -	if (r < 0) -		return r; - -	switch(tvp->cmd) { -	case DTV_CLEAR: -		/* Reset a cache of data specific to the frontend here. This does -		 * not effect hardware. -		 */ -		dvb_frontend_clear_cache(fe); -		dprintk("%s() Flushing property cache\n", __func__); -		break; -	case DTV_TUNE: -		/* interpret the cache of data, build either a traditional frontend -		 * tunerequest so we can pass validation in the FE_SET_FRONTEND -		 * ioctl. -		 */ -		fe->dtv_property_cache.state = tvp->cmd; -		dprintk("%s() Finalised property cache\n", __func__); -		dtv_property_cache_submit(fe); - -		r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, -			&fepriv->parameters); -		break; -	case DTV_FREQUENCY: -		fe->dtv_property_cache.frequency = tvp->u.data; -		break; -	case DTV_MODULATION: -		fe->dtv_property_cache.modulation = tvp->u.data; -		break; -	case DTV_BANDWIDTH_HZ: -		fe->dtv_property_cache.bandwidth_hz = tvp->u.data; -		break; -	case DTV_INVERSION: -		fe->dtv_property_cache.inversion = tvp->u.data; -		break; -	case DTV_SYMBOL_RATE: -		fe->dtv_property_cache.symbol_rate = tvp->u.data; -		break; -	case DTV_INNER_FEC: -		fe->dtv_property_cache.fec_inner = tvp->u.data; -		break; -	case DTV_PILOT: -		fe->dtv_property_cache.pilot = tvp->u.data; -		break; -	case DTV_ROLLOFF: -		fe->dtv_property_cache.rolloff = tvp->u.data; -		break; -	case DTV_DELIVERY_SYSTEM: -		fe->dtv_property_cache.delivery_system = tvp->u.data; -		break; -	case DTV_VOLTAGE: -		fe->dtv_property_cache.voltage = tvp->u.data; -		r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, -			(void *)fe->dtv_property_cache.voltage); -		break; -	case DTV_TONE: -		fe->dtv_property_cache.sectone = tvp->u.data; -		r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, -			(void *)fe->dtv_property_cache.sectone); -		break; -	case DTV_CODE_RATE_HP: -		fe->dtv_property_cache.code_rate_HP = tvp->u.data; -		break; -	case DTV_CODE_RATE_LP: -		fe->dtv_property_cache.code_rate_LP = tvp->u.data; -		break; -	case DTV_GUARD_INTERVAL: -		fe->dtv_property_cache.guard_interval = tvp->u.data; -		break; -	case DTV_TRANSMISSION_MODE: -		fe->dtv_property_cache.transmission_mode = tvp->u.data; -		break; -	case DTV_HIERARCHY: -		fe->dtv_property_cache.hierarchy = tvp->u.data; -		break; - -	/* ISDB-T Support here */ -	case DTV_ISDBT_PARTIAL_RECEPTION: -		fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data; -		break; -	case DTV_ISDBT_SOUND_BROADCASTING: -		fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data; -		break; -	case DTV_ISDBT_SB_SUBCHANNEL_ID: -		fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data; -		break; -	case DTV_ISDBT_SB_SEGMENT_IDX: -		fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data; -		break; -	case DTV_ISDBT_SB_SEGMENT_COUNT: -		fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data; -		break; -	case DTV_ISDBT_LAYER_ENABLED: -		fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERA_FEC: -		fe->dtv_property_cache.layer[0].fec = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERA_MODULATION: -		fe->dtv_property_cache.layer[0].modulation = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERA_SEGMENT_COUNT: -		fe->dtv_property_cache.layer[0].segment_count = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: -		fe->dtv_property_cache.layer[0].interleaving = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERB_FEC: -		fe->dtv_property_cache.layer[1].fec = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERB_MODULATION: -		fe->dtv_property_cache.layer[1].modulation = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERB_SEGMENT_COUNT: -		fe->dtv_property_cache.layer[1].segment_count = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: -		fe->dtv_property_cache.layer[1].interleaving = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERC_FEC: -		fe->dtv_property_cache.layer[2].fec = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERC_MODULATION: -		fe->dtv_property_cache.layer[2].modulation = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERC_SEGMENT_COUNT: -		fe->dtv_property_cache.layer[2].segment_count = tvp->u.data; -		break; -	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: -		fe->dtv_property_cache.layer[2].interleaving = tvp->u.data; -		break; -	case DTV_ISDBS_TS_ID: -		fe->dtv_property_cache.isdbs_ts_id = tvp->u.data; -		break; -	default: -		r = -1; -	} - -	return r; -} - -static int dvb_frontend_ioctl(struct file *file, -			unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	int err = -EOPNOTSUPP; - -	dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); - -	if (fepriv->exit != DVB_FE_NO_EXIT) -		return -ENODEV; - -	if ((file->f_flags & O_ACCMODE) == O_RDONLY && -	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || -	     cmd == FE_DISEQC_RECV_SLAVE_REPLY)) -		return -EPERM; - -	if (down_interruptible (&fepriv->sem)) -		return -ERESTARTSYS; - -	if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) -		err = dvb_frontend_ioctl_properties(file, cmd, parg); -	else { -		fe->dtv_property_cache.state = DTV_UNDEFINED; -		err = dvb_frontend_ioctl_legacy(file, cmd, parg); -	} - -	up(&fepriv->sem); -	return err; -} - -static int dvb_frontend_ioctl_properties(struct file *file, -			unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	int err = 0; - -	struct dtv_properties *tvps = NULL; -	struct dtv_property *tvp = NULL; -	int i; - -	dprintk("%s\n", __func__); - -	if(cmd == FE_SET_PROPERTY) { -		tvps = (struct dtv_properties __user *)parg; - -		dprintk("%s() properties.num = %d\n", __func__, tvps->num); -		dprintk("%s() properties.props = %p\n", __func__, tvps->props); - -		/* Put an arbitrary limit on the number of messages that can -		 * be sent at once */ -		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) -			return -EINVAL; - -		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); -		if (!tvp) { -			err = -ENOMEM; -			goto out; -		} - -		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { -			err = -EFAULT; -			goto out; -		} - -		for (i = 0; i < tvps->num; i++) { -			(tvp + i)->result = dtv_property_process_set(fe, tvp + i, file); -			err |= (tvp + i)->result; -		} - -		if(fe->dtv_property_cache.state == DTV_TUNE) -			dprintk("%s() Property cache is full, tuning\n", __func__); - -	} else -	if(cmd == FE_GET_PROPERTY) { - -		tvps = (struct dtv_properties __user *)parg; - -		dprintk("%s() properties.num = %d\n", __func__, tvps->num); -		dprintk("%s() properties.props = %p\n", __func__, tvps->props); - -		/* Put an arbitrary limit on the number of messages that can -		 * be sent at once */ -		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) -			return -EINVAL; - -		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); -		if (!tvp) { -			err = -ENOMEM; -			goto out; -		} - -		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { -			err = -EFAULT; -			goto out; -		} - -		for (i = 0; i < tvps->num; i++) { -			(tvp + i)->result = dtv_property_process_get(fe, tvp + i, file); -			err |= (tvp + i)->result; -		} - -		if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { -			err = -EFAULT; -			goto out; -		} - -	} else -		err = -EOPNOTSUPP; - -out: -	kfree(tvp); -	return err; -} - -static int dvb_frontend_ioctl_legacy(struct file *file, -			unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	int cb_err, err = -EOPNOTSUPP; - -	if (fe->dvb->fe_ioctl_override) { -		cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, -						    DVB_FE_IOCTL_PRE); -		if (cb_err < 0) -			return cb_err; -		if (cb_err > 0) -			return 0; -		/* fe_ioctl_override returning 0 allows -		 * dvb-core to continue handling the ioctl */ -	} - -	switch (cmd) { -	case FE_GET_INFO: { -		struct dvb_frontend_info* info = parg; -		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); -		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); - -		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't -		 * do it, it is done for it. */ -		info->caps |= FE_CAN_INVERSION_AUTO; -		err = 0; -		break; -	} - -	case FE_READ_STATUS: { -		fe_status_t* status = parg; - -		/* if retune was requested but hasn't occured yet, prevent -		 * that user get signal state from previous tuning */ -		if (fepriv->state == FESTATE_RETUNE || -		    fepriv->state == FESTATE_ERROR) { -			err=0; -			*status = 0; -			break; -		} - -		if (fe->ops.read_status) -			err = fe->ops.read_status(fe, status); -		break; -	} -	case FE_READ_BER: -		if (fe->ops.read_ber) -			err = fe->ops.read_ber(fe, (__u32*) parg); -		break; - -	case FE_READ_SIGNAL_STRENGTH: -		if (fe->ops.read_signal_strength) -			err = fe->ops.read_signal_strength(fe, (__u16*) parg); -		break; - -	case FE_READ_SNR: -		if (fe->ops.read_snr) -			err = fe->ops.read_snr(fe, (__u16*) parg); -		break; - -	case FE_READ_UNCORRECTED_BLOCKS: -		if (fe->ops.read_ucblocks) -			err = fe->ops.read_ucblocks(fe, (__u32*) parg); -		break; - - -	case FE_DISEQC_RESET_OVERLOAD: -		if (fe->ops.diseqc_reset_overload) { -			err = fe->ops.diseqc_reset_overload(fe); -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_DISEQC_SEND_MASTER_CMD: -		if (fe->ops.diseqc_send_master_cmd) { -			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_DISEQC_SEND_BURST: -		if (fe->ops.diseqc_send_burst) { -			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_SET_TONE: -		if (fe->ops.set_tone) { -			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); -			fepriv->tone = (fe_sec_tone_mode_t) parg; -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_SET_VOLTAGE: -		if (fe->ops.set_voltage) { -			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); -			fepriv->voltage = (fe_sec_voltage_t) parg; -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_DISHNETWORK_SEND_LEGACY_CMD: -		if (fe->ops.dishnetwork_send_legacy_command) { -			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} else if (fe->ops.set_voltage) { -			/* -			 * NOTE: This is a fallback condition.  Some frontends -			 * (stv0299 for instance) take longer than 8msec to -			 * respond to a set_voltage command.  Those switches -			 * need custom routines to switch properly.  For all -			 * other frontends, the following should work ok. -			 * Dish network legacy switches (as used by Dish500) -			 * are controlled by sending 9-bit command words -			 * spaced 8msec apart. -			 * the actual command word is switch/port dependant -			 * so it is up to the userspace application to send -			 * the right command. -			 * The command must always start with a '0' after -			 * initialization, so parg is 8 bits and does not -			 * include the initialization or start bit -			 */ -			unsigned long swcmd = ((unsigned long) parg) << 1; -			struct timeval nexttime; -			struct timeval tv[10]; -			int i; -			u8 last = 1; -			if (dvb_frontend_debug) -				printk("%s switch command: 0x%04lx\n", __func__, swcmd); -			do_gettimeofday(&nexttime); -			if (dvb_frontend_debug) -				memcpy(&tv[0], &nexttime, sizeof(struct timeval)); -			/* before sending a command, initialize by sending -			 * a 32ms 18V to the switch -			 */ -			fe->ops.set_voltage(fe, SEC_VOLTAGE_18); -			dvb_frontend_sleep_until(&nexttime, 32000); - -			for (i = 0; i < 9; i++) { -				if (dvb_frontend_debug) -					do_gettimeofday(&tv[i + 1]); -				if ((swcmd & 0x01) != last) { -					/* set voltage to (last ? 13V : 18V) */ -					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); -					last = (last) ? 0 : 1; -				} -				swcmd = swcmd >> 1; -				if (i != 8) -					dvb_frontend_sleep_until(&nexttime, 8000); -			} -			if (dvb_frontend_debug) { -				printk("%s(%d): switch delay (should be 32k followed by all 8k\n", -					__func__, fe->dvb->num); -				for (i = 1; i < 10; i++) -					printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); -			} -			err = 0; -			fepriv->state = FESTATE_DISEQC; -			fepriv->status = 0; -		} -		break; - -	case FE_DISEQC_RECV_SLAVE_REPLY: -		if (fe->ops.diseqc_recv_slave_reply) -			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); -		break; - -	case FE_ENABLE_HIGH_LNB_VOLTAGE: -		if (fe->ops.enable_high_lnb_voltage) -			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); -		break; - -	case FE_SET_FRONTEND: { -		struct dvb_frontend_tune_settings fetunesettings; - -		if(fe->dtv_property_cache.state == DTV_TUNE) { -			if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { -				err = -EINVAL; -				break; -			} -		} else { -			if (dvb_frontend_check_parameters(fe, parg) < 0) { -				err = -EINVAL; -				break; -			} - -			memcpy (&fepriv->parameters, parg, -				sizeof (struct dvb_frontend_parameters)); -			dtv_property_cache_sync(fe, &fepriv->parameters); -		} - -		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); -		memcpy(&fetunesettings.parameters, parg, -		       sizeof (struct dvb_frontend_parameters)); - -		/* force auto frequency inversion if requested */ -		if (dvb_force_auto_inversion) { -			fepriv->parameters.inversion = INVERSION_AUTO; -			fetunesettings.parameters.inversion = INVERSION_AUTO; -		} -		if (fe->ops.info.type == FE_OFDM) { -			/* without hierarchical coding code_rate_LP is irrelevant, -			 * so we tolerate the otherwise invalid FEC_NONE setting */ -			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && -			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE) -				fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO; -		} - -		/* get frontend-specific tuning settings */ -		if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { -			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; -			fepriv->max_drift = fetunesettings.max_drift; -			fepriv->step_size = fetunesettings.step_size; -		} else { -			/* default values */ -			switch(fe->ops.info.type) { -			case FE_QPSK: -				fepriv->min_delay = HZ/20; -				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; -				fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000; -				break; - -			case FE_QAM: -				fepriv->min_delay = HZ/20; -				fepriv->step_size = 0; /* no zigzag */ -				fepriv->max_drift = 0; -				break; - -			case FE_OFDM: -				fepriv->min_delay = HZ/20; -				fepriv->step_size = fe->ops.info.frequency_stepsize * 2; -				fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; -				break; -			case FE_ATSC: -				fepriv->min_delay = HZ/20; -				fepriv->step_size = 0; -				fepriv->max_drift = 0; -				break; -			} -		} -		if (dvb_override_tune_delay > 0) -			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; - -		fepriv->state = FESTATE_RETUNE; - -		/* Request the search algorithm to search */ -		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - -		dvb_frontend_wakeup(fe); -		dvb_frontend_add_event(fe, 0); -		fepriv->status = 0; -		err = 0; -		break; -	} - -	case FE_GET_EVENT: -		err = dvb_frontend_get_event (fe, parg, file->f_flags); -		break; - -	case FE_GET_FRONTEND: -		if (fe->ops.get_frontend) { -			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters)); -			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg); -		} -		break; - -	case FE_SET_FRONTEND_TUNE_MODE: -		fepriv->tune_mode_flags = (unsigned long) parg; -		err = 0; -		break; -	}; - -	if (fe->dvb->fe_ioctl_override) { -		cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, -						    DVB_FE_IOCTL_POST); -		if (cb_err < 0) -			return cb_err; -	} - -	return err; -} - - -static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; - -	dprintk ("%s\n", __func__); - -	poll_wait (file, &fepriv->events.wait_queue, wait); - -	if (fepriv->events.eventw != fepriv->events.eventr) -		return (POLLIN | POLLRDNORM | POLLPRI); - -	return 0; -} - -static int dvb_frontend_open(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	struct dvb_adapter *adapter = fe->dvb; -	int ret; - -	dprintk ("%s\n", __func__); -	if (fepriv->exit == DVB_FE_DEVICE_REMOVED) -		return -ENODEV; - -	if (adapter->mfe_shared) { -		mutex_lock (&adapter->mfe_lock); - -		if (adapter->mfe_dvbdev == NULL) -			adapter->mfe_dvbdev = dvbdev; - -		else if (adapter->mfe_dvbdev != dvbdev) { -			struct dvb_device -				*mfedev = adapter->mfe_dvbdev; -			struct dvb_frontend -				*mfe = mfedev->priv; -			struct dvb_frontend_private -				*mfepriv = mfe->frontend_priv; -			int mferetry = (dvb_mfe_wait_time << 1); - -			mutex_unlock (&adapter->mfe_lock); -			while (mferetry-- && (mfedev->users != -1 || -					mfepriv->thread != NULL)) { -				if(msleep_interruptible(500)) { -					if(signal_pending(current)) -						return -EINTR; -				} -			} - -			mutex_lock (&adapter->mfe_lock); -			if(adapter->mfe_dvbdev != dvbdev) { -				mfedev = adapter->mfe_dvbdev; -				mfe = mfedev->priv; -				mfepriv = mfe->frontend_priv; -				if (mfedev->users != -1 || -						mfepriv->thread != NULL) { -					mutex_unlock (&adapter->mfe_lock); -					return -EBUSY; -				} -				adapter->mfe_dvbdev = dvbdev; -			} -		} -	} - -	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { -		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) -			goto err0; -	} - -	if ((ret = dvb_generic_open (inode, file)) < 0) -		goto err1; - -	if ((file->f_flags & O_ACCMODE) != O_RDONLY) { -		/* normal tune mode when opened R/W */ -		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; -		fepriv->tone = -1; -		fepriv->voltage = -1; - -		ret = dvb_frontend_start (fe); -		if (ret) -			goto err2; - -		/*  empty event queue */ -		fepriv->events.eventr = fepriv->events.eventw = 0; -	} - -	if (adapter->mfe_shared) -		mutex_unlock (&adapter->mfe_lock); -	return ret; - -err2: -	dvb_generic_release(inode, file); -err1: -	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) -		fe->ops.ts_bus_ctrl(fe, 0); -err0: -	if (adapter->mfe_shared) -		mutex_unlock (&adapter->mfe_lock); -	return ret; -} - -static int dvb_frontend_release(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_frontend *fe = dvbdev->priv; -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	int ret; - -	dprintk ("%s\n", __func__); - -	if ((file->f_flags & O_ACCMODE) != O_RDONLY) -		fepriv->release_jiffies = jiffies; - -	ret = dvb_generic_release (inode, file); - -	if (dvbdev->users == -1) { -		if (fepriv->exit != DVB_FE_NO_EXIT) { -			fops_put(file->f_op); -			file->f_op = NULL; -			wake_up(&dvbdev->wait_queue); -		} -		if (fe->ops.ts_bus_ctrl) -			fe->ops.ts_bus_ctrl(fe, 0); -	} - -	return ret; -} - -static const struct file_operations dvb_frontend_fops = { -	.owner		= THIS_MODULE, -	.unlocked_ioctl	= dvb_generic_ioctl, -	.poll		= dvb_frontend_poll, -	.open		= dvb_frontend_open, -	.release	= dvb_frontend_release, -	.llseek		= noop_llseek, -}; - -int dvb_register_frontend(struct dvb_adapter* dvb, -			  struct dvb_frontend* fe) -{ -	struct dvb_frontend_private *fepriv; -	static const struct dvb_device dvbdev_template = { -		.users = ~0, -		.writers = 1, -		.readers = (~0)-1, -		.fops = &dvb_frontend_fops, -		.kernel_ioctl = dvb_frontend_ioctl -	}; - -	dprintk ("%s\n", __func__); - -	if (mutex_lock_interruptible(&frontend_mutex)) -		return -ERESTARTSYS; - -	fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); -	if (fe->frontend_priv == NULL) { -		mutex_unlock(&frontend_mutex); -		return -ENOMEM; -	} -	fepriv = fe->frontend_priv; - -	sema_init(&fepriv->sem, 1); -	init_waitqueue_head (&fepriv->wait_queue); -	init_waitqueue_head (&fepriv->events.wait_queue); -	mutex_init(&fepriv->events.mtx); -	fe->dvb = dvb; -	fepriv->inversion = INVERSION_OFF; - -	printk ("DVB: registering adapter %i frontend %i (%s)...\n", -		fe->dvb->num, -		fe->id, -		fe->ops.info.name); - -	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, -			     fe, DVB_DEVICE_FRONTEND); - -	mutex_unlock(&frontend_mutex); -	return 0; -} -EXPORT_SYMBOL(dvb_register_frontend); - -int dvb_unregister_frontend(struct dvb_frontend* fe) -{ -	struct dvb_frontend_private *fepriv = fe->frontend_priv; -	dprintk ("%s\n", __func__); - -	mutex_lock(&frontend_mutex); -	dvb_frontend_stop (fe); -	mutex_unlock(&frontend_mutex); - -	if (fepriv->dvbdev->users < -1) -		wait_event(fepriv->dvbdev->wait_queue, -				fepriv->dvbdev->users==-1); - -	mutex_lock(&frontend_mutex); -	dvb_unregister_device (fepriv->dvbdev); - -	/* fe is invalid now */ -	kfree(fepriv); -	mutex_unlock(&frontend_mutex); -	return 0; -} -EXPORT_SYMBOL(dvb_unregister_frontend); - -#ifdef CONFIG_MEDIA_ATTACH -void dvb_frontend_detach(struct dvb_frontend* fe) -{ -	void *ptr; - -	if (fe->ops.release_sec) { -		fe->ops.release_sec(fe); -		symbol_put_addr(fe->ops.release_sec); -	} -	if (fe->ops.tuner_ops.release) { -		fe->ops.tuner_ops.release(fe); -		symbol_put_addr(fe->ops.tuner_ops.release); -	} -	if (fe->ops.analog_ops.release) { -		fe->ops.analog_ops.release(fe); -		symbol_put_addr(fe->ops.analog_ops.release); -	} -	ptr = (void*)fe->ops.release; -	if (ptr) { -		fe->ops.release(fe); -		symbol_put_addr(ptr); -	} -} -#else -void dvb_frontend_detach(struct dvb_frontend* fe) -{ -	if (fe->ops.release_sec) -		fe->ops.release_sec(fe); -	if (fe->ops.tuner_ops.release) -		fe->ops.tuner_ops.release(fe); -	if (fe->ops.analog_ops.release) -		fe->ops.analog_ops.release(fe); -	if (fe->ops.release) -		fe->ops.release(fe); -} -#endif -EXPORT_SYMBOL(dvb_frontend_detach); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h deleted file mode 100644 index f9f19be7718..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * dvb_frontend.h - * - * 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" - -struct dvb_frontend_tune_settings { -	int min_delay_ms; -	int step_size; -	int max_drift; -	struct dvb_frontend_parameters parameters; -}; - -struct dvb_frontend; - -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 { -	unsigned int frequency; -	unsigned int mode; -	unsigned int audmode; -	u64 std; -}; - -enum dvbfe_modcod { -	DVBFE_MODCOD_DUMMY_PLFRAME	= 0, -	DVBFE_MODCOD_QPSK_1_4, -	DVBFE_MODCOD_QPSK_1_3, -	DVBFE_MODCOD_QPSK_2_5, -	DVBFE_MODCOD_QPSK_1_2, -	DVBFE_MODCOD_QPSK_3_5, -	DVBFE_MODCOD_QPSK_2_3, -	DVBFE_MODCOD_QPSK_3_4, -	DVBFE_MODCOD_QPSK_4_5, -	DVBFE_MODCOD_QPSK_5_6, -	DVBFE_MODCOD_QPSK_8_9, -	DVBFE_MODCOD_QPSK_9_10, -	DVBFE_MODCOD_8PSK_3_5, -	DVBFE_MODCOD_8PSK_2_3, -	DVBFE_MODCOD_8PSK_3_4, -	DVBFE_MODCOD_8PSK_5_6, -	DVBFE_MODCOD_8PSK_8_9, -	DVBFE_MODCOD_8PSK_9_10, -	DVBFE_MODCOD_16APSK_2_3, -	DVBFE_MODCOD_16APSK_3_4, -	DVBFE_MODCOD_16APSK_4_5, -	DVBFE_MODCOD_16APSK_5_6, -	DVBFE_MODCOD_16APSK_8_9, -	DVBFE_MODCOD_16APSK_9_10, -	DVBFE_MODCOD_32APSK_3_4, -	DVBFE_MODCOD_32APSK_4_5, -	DVBFE_MODCOD_32APSK_5_6, -	DVBFE_MODCOD_32APSK_8_9, -	DVBFE_MODCOD_32APSK_9_10, -	DVBFE_MODCOD_RESERVED_1, -	DVBFE_MODCOD_BPSK_1_3, -	DVBFE_MODCOD_BPSK_1_4, -	DVBFE_MODCOD_RESERVED_2 -}; - -enum tuner_param { -	DVBFE_TUNER_FREQUENCY		= (1 <<  0), -	DVBFE_TUNER_TUNERSTEP		= (1 <<  1), -	DVBFE_TUNER_IFFREQ		= (1 <<  2), -	DVBFE_TUNER_BANDWIDTH		= (1 <<  3), -	DVBFE_TUNER_REFCLOCK		= (1 <<  4), -	DVBFE_TUNER_IQSENSE		= (1 <<  5), -	DVBFE_TUNER_DUMMY		= (1 << 31) -}; - -/* - * ALGO_HW: (Hardware Algorithm) - * ---------------------------------------------------------------- - * Devices that support this algorithm do everything in hardware - * and no software support is needed to handle them. - * Requesting these devices to LOCK is the only thing required, - * device is supposed to do everything in the hardware. - * - * ALGO_SW: (Software Algorithm) - * ---------------------------------------------------------------- - * These are dumb devices, that require software to do everything - * - * 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. - * - * 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) -}; - -struct tuner_state { -	u32 frequency; -	u32 tunerstep; -	u32 ifreq; -	u32 bandwidth; -	u32 iqsense; -	u32 refclock; -}; - -/* - * 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 { - -	struct dvb_tuner_info info; - -	int (*release)(struct dvb_frontend *fe); -	int (*init)(struct dvb_frontend *fe); -	int (*sleep)(struct dvb_frontend *fe); - -	/** This is for simple PLLs - set all parameters in one go. */ -	int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); -	int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); - -	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ -	int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); - -	/** This is to allow setting tuner-specific configs */ -	int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); - -	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); -	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); - -#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); - -	/** These are provided separately from set_params in order to facilitate silicon -	 * tuners which require sophisticated tuning loops, controlling each parameter separately. */ -	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); -	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); - -	/* -	 * These are provided separately from set_params in order to facilitate silicon -	 * tuners which require sophisticated tuning loops, controlling each parameter separately. -	 */ -	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); -	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); -}; - -struct analog_demod_info { -	char *name; -}; - -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); -	int  (*is_stereo)(struct dvb_frontend *fe); -	int  (*get_afc)(struct dvb_frontend *fe); -	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 dvb_frontend_ops { - -	struct dvb_frontend_info info; - -	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, -		    struct dvb_frontend_parameters* params, -		    unsigned int mode_flags, -		    unsigned int *delay, -		    fe_status_t *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, struct dvb_frontend_parameters* params); -	int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); - -	int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - -	int (*read_status)(struct dvb_frontend* fe, fe_status_t* 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, fe_sec_mini_cmd_t minicmd); -	int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); -	int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); -	int (*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); - -	/* 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_frontend_parameters *p); -	int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); - -	struct dvb_tuner_ops tuner_ops; -	struct analog_demod_ops analog_ops; - -	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -}; - -#define MAX_EVENT 8 - -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; -}; - -struct dtv_frontend_properties { - -	/* Cache State */ -	u32			state; - -	u32			frequency; -	fe_modulation_t		modulation; - -	fe_sec_voltage_t	voltage; -	fe_sec_tone_mode_t	sectone; -	fe_spectral_inversion_t	inversion; -	fe_code_rate_t		fec_inner; -	fe_transmit_mode_t	transmission_mode; -	u32			bandwidth_hz;	/* 0 = AUTO */ -	fe_guard_interval_t	guard_interval; -	fe_hierarchy_t		hierarchy; -	u32			symbol_rate; -	fe_code_rate_t		code_rate_HP; -	fe_code_rate_t		code_rate_LP; - -	fe_pilot_t		pilot; -	fe_rolloff_t		rolloff; - -	fe_delivery_system_t	delivery_system; - -	/* 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; -	    fe_code_rate_t	fec; -	    fe_modulation_t	modulation; -	    u8			interleaving; -	} layer[3]; - -	/* ISDB-T specifics */ -	u32			isdbs_ts_id; -}; - -struct dvb_frontend { -	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 -	int (*callback)(void *adapter_priv, int component, int cmd, int arg); -	int id; -}; - -extern int dvb_register_frontend(struct dvb_adapter *dvb, -				 struct dvb_frontend *fe); - -extern int dvb_unregister_frontend(struct dvb_frontend *fe); - -extern void dvb_frontend_detach(struct dvb_frontend *fe); - -extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); - -extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); -extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); - -#endif diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c deleted file mode 100644 index beb7c93aa6c..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_math.c +++ /dev/null @@ -1,145 +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. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/bitops.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <asm/bug.h> -#include "dvb_math.h" - -static const unsigned short logtable[256] = { -	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, -	0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508, -	0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6, -	0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37, -	0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f, -	0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41, -	0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1, -	0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142, -	0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68, -	0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355, -	0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c, -	0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490, -	0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3, -	0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507, -	0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe, -	0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca, -	0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c, -	0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7, -	0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c, -	0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c, -	0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a, -	0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065, -	0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730, -	0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc, -	0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469, -	0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9, -	0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c, -	0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765, -	0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, -	0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, -	0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, -	0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 -}; - -unsigned int intlog2(u32 value) -{ -	/** -	 *	returns: log2(value) * 2^24 -	 *	wrong result if value = 0 (log2(0) is undefined) -	 */ -	unsigned int msb; -	unsigned int logentry; -	unsigned int significand; -	unsigned int interpolation; - -	if (unlikely(value == 0)) { -		WARN_ON(1); -		return 0; -	} - -	/* first detect the msb (count begins at 0) */ -	msb = fls(value) - 1; - -	/** -	 *	now we use a logtable after the following method: -	 * -	 *	log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24 -	 *	where x = msb and therefore 1 <= y < 2 -	 *	first y is determined by shifting the value left -	 *	so that msb is bit 31 -	 *		0x00231f56 -> 0x8C7D5800 -	 *	the result is y * 2^31 -> "significand" -	 *	then the highest 9 bits are used for a table lookup -	 *	the highest bit is discarded because it's always set -	 *	the highest nine bits in our example are 100011000 -	 *	so we would use the entry 0x18 -	 */ -	significand = value << (31 - msb); -	logentry = (significand >> 23) & 0xff; - -	/** -	 *	last step we do is interpolation because of the -	 *	limitations of the log table the error is that part of -	 *	the significand which isn't used for lookup then we -	 *	compute the ratio between the error and the next table entry -	 *	and interpolate it between the log table entry used and the -	 *	next one the biggest error possible is 0x7fffff -	 *	(in our example it's 0x7D5800) -	 *	needed value for next table entry is 0x800000 -	 *	so the interpolation is -	 *	(error / 0x800000) * (logtable_next - logtable_current) -	 *	in the implementation the division is moved to the end for -	 *	better accuracy there is also an overflow correction if -	 *	logtable_next is 256 -	 */ -	interpolation = ((significand & 0x7fffff) * -			((logtable[(logentry + 1) & 0xff] - -			  logtable[logentry]) & 0xffff)) >> 15; - -	/* now we return the result */ -	return ((msb << 24) + (logtable[logentry] << 8) + interpolation); -} -EXPORT_SYMBOL(intlog2); - -unsigned int intlog10(u32 value) -{ -	/** -	 *	returns: log10(value) * 2^24 -	 *	wrong result if value = 0 (log10(0) is undefined) -	 */ -	u64 log; - -	if (unlikely(value == 0)) { -		WARN_ON(1); -		return 0; -	} - -	log = intlog2(value); - -	/** -	 *	we use the following method: -	 *	log10(x) = log2(x) * log10(2) -	 */ - -	return (log * 646456993) >> 31; -} -EXPORT_SYMBOL(intlog10); diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h deleted file mode 100644 index aecc867e940..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_math.h +++ /dev/null @@ -1,58 +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. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __DVB_MATH_H -#define __DVB_MATH_H - -#include <linux/types.h> - -/** - * computes log2 of a value; the result is shifted left by 24 bits - * - * to use rational values you can use the following method: - *   intlog2(value) = intlog2(value * 2^x) - x * 2^24 - * - * example: intlog2(8) will give 3 << 24 = 3 * 2^24 - * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24 - * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24 - * - * @param value The value (must be != 0) - * @return log2(value) * 2^24 - */ -extern unsigned int intlog2(u32 value); - -/** - * computes log10 of a value; the result is shifted left by 24 bits - * - * to use rational values you can use the following method: - *   intlog10(value) = intlog10(value * 10^x) - x * 2^24 - * - * example: intlog10(1000) will give 3 << 24 = 3 * 2^24 - *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24 - * - * look at intlog2 for similar examples - * - * @param value The value (must be != 0) - * @return log10(value) * 2^24 - */ -extern unsigned int intlog10(u32 value); - -#endif diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c deleted file mode 100644 index 4df42aaae7f..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ /dev/null @@ -1,1517 +0,0 @@ -/* - * dvb_net.c - * - * Copyright (C) 2001 Convergence integrated media GmbH - *                    Ralph Metzler <ralph@convergence.de> - * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> - * - * ULE Decapsulation code: - * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH. - *                      and Department of Scientific Computing - *                          Paris Lodron University of Salzburg. - *                          Hilmar Linder <hlinder@cosy.sbg.ac.at> - *                      and Wolfram Stering <wstering@cosy.sbg.ac.at> - * - * ULE Decaps according to RFC 4326. - * - * 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; either version 2 - * 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 General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -/* - * ULE ChangeLog: - * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt - * - * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt: - *                       ULE Extension header handling. - *                     Bugreports by Moritz Vieth and Hanno Tersteegen, - *                       Fraunhofer Institute for Open Communication Systems - *                       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. - * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by - *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>, - *                       Paris Lodron University of Salzburg. - */ - -/* - * FIXME / TODO (dvb_net.c): - * - * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/dvb/net.h> -#include <linux/uio.h> -#include <asm/uaccess.h> -#include <linux/crc32.h> -#include <linux/mutex.h> -#include <linux/sched.h> - -#include "dvb_demux.h" -#include "dvb_net.h" - -static int dvb_net_debug; -module_param(dvb_net_debug, int, 0444); -MODULE_PARM_DESC(dvb_net_debug, "enable debug messages"); - -#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0) - - -static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) -{ -	unsigned int j; -	for (j = 0; j < cnt; j++) -		c = crc32_be( c, iov[j].iov_base, iov[j].iov_len ); -	return c; -} - - -#define DVB_NET_MULTICAST_MAX 10 - -#undef ULE_DEBUG - -#ifdef ULE_DEBUG - -#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" -#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5] - -#define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) - -static void hexdump( const unsigned char *buf, unsigned short len ) -{ -	char str[80], octet[10]; -	int ofs, i, l; - -	for (ofs = 0; ofs < len; ofs += 16) { -		sprintf( str, "%03d: ", ofs ); - -		for (i = 0; i < 16; i++) { -			if ((i + ofs) < len) -				sprintf( octet, "%02x ", buf[ofs + i] ); -			else -				strcpy( octet, "   " ); - -			strcat( str, octet ); -		} -		strcat( str, "  " ); -		l = strlen( str ); - -		for (i = 0; (i < 16) && ((i + ofs) < len); i++) -			str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.'; - -		str[l] = '\0'; -		printk( KERN_WARNING "%s\n", str ); -	} -} - -#endif - -struct dvb_net_priv { -	int in_use; -	u16 pid; -	struct net_device *net; -	struct dvb_net *host; -	struct dmx_demux *demux; -	struct dmx_section_feed *secfeed; -	struct dmx_section_filter *secfilter; -	struct dmx_ts_feed *tsfeed; -	int multi_num; -	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX]; -	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6]; -	int rx_mode; -#define RX_MODE_UNI 0 -#define RX_MODE_MULTI 1 -#define RX_MODE_ALL_MULTI 2 -#define RX_MODE_PROMISC 3 -	struct work_struct set_multicast_list_wq; -	struct work_struct restart_net_feed_wq; -	unsigned char feedtype;			/* Either FEED_TYPE_ or FEED_TYPE_ULE */ -	int need_pusi;				/* Set to 1, if synchronization on PUSI required. */ -	unsigned char tscc;			/* TS continuity counter after sync on PUSI. */ -	struct sk_buff *ule_skb;		/* ULE SNDU decodes into this buffer. */ -	unsigned char *ule_next_hdr;		/* Pointer into skb to next ULE extension header. */ -	unsigned short ule_sndu_len;		/* ULE SNDU length in bytes, w/o D-Bit. */ -	unsigned short ule_sndu_type;		/* ULE SNDU type field, complete. */ -	unsigned char ule_sndu_type_1;		/* ULE SNDU type field, if split across 2 TS cells. */ -	unsigned char ule_dbit;			/* Whether the DestMAC address present -						 * or not (bit is set). */ -	unsigned char ule_bridged;		/* Whether the ULE_BRIDGED extension header was found. */ -	int ule_sndu_remain;			/* Nr. of bytes still required for current ULE SNDU. */ -	unsigned long ts_count;			/* Current ts cell counter. */ -	struct mutex mutex; -}; - - -/** - *	Determine the packet's protocol ID. The rule here is that we - *	assume 802.3 if the type field is short enough to be a length. - *	This is normal practice and works for any 'now in use' protocol. - * - *  stolen from eth.c out of the linux kernel, hacked for dvb-device - *  by Michael Holzt <kju@debian.org> - */ -static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, -				      struct net_device *dev) -{ -	struct ethhdr *eth; -	unsigned char *rawp; - -	skb_reset_mac_header(skb); -	skb_pull(skb,dev->hard_header_len); -	eth = eth_hdr(skb); - -	if (*eth->h_dest & 1) { -		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) -			skb->pkt_type=PACKET_BROADCAST; -		else -			skb->pkt_type=PACKET_MULTICAST; -	} - -	if (ntohs(eth->h_proto) >= 1536) -		return eth->h_proto; - -	rawp = skb->data; - -	/** -	 *	This is a magic hack to spot IPX packets. Older Novell breaks -	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC -	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This -	 *	won't work for fault tolerant netware but does for the rest. -	 */ -	if (*(unsigned short *)rawp == 0xFFFF) -		return htons(ETH_P_802_3); - -	/** -	 *	Real 802.2 LLC -	 */ -	return htons(ETH_P_802_2); -} - -#define TS_SZ	188 -#define TS_SYNC	0x47 -#define TS_TEI	0x80 -#define TS_SC	0xC0 -#define TS_PUSI	0x40 -#define TS_AF_A	0x20 -#define TS_AF_D	0x10 - -/* ULE Extension Header handlers. */ - -#define ULE_TEST	0 -#define ULE_BRIDGED	1 - -#define ULE_OPTEXTHDR_PADDING 0 - -static int ule_test_sndu( struct dvb_net_priv *p ) -{ -	return -1; -} - -static int ule_bridged_sndu( struct dvb_net_priv *p ) -{ -	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr; -	if(ntohs(hdr->h_proto) < 1536) { -		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data); -		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */ -		if(framelen != ntohs(hdr->h_proto)) { -			return -1; -		} -	} -	/* Note: -	 * From RFC4326: -	 *  "A bridged SNDU is a Mandatory Extension Header of Type 1. -	 *   It must be the final (or only) extension header specified in the header chain of a SNDU." -	 * The 'ule_bridged' flag will cause the extension header processing loop to terminate. -	 */ -	p->ule_bridged = 1; -	return 0; -} - -static int ule_exthdr_padding(struct dvb_net_priv *p) -{ -	return 0; -} - -/** Handle ULE extension headers. - *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. - *  Returns: >= 0: nr. of bytes consumed by next extension header - *	     -1:   Mandatory extension header that is not recognized or TEST SNDU; discard. - */ -static int handle_one_ule_extension( struct dvb_net_priv *p ) -{ -	/* Table of mandatory extension header handlers.  The header type is the index. */ -	static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) = -		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  }; - -	/* Table of optional extension header handlers.  The header type is the index. */ -	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = -		{ [0] = ule_exthdr_padding, [1] = NULL, }; - -	int ext_len = 0; -	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; -	unsigned char htype = p->ule_sndu_type & 0x00FF; - -	/* Discriminate mandatory and optional extension headers. */ -	if (hlen == 0) { -		/* Mandatory extension header */ -		if (ule_mandatory_ext_handlers[htype]) { -			ext_len = ule_mandatory_ext_handlers[htype]( p ); -			if(ext_len >= 0) { -				p->ule_next_hdr += ext_len; -				if (!p->ule_bridged) { -					p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr); -					p->ule_next_hdr += 2; -				} else { -					p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); -					/* This assures the extension handling loop will terminate. */ -				} -			} -			// else: extension handler failed or SNDU should be discarded -		} else -			ext_len = -1;	/* SNDU has to be discarded. */ -	} else { -		/* Optional extension header.  Calculate the length. */ -		ext_len = hlen << 1; -		/* Process the optional extension header according to its type. */ -		if (ule_optional_ext_handlers[htype]) -			(void)ule_optional_ext_handlers[htype]( p ); -		p->ule_next_hdr += ext_len; -		p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) ); -		/* -		 * note: the length of the next header type is included in the -		 * length of THIS optional extension header -		 */ -	} - -	return ext_len; -} - -static int handle_ule_extensions( struct dvb_net_priv *p ) -{ -	int total_ext_len = 0, l; - -	p->ule_next_hdr = p->ule_skb->data; -	do { -		l = handle_one_ule_extension( p ); -		if (l < 0) -			return l;	/* Stop extension header processing and discard SNDU. */ -		total_ext_len += l; -#ifdef ULE_DEBUG -		dprintk("handle_ule_extensions: 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 < 1536); - -	return total_ext_len; -} - - -/** Prepare for a new ULE SNDU: reset the decoder state. */ -static inline void reset_ule( struct dvb_net_priv *p ) -{ -	p->ule_skb = NULL; -	p->ule_next_hdr = NULL; -	p->ule_sndu_len = 0; -	p->ule_sndu_type = 0; -	p->ule_sndu_type_1 = 0; -	p->ule_sndu_remain = 0; -	p->ule_dbit = 0xFF; -	p->ule_bridged = 0; -} - -/** - * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of - * TS cells of a single PID. - */ -static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); -	unsigned long skipped = 0L; -	const u8 *ts, *ts_end, *from_where = NULL; -	u8 ts_remain = 0, how_much = 0, new_ts = 1; -	struct ethhdr *ethh = NULL; -	bool error = false; - -#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 - -	/* For all TS cells in current buffer. -	 * Appearently, we are called for every single TS cell. -	 */ -	for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) { - -		if (new_ts) { -			/* We are about to process a new TS cell. */ - -#ifdef ULE_DEBUG -			if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist; -			memcpy( ule_where, ts, TS_SZ ); -			if (ule_dump) { -				hexdump( ule_where, TS_SZ ); -				ule_dump = 0; -			} -			ule_where += TS_SZ; -#endif - -			/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */ -			if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) { -				printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n", -				       priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6); - -				/* Drop partly decoded SNDU, reset state, resync on PUSI. */ -				if (priv->ule_skb) { -					dev_kfree_skb( priv->ule_skb ); -					/* Prepare for next SNDU. */ -					dev->stats.rx_errors++; -					dev->stats.rx_frame_errors++; -				} -				reset_ule(priv); -				priv->need_pusi = 1; - -				/* Continue with next TS cell. */ -				ts += TS_SZ; -				priv->ts_count++; -				continue; -			} - -			ts_remain = 184; -			from_where = ts + 4; -		} -		/* Synchronize on PUSI, if required. */ -		if (priv->need_pusi) { -			if (ts[1] & TS_PUSI) { -				/* Find beginning of first ULE SNDU in current TS cell. */ -				/* Synchronize continuity counter. */ -				priv->tscc = ts[3] & 0x0F; -				/* There is a pointer field here. */ -				if (ts[4] > ts_remain) { -					printk(KERN_ERR "%lu: Invalid ULE packet " -					       "(pointer field %d)\n", priv->ts_count, ts[4]); -					ts += TS_SZ; -					priv->ts_count++; -					continue; -				} -				/* Skip to destination of pointer field. */ -				from_where = &ts[5] + ts[4]; -				ts_remain -= 1 + ts[4]; -				skipped = 0; -			} else { -				skipped++; -				ts += TS_SZ; -				priv->ts_count++; -				continue; -			} -		} - -		if (new_ts) { -			/* Check continuity counter. */ -			if ((ts[3] & 0x0F) == priv->tscc) -				priv->tscc = (priv->tscc + 1) & 0x0F; -			else { -				/* TS discontinuity handling: */ -				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " -				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); -				/* Drop partly decoded SNDU, reset state, resync on PUSI. */ -				if (priv->ule_skb) { -					dev_kfree_skb( priv->ule_skb ); -					/* Prepare for next SNDU. */ -					// reset_ule(priv);  moved to below. -					dev->stats.rx_errors++; -					dev->stats.rx_frame_errors++; -				} -				reset_ule(priv); -				/* skip to next PUSI. */ -				priv->need_pusi = 1; -				continue; -			} -			/* If we still have an incomplete payload, but PUSI is -			 * set; some TS cells are missing. -			 * This is only possible here, if we missed exactly 16 TS -			 * cells (continuity counter wrap). */ -			if (ts[1] & TS_PUSI) { -				if (! priv->need_pusi) { -					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) { -						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */ -						printk(KERN_WARNING "%lu: Invalid pointer " -						       "field: %u.\n", priv->ts_count, *from_where); - -						/* Drop partly decoded SNDU, reset state, resync on PUSI. */ -						if (priv->ule_skb) { -							error = true; -							dev_kfree_skb(priv->ule_skb); -						} - -						if (error || priv->ule_sndu_remain) { -							dev->stats.rx_errors++; -							dev->stats.rx_frame_errors++; -							error = false; -						} - -						reset_ule(priv); -						priv->need_pusi = 1; -						continue; -					} -					/* Skip pointer field (we're processing a -					 * packed payload). */ -					from_where += 1; -					ts_remain -= 1; -				} else -					priv->need_pusi = 0; - -				if (priv->ule_sndu_remain > 183) { -					/* Current SNDU lacks more data than there could be available in the -					 * current TS cell. */ -					dev->stats.rx_errors++; -					dev->stats.rx_length_errors++; -					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " -					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n", -					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); -					dev_kfree_skb(priv->ule_skb); -					/* Prepare for next SNDU. */ -					reset_ule(priv); -					/* Resync: go to where pointer field points to: start of next ULE SNDU. */ -					from_where += ts[4]; -					ts_remain -= ts[4]; -				} -			} -		} - -		/* Check if new payload needs to be started. */ -		if (priv->ule_skb == NULL) { -			/* Start a new payload with skb. -			 * Find ULE header.  It is only guaranteed that the -			 * length field (2 bytes) is contained in the current -			 * TS. -			 * Check ts_remain has to be >= 2 here. */ -			if (ts_remain < 2) { -				printk(KERN_WARNING "Invalid payload packing: only %d " -				       "bytes left in TS.  Resyncing.\n", ts_remain); -				priv->ule_sndu_len = 0; -				priv->need_pusi = 1; -				ts += TS_SZ; -				continue; -			} - -			if (! priv->ule_sndu_len) { -				/* Got at least two bytes, thus extrace the SNDU length. */ -				priv->ule_sndu_len = from_where[0] << 8 | from_where[1]; -				if (priv->ule_sndu_len & 0x8000) { -					/* D-Bit is set: no dest mac present. */ -					priv->ule_sndu_len &= 0x7FFF; -					priv->ule_dbit = 1; -				} else -					priv->ule_dbit = 0; - -				if (priv->ule_sndu_len < 5) { -					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " -					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); -					dev->stats.rx_errors++; -					dev->stats.rx_length_errors++; -					priv->ule_sndu_len = 0; -					priv->need_pusi = 1; -					new_ts = 1; -					ts += TS_SZ; -					priv->ts_count++; -					continue; -				} -				ts_remain -= 2;	/* consume the 2 bytes SNDU length. */ -				from_where += 2; -			} - -			priv->ule_sndu_remain = priv->ule_sndu_len + 2; -			/* -			 * State of current TS: -			 *   ts_remain (remaining bytes in the current TS cell) -			 *   0	ule_type is not available now, we need the next TS cell -			 *   1	the first byte of the ule_type is present -			 * >=2	full ULE header present, maybe some payload data as well. -			 */ -			switch (ts_remain) { -				case 1: -					priv->ule_sndu_remain--; -					priv->ule_sndu_type = from_where[0] << 8; -					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ -					ts_remain -= 1; from_where += 1; -					/* Continue w/ next TS. */ -				case 0: -					new_ts = 1; -					ts += TS_SZ; -					priv->ts_count++; -					continue; - -				default: /* complete ULE header is present in current TS. */ -					/* Extract ULE type field. */ -					if (priv->ule_sndu_type_1) { -						priv->ule_sndu_type_1 = 0; -						priv->ule_sndu_type |= from_where[0]; -						from_where += 1; /* points to payload start. */ -						ts_remain -= 1; -					} else { -						/* Complete type is present in new TS. */ -						priv->ule_sndu_type = from_where[0] << 8 | from_where[1]; -						from_where += 2; /* points to payload start. */ -						ts_remain -= 2; -					} -					break; -			} - -			/* Allocate the skb (decoder target buffer) with the correct size, as follows: -			 * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */ -			priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN ); -			if (priv->ule_skb == NULL) { -				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", -				       dev->name); -				dev->stats.rx_dropped++; -				return; -			} - -			/* This includes the CRC32 _and_ dest mac, if !dbit. */ -			priv->ule_sndu_remain = priv->ule_sndu_len; -			priv->ule_skb->dev = dev; -			/* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */ -			skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN ); -		} - -		/* Copy data into our current skb. */ -		how_much = min(priv->ule_sndu_remain, (int)ts_remain); -		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much); -		priv->ule_sndu_remain -= how_much; -		ts_remain -= how_much; -		from_where += how_much; - -		/* Check for complete payload. */ -		if (priv->ule_sndu_remain <= 0) { -			/* Check CRC32, we've got it in our skb already. */ -			__be16 ulen = htons(priv->ule_sndu_len); -			__be16 utype = htons(priv->ule_sndu_type); -			const u8 *tail; -			struct kvec iov[3] = { -				{ &ulen, sizeof ulen }, -				{ &utype, sizeof utype }, -				{ priv->ule_skb->data, priv->ule_skb->len - 4 } -			}; -			u32 ule_crc = ~0L, expected_crc; -			if (priv->ule_dbit) { -				/* Set D-bit for CRC32 verification, -				 * if it was set originally. */ -				ulen |= htons(0x8000); -			} - -			ule_crc = iov_crc32(ule_crc, iov, 3); -			tail = skb_tail_pointer(priv->ule_skb); -			expected_crc = *(tail - 4) << 24 | -				       *(tail - 3) << 16 | -				       *(tail - 2) << 8 | -				       *(tail - 1); -			if (ule_crc != expected_crc) { -				printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n", -				       priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0); - -#ifdef 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 (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( ule_where - TS_SZ - TS_SZ, TS_SZ ); -					hexdump( ule_where - TS_SZ, TS_SZ ); -				} -				ule_dump = 1; -#endif - -				dev->stats.rx_errors++; -				dev->stats.rx_crc_errors++; -				dev_kfree_skb(priv->ule_skb); -			} else { -				/* CRC32 verified OK. */ -				u8 dest_addr[ETH_ALEN]; -				static const u8 bc_addr[ETH_ALEN] = -					{ [ 0 ... ETH_ALEN-1] = 0xff }; - -				/* CRC32 was OK. Remove it from skb. */ -				priv->ule_skb->tail -= 4; -				priv->ule_skb->len -= 4; - -				if (!priv->ule_dbit) { -					/* -					 * The destination MAC address is the -					 * next data in the skb.  It comes -					 * before any extension headers. -					 * -					 * Check if the payload of this SNDU -					 * should be passed up the stack. -					 */ -					register int drop = 0; -					if (priv->rx_mode != RX_MODE_PROMISC) { -						if (priv->ule_skb->data[0] & 0x01) { -							/* multicast or broadcast */ -							if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) { -								/* multicast */ -								if (priv->rx_mode == RX_MODE_MULTI) { -									int i; -									for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++) -										; -									if (i == priv->multi_num) -										drop = 1; -								} else if (priv->rx_mode != RX_MODE_ALL_MULTI) -									drop = 1; /* no broadcast; */ -								/* else: all multicast mode: accept all multicast packets */ -							} -							/* else: broadcast */ -						} -						else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN)) -							drop = 1; -						/* else: destination address matches the MAC address of our receiver device */ -					} -					/* else: promiscuous mode; pass everything up the stack */ - -					if (drop) { -#ifdef ULE_DEBUG -						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n", -							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr)); -#endif -						dev_kfree_skb(priv->ule_skb); -						goto sndu_done; -					} -					else -					{ -						skb_copy_from_linear_data(priv->ule_skb, -							      dest_addr, -							      ETH_ALEN); -						skb_pull(priv->ule_skb, ETH_ALEN); -					} -				} - -				/* Handle ULE Extension Headers. */ -				if (priv->ule_sndu_type < 1536) { -					/* There is an extension header.  Handle it accordingly. */ -					int l = handle_ule_extensions(priv); -					if (l < 0) { -						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */ -						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); -						dev_kfree_skb(priv->ule_skb); -						goto sndu_done; -					} -					skb_pull(priv->ule_skb, l); -				} - -				/* -				 * Construct/assure correct ethernet header. -				 * Note: in bridged mode (priv->ule_bridged != -				 * 0) we already have the (original) ethernet -				 * header at the start of the payload (after -				 * optional dest. address and any extension -				 * headers). -				 */ - -				if (!priv->ule_bridged) { -					skb_push(priv->ule_skb, ETH_HLEN); -					ethh = (struct ethhdr *)priv->ule_skb->data; -					if (!priv->ule_dbit) { -						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */ -						memcpy(ethh->h_dest, dest_addr, ETH_ALEN); -						memset(ethh->h_source, 0, ETH_ALEN); -					} -					else /* zeroize source and dest */ -						memset( ethh, 0, ETH_ALEN*2 ); - -					ethh->h_proto = htons(priv->ule_sndu_type); -				} -				/* else:  skb is in correct state; nothing to do. */ -				priv->ule_bridged = 0; - -				/* Stuff into kernel's protocol stack. */ -				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev); -				/* If D-bit is set (i.e. destination MAC address not present), -				 * receive the packet anyhow. */ -				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) -					priv->ule_skb->pkt_type = PACKET_HOST; */ -				dev->stats.rx_packets++; -				dev->stats.rx_bytes += priv->ule_skb->len; -				netif_rx(priv->ule_skb); -			} -			sndu_done: -			/* Prepare for next SNDU. */ -			reset_ule(priv); -		} - -		/* More data in current TS (look at the bytes following the CRC32)? */ -		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) { -			/* Next ULE SNDU starts right there. */ -			new_ts = 0; -			priv->ule_skb = NULL; -			priv->ule_sndu_type_1 = 0; -			priv->ule_sndu_len = 0; -			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n", -			//	*(from_where + 0), *(from_where + 1), -			//	*(from_where + 2), *(from_where + 3)); -			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0); -			// hexdump(ts, 188); -		} else { -			new_ts = 1; -			ts += TS_SZ; -			priv->ts_count++; -			if (priv->ule_skb == NULL) { -				priv->need_pusi = 1; -				priv->ule_sndu_type_1 = 0; -				priv->ule_sndu_len = 0; -			} -		} -	}	/* for all available TS cells */ -} - -static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, -			       const u8 *buffer2, size_t buffer2_len, -			       struct dmx_ts_feed *feed, enum dmx_success success) -{ -	struct net_device *dev = feed->priv; - -	if (buffer2) -		printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2); -	if (buffer1_len > 32768) -		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len); -	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n", -		  buffer1_len, buffer1_len / TS_SZ, buffer1); */ -	dvb_net_ule(dev, buffer1, buffer1_len); -	return 0; -} - - -static void dvb_net_sec(struct net_device *dev, -			const u8 *pkt, int pkt_len) -{ -	u8 *eth; -	struct sk_buff *skb; -	struct net_device_stats *stats = &dev->stats; -	int snap = 0; - -	/* note: pkt_len includes a 32bit checksum */ -	if (pkt_len < 16) { -		printk("%s: IP/MPE packet length = %d too small.\n", -			dev->name, pkt_len); -		stats->rx_errors++; -		stats->rx_length_errors++; -		return; -	} -/* it seems some ISPs manage to screw up here, so we have to - * relax the error checks... */ -#if 0 -	if ((pkt[5] & 0xfd) != 0xc1) { -		/* drop scrambled or broken packets */ -#else -	if ((pkt[5] & 0x3c) != 0x00) { -		/* drop scrambled */ -#endif -		stats->rx_errors++; -		stats->rx_crc_errors++; -		return; -	} -	if (pkt[5] & 0x02) { -		/* handle LLC/SNAP, see rfc-1042 */ -		if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) { -			stats->rx_dropped++; -			return; -		} -		snap = 8; -	} -	if (pkt[7]) { -		/* FIXME: assemble datagram from multiple sections */ -		stats->rx_errors++; -		stats->rx_frame_errors++; -		return; -	} - -	/* we have 14 byte ethernet header (ip header follows); -	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP -	 */ -	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) { -		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); -		stats->rx_dropped++; -		return; -	} -	skb_reserve(skb, 2);    /* longword align L3 header */ -	skb->dev = dev; - -	/* copy L3 payload */ -	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap); -	memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap); - -	/* create ethernet header: */ -	eth[0]=pkt[0x0b]; -	eth[1]=pkt[0x0a]; -	eth[2]=pkt[0x09]; -	eth[3]=pkt[0x08]; -	eth[4]=pkt[0x04]; -	eth[5]=pkt[0x03]; - -	eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0; - -	if (snap) { -		eth[12] = pkt[18]; -		eth[13] = pkt[19]; -	} else { -		/* protocol numbers are from rfc-1700 or -		 * http://www.iana.org/assignments/ethernet-numbers -		 */ -		if (pkt[12] >> 4 == 6) { /* version field from IP header */ -			eth[12] = 0x86;	/* IPv6 */ -			eth[13] = 0xdd; -		} else { -			eth[12] = 0x08;	/* IPv4 */ -			eth[13] = 0x00; -		} -	} - -	skb->protocol = dvb_net_eth_type_trans(skb, dev); - -	stats->rx_packets++; -	stats->rx_bytes+=skb->len; -	netif_rx(skb); -} - -static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, -		 const u8 *buffer2, size_t buffer2_len, -		 struct dmx_section_filter *filter, -		 enum dmx_success success) -{ -	struct net_device *dev = filter->priv; - -	/** -	 * we rely on the DVB API definition where exactly one complete -	 * section is delivered in buffer1 -	 */ -	dvb_net_sec (dev, buffer1, buffer1_len); -	return 0; -} - -static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) -{ -	dev_kfree_skb(skb); -	return NETDEV_TX_OK; -} - -static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00}; -static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00}; -static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -static int dvb_net_filter_sec_set(struct net_device *dev, -		   struct dmx_section_filter **secfilter, -		   u8 *mac, u8 *mac_mask) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); -	int ret; - -	*secfilter=NULL; -	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter); -	if (ret<0) { -		printk("%s: could not get filter\n", dev->name); -		return ret; -	} - -	(*secfilter)->priv=(void *) dev; - -	memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE); -	memset((*secfilter)->filter_mask,  0x00, DMX_MAX_FILTER_SIZE); -	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE); - -	(*secfilter)->filter_value[0]=0x3e; -	(*secfilter)->filter_value[3]=mac[5]; -	(*secfilter)->filter_value[4]=mac[4]; -	(*secfilter)->filter_value[8]=mac[3]; -	(*secfilter)->filter_value[9]=mac[2]; -	(*secfilter)->filter_value[10]=mac[1]; -	(*secfilter)->filter_value[11]=mac[0]; - -	(*secfilter)->filter_mask[0] = 0xff; -	(*secfilter)->filter_mask[3] = mac_mask[5]; -	(*secfilter)->filter_mask[4] = mac_mask[4]; -	(*secfilter)->filter_mask[8] = mac_mask[3]; -	(*secfilter)->filter_mask[9] = mac_mask[2]; -	(*secfilter)->filter_mask[10] = mac_mask[1]; -	(*secfilter)->filter_mask[11]=mac_mask[0]; - -	dprintk("%s: filter mac=%pM\n", dev->name, mac); -	dprintk("%s: filter mask=%pM\n", dev->name, mac_mask); - -	return 0; -} - -static int dvb_net_feed_start(struct net_device *dev) -{ -	int ret = 0, i; -	struct dvb_net_priv *priv = netdev_priv(dev); -	struct dmx_demux *demux = priv->demux; -	unsigned char *mac = (unsigned char *) dev->dev_addr; - -	dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode); -	mutex_lock(&priv->mutex); -	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) -		printk("%s: BUG %d\n", __func__, __LINE__); - -	priv->secfeed=NULL; -	priv->secfilter=NULL; -	priv->tsfeed = NULL; - -	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { -		dprintk("%s: alloc secfeed\n", __func__); -		ret=demux->allocate_section_feed(demux, &priv->secfeed, -					 dvb_net_sec_callback); -		if (ret<0) { -			printk("%s: could not allocate section feed\n", dev->name); -			goto error; -		} - -		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1); - -		if (ret<0) { -			printk("%s: could not set section feed\n", dev->name); -			priv->demux->release_section_feed(priv->demux, priv->secfeed); -			priv->secfeed=NULL; -			goto error; -		} - -		if (priv->rx_mode != RX_MODE_PROMISC) { -			dprintk("%s: set secfilter\n", __func__); -			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal); -		} - -		switch (priv->rx_mode) { -		case RX_MODE_MULTI: -			for (i = 0; i < priv->multi_num; i++) { -				dprintk("%s: set multi_secfilter[%d]\n", __func__, i); -				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i], -						       priv->multi_macs[i], mask_normal); -			} -			break; -		case RX_MODE_ALL_MULTI: -			priv->multi_num=1; -			dprintk("%s: set multi_secfilter[0]\n", __func__); -			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0], -					       mac_allmulti, mask_allmulti); -			break; -		case RX_MODE_PROMISC: -			priv->multi_num=0; -			dprintk("%s: set secfilter\n", __func__); -			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc); -			break; -		} - -		dprintk("%s: start filtering\n", __func__); -		priv->secfeed->start_filtering(priv->secfeed); -	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { -		struct timespec timeout = { 0, 10000000 }; // 10 msec - -		/* we have payloads encapsulated in TS */ -		dprintk("%s: alloc tsfeed\n", __func__); -		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback); -		if (ret < 0) { -			printk("%s: could not allocate ts feed\n", dev->name); -			goto error; -		} - -		/* Set netdevice pointer for ts decaps callback. */ -		priv->tsfeed->priv = (void *)dev; -		ret = priv->tsfeed->set(priv->tsfeed, -					priv->pid, /* pid */ -					TS_PACKET, /* type */ -					DMX_TS_PES_OTHER, /* pes type */ -					32768,     /* circular buffer size */ -					timeout    /* timeout */ -					); - -		if (ret < 0) { -			printk("%s: could not set ts feed\n", dev->name); -			priv->demux->release_ts_feed(priv->demux, priv->tsfeed); -			priv->tsfeed = NULL; -			goto error; -		} - -		dprintk("%s: start filtering\n", __func__); -		priv->tsfeed->start_filtering(priv->tsfeed); -	} else -		ret = -EINVAL; - -error: -	mutex_unlock(&priv->mutex); -	return ret; -} - -static int dvb_net_feed_stop(struct net_device *dev) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); -	int i, ret = 0; - -	dprintk("%s\n", __func__); -	mutex_lock(&priv->mutex); -	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { -		if (priv->secfeed) { -			if (priv->secfeed->is_filtering) { -				dprintk("%s: stop secfeed\n", __func__); -				priv->secfeed->stop_filtering(priv->secfeed); -			} - -			if (priv->secfilter) { -				dprintk("%s: release secfilter\n", __func__); -				priv->secfeed->release_filter(priv->secfeed, -							      priv->secfilter); -				priv->secfilter=NULL; -			} - -			for (i=0; i<priv->multi_num; i++) { -				if (priv->multi_secfilter[i]) { -					dprintk("%s: release multi_filter[%d]\n", -						__func__, i); -					priv->secfeed->release_filter(priv->secfeed, -								      priv->multi_secfilter[i]); -					priv->multi_secfilter[i] = NULL; -				} -			} - -			priv->demux->release_section_feed(priv->demux, priv->secfeed); -			priv->secfeed = NULL; -		} else -			printk("%s: no feed to stop\n", dev->name); -	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { -		if (priv->tsfeed) { -			if (priv->tsfeed->is_filtering) { -				dprintk("%s: stop tsfeed\n", __func__); -				priv->tsfeed->stop_filtering(priv->tsfeed); -			} -			priv->demux->release_ts_feed(priv->demux, priv->tsfeed); -			priv->tsfeed = NULL; -		} -		else -			printk("%s: no ts feed to stop\n", dev->name); -	} else -		ret = -EINVAL; -	mutex_unlock(&priv->mutex); -	return ret; -} - - -static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); - -	if (priv->multi_num == DVB_NET_MULTICAST_MAX) -		return -ENOMEM; - -	memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN); - -	priv->multi_num++; -	return 0; -} - - -static void wq_set_multicast_list (struct work_struct *work) -{ -	struct dvb_net_priv *priv = -		container_of(work, struct dvb_net_priv, set_multicast_list_wq); -	struct net_device *dev = priv->net; - -	dvb_net_feed_stop(dev); -	priv->rx_mode = RX_MODE_UNI; -	netif_addr_lock_bh(dev); - -	if (dev->flags & IFF_PROMISC) { -		dprintk("%s: promiscuous mode\n", dev->name); -		priv->rx_mode = RX_MODE_PROMISC; -	} else if ((dev->flags & IFF_ALLMULTI)) { -		dprintk("%s: allmulti mode\n", dev->name); -		priv->rx_mode = RX_MODE_ALL_MULTI; -	} else if (!netdev_mc_empty(dev)) { -		struct netdev_hw_addr *ha; - -		dprintk("%s: set_mc_list, %d entries\n", -			dev->name, netdev_mc_count(dev)); - -		priv->rx_mode = RX_MODE_MULTI; -		priv->multi_num = 0; - -		netdev_for_each_mc_addr(ha, dev) -			dvb_set_mc_filter(dev, ha->addr); -	} - -	netif_addr_unlock_bh(dev); -	dvb_net_feed_start(dev); -} - - -static void dvb_net_set_multicast_list (struct net_device *dev) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); -	schedule_work(&priv->set_multicast_list_wq); -} - - -static void wq_restart_net_feed (struct work_struct *work) -{ -	struct dvb_net_priv *priv = -		container_of(work, struct dvb_net_priv, restart_net_feed_wq); -	struct net_device *dev = priv->net; - -	if (netif_running(dev)) { -		dvb_net_feed_stop(dev); -		dvb_net_feed_start(dev); -	} -} - - -static int dvb_net_set_mac (struct net_device *dev, void *p) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); -	struct sockaddr *addr=p; - -	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - -	if (netif_running(dev)) -		schedule_work(&priv->restart_net_feed_wq); - -	return 0; -} - - -static int dvb_net_open(struct net_device *dev) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); - -	priv->in_use++; -	dvb_net_feed_start(dev); -	return 0; -} - - -static int dvb_net_stop(struct net_device *dev) -{ -	struct dvb_net_priv *priv = netdev_priv(dev); - -	priv->in_use--; -	return dvb_net_feed_stop(dev); -} - -static const struct header_ops dvb_header_ops = { -	.create		= eth_header, -	.parse		= eth_header_parse, -	.rebuild	= eth_rebuild_header, -}; - - -static const struct net_device_ops dvb_netdev_ops = { -	.ndo_open		= dvb_net_open, -	.ndo_stop		= dvb_net_stop, -	.ndo_start_xmit		= dvb_net_tx, -	.ndo_set_multicast_list = dvb_net_set_multicast_list, -	.ndo_set_mac_address    = dvb_net_set_mac, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static void dvb_net_setup(struct net_device *dev) -{ -	ether_setup(dev); - -	dev->header_ops		= &dvb_header_ops; -	dev->netdev_ops		= &dvb_netdev_ops; -	dev->mtu		= 4096; - -	dev->flags |= IFF_NOARP; -} - -static int get_if(struct dvb_net *dvbnet) -{ -	int i; - -	for (i=0; i<DVB_NET_DEVICES_MAX; i++) -		if (!dvbnet->state[i]) -			break; - -	if (i == DVB_NET_DEVICES_MAX) -		return -1; - -	dvbnet->state[i]=1; -	return i; -} - -static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) -{ -	struct net_device *net; -	struct dvb_net_priv *priv; -	int result; -	int if_num; - -	if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE) -		return -EINVAL; -	if ((if_num = get_if(dvbnet)) < 0) -		return -EINVAL; - -	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup); -	if (!net) -		return -ENOMEM; - -	if (dvbnet->dvbdev->id) -		snprintf(net->name, IFNAMSIZ, "dvb%d%u%d", -			 dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num); -	else -		/* compatibility fix to keep dvb0_0 format */ -		snprintf(net->name, IFNAMSIZ, "dvb%d_%d", -			 dvbnet->dvbdev->adapter->num, if_num); - -	net->addr_len = 6; -	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); - -	dvbnet->device[if_num] = net; - -	priv = netdev_priv(net); -	priv->net = net; -	priv->demux = dvbnet->demux; -	priv->pid = pid; -	priv->rx_mode = RX_MODE_UNI; -	priv->need_pusi = 1; -	priv->tscc = 0; -	priv->feedtype = feedtype; -	reset_ule(priv); - -	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list); -	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed); -	mutex_init(&priv->mutex); - -	net->base_addr = pid; - -	if ((result = register_netdev(net)) < 0) { -		dvbnet->device[if_num] = NULL; -		free_netdev(net); -		return result; -	} -	printk("dvb_net: created network interface %s\n", net->name); - -	return if_num; -} - -static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) -{ -	struct net_device *net = dvbnet->device[num]; -	struct dvb_net_priv *priv; - -	if (!dvbnet->state[num]) -		return -EINVAL; -	priv = netdev_priv(net); -	if (priv->in_use) -		return -EBUSY; - -	dvb_net_stop(net); -	flush_scheduled_work(); -	printk("dvb_net: removed network interface %s\n", net->name); -	unregister_netdev(net); -	dvbnet->state[num]=0; -	dvbnet->device[num] = NULL; -	free_netdev(net); - -	return 0; -} - -static int dvb_net_do_ioctl(struct file *file, -		  unsigned int cmd, void *parg) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_net *dvbnet = dvbdev->priv; - -	if (((file->f_flags&O_ACCMODE)==O_RDONLY)) -		return -EPERM; - -	switch (cmd) { -	case NET_ADD_IF: -	{ -		struct dvb_net_if *dvbnetif = parg; -		int result; - -		if (!capable(CAP_SYS_ADMIN)) -			return -EPERM; - -		if (!try_module_get(dvbdev->adapter->module)) -			return -EPERM; - -		result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype); -		if (result<0) { -			module_put(dvbdev->adapter->module); -			return result; -		} -		dvbnetif->if_num=result; -		break; -	} -	case NET_GET_IF: -	{ -		struct net_device *netdev; -		struct dvb_net_priv *priv_data; -		struct dvb_net_if *dvbnetif = parg; - -		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || -		    !dvbnet->state[dvbnetif->if_num]) -			return -EINVAL; - -		netdev = dvbnet->device[dvbnetif->if_num]; - -		priv_data = netdev_priv(netdev); -		dvbnetif->pid=priv_data->pid; -		dvbnetif->feedtype=priv_data->feedtype; -		break; -	} -	case NET_REMOVE_IF: -	{ -		int ret; - -		if (!capable(CAP_SYS_ADMIN)) -			return -EPERM; -		if ((unsigned long) parg >= DVB_NET_DEVICES_MAX) -			return -EINVAL; -		ret = dvb_net_remove_if(dvbnet, (unsigned long) parg); -		if (!ret) -			module_put(dvbdev->adapter->module); -		return ret; -	} - -	/* binary compatibility cruft */ -	case __NET_ADD_IF_OLD: -	{ -		struct __dvb_net_if_old *dvbnetif = parg; -		int result; - -		if (!capable(CAP_SYS_ADMIN)) -			return -EPERM; - -		if (!try_module_get(dvbdev->adapter->module)) -			return -EPERM; - -		result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE); -		if (result<0) { -			module_put(dvbdev->adapter->module); -			return result; -		} -		dvbnetif->if_num=result; -		break; -	} -	case __NET_GET_IF_OLD: -	{ -		struct net_device *netdev; -		struct dvb_net_priv *priv_data; -		struct __dvb_net_if_old *dvbnetif = parg; - -		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || -		    !dvbnet->state[dvbnetif->if_num]) -			return -EINVAL; - -		netdev = dvbnet->device[dvbnetif->if_num]; - -		priv_data = netdev_priv(netdev); -		dvbnetif->pid=priv_data->pid; -		break; -	} -	default: -		return -ENOTTY; -	} -	return 0; -} - -static long dvb_net_ioctl(struct file *file, -	      unsigned int cmd, unsigned long arg) -{ -	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); -} - -static int dvb_net_close(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; -	struct dvb_net *dvbnet = dvbdev->priv; - -	dvb_generic_release(inode, file); - -	if(dvbdev->users == 1 && dvbnet->exit == 1) { -		fops_put(file->f_op); -		file->f_op = NULL; -		wake_up(&dvbdev->wait_queue); -	} -	return 0; -} - - -static const struct file_operations dvb_net_fops = { -	.owner = THIS_MODULE, -	.unlocked_ioctl = dvb_net_ioctl, -	.open =	dvb_generic_open, -	.release = dvb_net_close, -	.llseek = noop_llseek, -}; - -static struct dvb_device dvbdev_net = { -	.priv = NULL, -	.users = 1, -	.writers = 1, -	.fops = &dvb_net_fops, -}; - - -void dvb_net_release (struct dvb_net *dvbnet) -{ -	int i; - -	dvbnet->exit = 1; -	if (dvbnet->dvbdev->users < 1) -		wait_event(dvbnet->dvbdev->wait_queue, -				dvbnet->dvbdev->users==1); - -	dvb_unregister_device(dvbnet->dvbdev); - -	for (i=0; i<DVB_NET_DEVICES_MAX; i++) { -		if (!dvbnet->state[i]) -			continue; -		dvb_net_remove_if(dvbnet, i); -	} -} -EXPORT_SYMBOL(dvb_net_release); - - -int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, -		  struct dmx_demux *dmx) -{ -	int i; - -	dvbnet->demux = dmx; - -	for (i=0; i<DVB_NET_DEVICES_MAX; i++) -		dvbnet->state[i] = 0; - -	dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net, -			     dvbnet, DVB_DEVICE_NET); - -	return 0; -} -EXPORT_SYMBOL(dvb_net_init); diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h deleted file mode 100644 index 3a3126cae03..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_net.h +++ /dev/null @@ -1,47 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#ifndef _DVB_NET_H_ -#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 - -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; -}; - - -void dvb_net_release(struct dvb_net *); -int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); - -#endif diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c deleted file mode 100644 index a5712cd7c65..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * - * dvb_ringbuffer.c: 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. - * - * 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. - */ - - - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <asm/uaccess.h> - -#include "dvb_ringbuffer.h" - -#define PKT_READY 0 -#define PKT_DISPOSED 1 - - -void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) -{ -	rbuf->pread=rbuf->pwrite=0; -	rbuf->data=data; -	rbuf->size=len; -	rbuf->error=0; - -	init_waitqueue_head(&rbuf->queue); - -	spin_lock_init(&(rbuf->lock)); -} - - - -int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) -{ -	return (rbuf->pread==rbuf->pwrite); -} - - - -ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) -{ -	ssize_t free; - -	free = rbuf->pread - rbuf->pwrite; -	if (free <= 0) -		free += rbuf->size; -	return free-1; -} - - - -ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) -{ -	ssize_t avail; - -	avail = rbuf->pwrite - rbuf->pread; -	if (avail < 0) -		avail += rbuf->size; -	return avail; -} - - - -void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) -{ -	rbuf->pread = rbuf->pwrite; -	rbuf->error = 0; -} -EXPORT_SYMBOL(dvb_ringbuffer_flush); - -void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) -{ -	rbuf->pread = rbuf->pwrite = 0; -	rbuf->error = 0; -} - -void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) -{ -	unsigned long flags; - -	spin_lock_irqsave(&rbuf->lock, flags); -	dvb_ringbuffer_flush(rbuf); -	spin_unlock_irqrestore(&rbuf->lock, flags); - -	wake_up(&rbuf->queue); -} - -ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len) -{ -	size_t todo = len; -	size_t split; - -	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; -	if (split > 0) { -		if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) -			return -EFAULT; -		buf += split; -		todo -= split; -		rbuf->pread = 0; -	} -	if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) -		return -EFAULT; - -	rbuf->pread = (rbuf->pread + todo) % rbuf->size; - -	return len; -} - -void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) -{ -	size_t todo = len; -	size_t split; - -	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; -	if (split > 0) { -		memcpy(buf, rbuf->data+rbuf->pread, split); -		buf += split; -		todo -= split; -		rbuf->pread = 0; -	} -	memcpy(buf, rbuf->data+rbuf->pread, todo); - -	rbuf->pread = (rbuf->pread + todo) % rbuf->size; -} - - -ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) -{ -	size_t todo = len; -	size_t split; - -	split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; - -	if (split > 0) { -		memcpy(rbuf->data+rbuf->pwrite, buf, split); -		buf += split; -		todo -= split; -		rbuf->pwrite = 0; -	} -	memcpy(rbuf->data+rbuf->pwrite, buf, todo); -	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; - -	return len; -} - -ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) -{ -	int status; -	ssize_t oldpwrite = rbuf->pwrite; - -	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8); -	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff); -	DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY); -	status = dvb_ringbuffer_write(rbuf, buf, len); - -	if (status < 0) rbuf->pwrite = oldpwrite; -	return status; -} - -ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, -				int offset, u8 __user *buf, size_t len) -{ -	size_t todo; -	size_t split; -	size_t pktlen; - -	pktlen = rbuf->data[idx] << 8; -	pktlen |= rbuf->data[(idx + 1) % rbuf->size]; -	if (offset > pktlen) return -EINVAL; -	if ((offset + len) > pktlen) len = pktlen - offset; - -	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; -	todo = len; -	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; -	if (split > 0) { -		if (copy_to_user(buf, rbuf->data+idx, split)) -			return -EFAULT; -		buf += split; -		todo -= split; -		idx = 0; -	} -	if (copy_to_user(buf, rbuf->data+idx, todo)) -		return -EFAULT; - -	return len; -} - -ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, -				int offset, u8* buf, size_t len) -{ -	size_t todo; -	size_t split; -	size_t pktlen; - -	pktlen = rbuf->data[idx] << 8; -	pktlen |= rbuf->data[(idx + 1) % rbuf->size]; -	if (offset > pktlen) return -EINVAL; -	if ((offset + len) > pktlen) len = pktlen - offset; - -	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; -	todo = len; -	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; -	if (split > 0) { -		memcpy(buf, rbuf->data+idx, split); -		buf += split; -		todo -= split; -		idx = 0; -	} -	memcpy(buf, rbuf->data+idx, todo); -	return len; -} - -void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) -{ -	size_t pktlen; - -	rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; - -	// clean up disposed packets -	while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { -		if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { -			pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; -			pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); -			DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); -		} else { -			// first packet is not disposed, so we stop cleaning now -			break; -		} -	} -} - -ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen) -{ -	int consumed; -	int curpktlen; -	int curpktstatus; - -	if (idx == -1) { -	       idx = rbuf->pread; -	} else { -		curpktlen = rbuf->data[idx] << 8; -		curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; -		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; -	} - -	consumed = (idx - rbuf->pread) % rbuf->size; - -	while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { - -		curpktlen = rbuf->data[idx] << 8; -		curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; -		curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; - -		if (curpktstatus == PKT_READY) { -			*pktlen = curpktlen; -			return idx; -		} - -		consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; -		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; -	} - -	// no packets available -	return -1; -} - - - -EXPORT_SYMBOL(dvb_ringbuffer_init); -EXPORT_SYMBOL(dvb_ringbuffer_empty); -EXPORT_SYMBOL(dvb_ringbuffer_free); -EXPORT_SYMBOL(dvb_ringbuffer_avail); -EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); -EXPORT_SYMBOL(dvb_ringbuffer_read_user); -EXPORT_SYMBOL(dvb_ringbuffer_read); -EXPORT_SYMBOL(dvb_ringbuffer_write); diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h deleted file mode 100644 index 41f04dae69b..00000000000 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ /dev/null @@ -1,186 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _DVB_RINGBUFFER_H_ -#define _DVB_RINGBUFFER_H_ - -#include <linux/spinlock.h> -#include <linux/wait.h> - -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 - - -/* -** Notes: -** ------ -** (1) For performance reasons read and write routines don't check buffer sizes -**     and/or number of bytes free/available. This has to be done before these -**     routines are called. For example: -** -**     *** write <buflen> bytes *** -**     free = dvb_ringbuffer_free(rbuf); -**     if (free >= buflen) -**         count = dvb_ringbuffer_write(rbuf, buffer, buflen); -**     else -**         ... -** -**     *** read min. 1000, max. <bufsize> bytes *** -**     avail = dvb_ringbuffer_avail(rbuf); -**     if (avail >= 1000) -**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize)); -**     else -**         ... -** -** (2) If there is exactly one reader and one writer, there is no need -**     to lock read or write operations. -**     Two or more readers must be locked against each other. -**     Flushing the buffer counts as a read operation. -**     Resetting the buffer counts as a read and write operation. -**     Two or more writers must be locked against each other. -*/ - -/* initialize ring buffer, lock and queue */ -extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len); - -/* test whether buffer is empty */ -extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); - -/* return the number of free bytes in the buffer */ -extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); - -/* return the number of bytes waiting in the buffer */ -extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); - - -/* -** Reset the read and write pointers to zero and flush the buffer -** This counts as a read and write operation -*/ -extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); - - -/* read routines & macros */ -/* ---------------------- */ -/* flush buffer */ -extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); - -/* flush buffer protected by spinlock and wake-up waiting task(s) */ -extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); - -/* peek at byte <offs> in the buffer */ -#define DVB_RINGBUFFER_PEEK(rbuf,offs)	\ -			(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size] - -/* advance read ptr by <num> bytes */ -#define DVB_RINGBUFFER_SKIP(rbuf,num)	\ -			(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size - -/* -** read <len> bytes from ring buffer into <buf> -** <usermem> specifies whether <buf> resides in user space -** returns number of bytes transferred or -EFAULT -*/ -extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, -				   u8 __user *buf, size_t len); -extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, -				   u8 *buf, size_t len); - - -/* write routines & macros */ -/* ----------------------- */ -/* write single byte to ring buffer */ -#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte)	\ -			{ (rbuf)->data[(rbuf)->pwrite]=(byte); \ -			(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; } -/* -** write <len> bytes to ring buffer -** <usermem> specifies whether <buf> resides in user space -** returns number of bytes transferred or -EFAULT -*/ -extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, -				    size_t len); - - -/** - * Write a packet into the ringbuffer. - * - * <rbuf> Ringbuffer to write to. - * <buf> Buffer to write. - * <len> Length of buffer (currently limited to 65535 bytes max). - * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. - */ -extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, -					size_t len); - -/** - * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this - * does NOT update the read pointer in the ringbuffer. You must use - * dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required. - * - * <rbuf> Ringbuffer concerned. - * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). - * <offset> Offset into packet to read from. - * <buf> Destination buffer for data. - * <len> Size of destination buffer. - * <usermem> Set to 1 if <buf> is in userspace. - * returns Number of bytes read, or -EFAULT. - */ -extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, -				       int offset, u8 __user *buf, size_t len); -extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, -				       int offset, u8 *buf, size_t len); - -/** - * Dispose of a packet in the ring buffer. - * - * <rbuf> Ring buffer concerned. - * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). - */ -extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); - -/** - * Get the index of the next packet in a ringbuffer. - * - * <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_ */ diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c deleted file mode 100644 index f7328777595..00000000000 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * dvbdev.c - * - * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de> - *                  & Marcus Metzler <marcus@convergence.de> - *                    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. - * - * 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. - * - */ - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/mutex.h> -#include "dvbdev.h" - -static DEFINE_MUTEX(dvbdev_mutex); -static int dvbdev_debug; - -module_param(dvbdev_debug, int, 0644); -MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); - -#define dprintk if (dvbdev_debug) printk - -static LIST_HEAD(dvb_adapter_list); -static DEFINE_MUTEX(dvbdev_register_lock); - -static const char * const dnames[] = { -	"video", "audio", "sec", "frontend", "demux", "dvr", "ca", -	"net", "osd" -}; - -#ifdef CONFIG_DVB_DYNAMIC_MINORS -#define MAX_DVB_MINORS		256 -#define DVB_MAX_IDS		MAX_DVB_MINORS -#else -#define DVB_MAX_IDS		4 -#define nums2minor(num,type,id)	((num << 6) | (id << 4) | type) -#define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64) -#endif - -static struct class *dvb_class; - -static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; -static DECLARE_RWSEM(minor_rwsem); - -static int dvb_device_open(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev; - -	mutex_lock(&dvbdev_mutex); -	down_read(&minor_rwsem); -	dvbdev = dvb_minors[iminor(inode)]; - -	if (dvbdev && dvbdev->fops) { -		int err = 0; -		const struct file_operations *old_fops; - -		file->private_data = dvbdev; -		old_fops = file->f_op; -		file->f_op = fops_get(dvbdev->fops); -		if (file->f_op == NULL) { -			file->f_op = old_fops; -			goto fail; -		} -		if(file->f_op->open) -			err = file->f_op->open(inode,file); -		if (err) { -			fops_put(file->f_op); -			file->f_op = fops_get(old_fops); -		} -		fops_put(old_fops); -		up_read(&minor_rwsem); -		mutex_unlock(&dvbdev_mutex); -		return err; -	} -fail: -	up_read(&minor_rwsem); -	mutex_unlock(&dvbdev_mutex); -	return -ENODEV; -} - - -static const struct file_operations dvb_device_fops = -{ -	.owner =	THIS_MODULE, -	.open =		dvb_device_open, -	.llseek =	noop_llseek, -}; - -static struct cdev dvb_device_cdev; - -int dvb_generic_open(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; - -	if (!dvbdev) -		return -ENODEV; - -	if (!dvbdev->users) -		return -EBUSY; - -	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -		if (!dvbdev->readers) -			return -EBUSY; -		dvbdev->readers--; -	} else { -		if (!dvbdev->writers) -			return -EBUSY; -		dvbdev->writers--; -	} - -	dvbdev->users--; -	return 0; -} -EXPORT_SYMBOL(dvb_generic_open); - - -int dvb_generic_release(struct inode *inode, struct file *file) -{ -	struct dvb_device *dvbdev = file->private_data; - -	if (!dvbdev) -		return -ENODEV; - -	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -		dvbdev->readers++; -	} else { -		dvbdev->writers++; -	} - -	dvbdev->users++; -	return 0; -} -EXPORT_SYMBOL(dvb_generic_release); - - -long dvb_generic_ioctl(struct file *file, -		       unsigned int cmd, unsigned long arg) -{ -	struct dvb_device *dvbdev = file->private_data; - -	if (!dvbdev) -		return -ENODEV; - -	if (!dvbdev->kernel_ioctl) -		return -EINVAL; - -	return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); -} -EXPORT_SYMBOL(dvb_generic_ioctl); - - -static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) -{ -	u32 id = 0; - -	while (id < DVB_MAX_IDS) { -		struct dvb_device *dev; -		list_for_each_entry(dev, &adap->device_list, list_head) -			if (dev->type == type && dev->id == id) -				goto skip; -		return id; -skip: -		id++; -	} -	return -ENFILE; -} - - -int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, -			const struct dvb_device *template, void *priv, int type) -{ -	struct dvb_device *dvbdev; -	struct file_operations *dvbdevfops; -	struct device *clsdev; -	int minor; -	int id; - -	mutex_lock(&dvbdev_register_lock); - -	if ((id = dvbdev_get_free_id (adap, type)) < 0){ -		mutex_unlock(&dvbdev_register_lock); -		*pdvbdev = NULL; -		printk(KERN_ERR "%s: couldn't find free device id\n", __func__); -		return -ENFILE; -	} - -	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); - -	if (!dvbdev){ -		mutex_unlock(&dvbdev_register_lock); -		return -ENOMEM; -	} - -	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); - -	if (!dvbdevfops){ -		kfree (dvbdev); -		mutex_unlock(&dvbdev_register_lock); -		return -ENOMEM; -	} - -	memcpy(dvbdev, template, sizeof(struct dvb_device)); -	dvbdev->type = type; -	dvbdev->id = id; -	dvbdev->adapter = adap; -	dvbdev->priv = priv; -	dvbdev->fops = dvbdevfops; -	init_waitqueue_head (&dvbdev->wait_queue); - -	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); -	dvbdevfops->owner = adap->module; - -	list_add_tail (&dvbdev->list_head, &adap->device_list); - -	down_write(&minor_rwsem); -#ifdef CONFIG_DVB_DYNAMIC_MINORS -	for (minor = 0; minor < MAX_DVB_MINORS; minor++) -		if (dvb_minors[minor] == NULL) -			break; - -	if (minor == MAX_DVB_MINORS) { -		kfree(dvbdevfops); -		kfree(dvbdev); -		mutex_unlock(&dvbdev_register_lock); -		return -EINVAL; -	} -#else -	minor = nums2minor(adap->num, type, id); -#endif - -	dvbdev->minor = minor; -	dvb_minors[minor] = dvbdev; -	up_write(&minor_rwsem); - -	mutex_unlock(&dvbdev_register_lock); - -	clsdev = device_create(dvb_class, adap->device, -			       MKDEV(DVB_MAJOR, minor), -			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); -	if (IS_ERR(clsdev)) { -		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", -		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); -		return PTR_ERR(clsdev); -	} - -	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", -		adap->num, dnames[type], id, minor, minor); - -	return 0; -} -EXPORT_SYMBOL(dvb_register_device); - - -void dvb_unregister_device(struct dvb_device *dvbdev) -{ -	if (!dvbdev) -		return; - -	down_write(&minor_rwsem); -	dvb_minors[dvbdev->minor] = NULL; -	up_write(&minor_rwsem); - -	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); - -	list_del (&dvbdev->list_head); -	kfree (dvbdev->fops); -	kfree (dvbdev); -} -EXPORT_SYMBOL(dvb_unregister_device); - -static int dvbdev_check_free_adapter_num(int num) -{ -	struct list_head *entry; -	list_for_each(entry, &dvb_adapter_list) { -		struct dvb_adapter *adap; -		adap = list_entry(entry, struct dvb_adapter, list_head); -		if (adap->num == num) -			return 0; -	} -	return 1; -} - -static int dvbdev_get_free_adapter_num (void) -{ -	int num = 0; - -	while (num < DVB_MAX_ADAPTERS) { -		if (dvbdev_check_free_adapter_num(num)) -			return num; -		num++; -	} - -	return -ENFILE; -} - - -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, -			 struct module *module, struct device *device, -			 short *adapter_nums) -{ -	int i, num; - -	mutex_lock(&dvbdev_register_lock); - -	for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { -		num = adapter_nums[i]; -		if (num >= 0  &&  num < DVB_MAX_ADAPTERS) { -		/* use the one the driver asked for */ -			if (dvbdev_check_free_adapter_num(num)) -				break; -		} else { -			num = dvbdev_get_free_adapter_num(); -			break; -		} -		num = -1; -	} - -	if (num < 0) { -		mutex_unlock(&dvbdev_register_lock); -		return -ENFILE; -	} - -	memset (adap, 0, sizeof(struct dvb_adapter)); -	INIT_LIST_HEAD (&adap->device_list); - -	printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); - -	adap->num = num; -	adap->name = name; -	adap->module = module; -	adap->device = device; -	adap->mfe_shared = 0; -	adap->mfe_dvbdev = NULL; -	mutex_init (&adap->mfe_lock); - -	list_add_tail (&adap->list_head, &dvb_adapter_list); - -	mutex_unlock(&dvbdev_register_lock); - -	return num; -} -EXPORT_SYMBOL(dvb_register_adapter); - - -int dvb_unregister_adapter(struct dvb_adapter *adap) -{ -	mutex_lock(&dvbdev_register_lock); -	list_del (&adap->list_head); -	mutex_unlock(&dvbdev_register_lock); -	return 0; -} -EXPORT_SYMBOL(dvb_unregister_adapter); - -/* if the miracle happens and "generic_usercopy()" is included into -   the kernel, then this can vanish. please don't make the mistake and -   define this as video_usercopy(). this will introduce a dependecy -   to the v4l "videodev.o" module, which is unnecessary for some -   cards (ie. the budget dvb-cards don't need the v4l module...) */ -int dvb_usercopy(struct file *file, -		     unsigned int cmd, unsigned long arg, -		     int (*func)(struct file *file, -		     unsigned int cmd, void *arg)) -{ -	char    sbuf[128]; -	void    *mbuf = NULL; -	void    *parg = NULL; -	int     err  = -EINVAL; - -	/*  Copy arguments into temp kernel buffer  */ -	switch (_IOC_DIR(cmd)) { -	case _IOC_NONE: -		/* -		 * For this command, the pointer is actually an integer -		 * argument. -		 */ -		parg = (void *) arg; -		break; -	case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -	case _IOC_WRITE: -	case (_IOC_WRITE | _IOC_READ): -		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -			parg = sbuf; -		} else { -			/* too big to allocate from stack */ -			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); -			if (NULL == mbuf) -				return -ENOMEM; -			parg = mbuf; -		} - -		err = -EFAULT; -		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -			goto out; -		break; -	} - -	/* call driver */ -	mutex_lock(&dvbdev_mutex); -	if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) -		err = -EINVAL; -	mutex_unlock(&dvbdev_mutex); - -	if (err < 0) -		goto out; - -	/*  Copy results into user buffer  */ -	switch (_IOC_DIR(cmd)) -	{ -	case _IOC_READ: -	case (_IOC_WRITE | _IOC_READ): -		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -			err = -EFAULT; -		break; -	} - -out: -	kfree(mbuf); -	return err; -} - -static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	struct dvb_device *dvbdev = dev_get_drvdata(dev); - -	add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); -	add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); -	add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); -	return 0; -} - -static char *dvb_devnode(struct device *dev, mode_t *mode) -{ -	struct dvb_device *dvbdev = dev_get_drvdata(dev); - -	return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", -		dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); -} - - -static int __init init_dvbdev(void) -{ -	int retval; -	dev_t dev = MKDEV(DVB_MAJOR, 0); - -	if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { -		printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); -		return retval; -	} - -	cdev_init(&dvb_device_cdev, &dvb_device_fops); -	if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { -		printk(KERN_ERR "dvb-core: unable register character device\n"); -		goto error; -	} - -	dvb_class = class_create(THIS_MODULE, "dvb"); -	if (IS_ERR(dvb_class)) { -		retval = PTR_ERR(dvb_class); -		goto error; -	} -	dvb_class->dev_uevent = dvb_uevent; -	dvb_class->devnode = dvb_devnode; -	return 0; - -error: -	cdev_del(&dvb_device_cdev); -	unregister_chrdev_region(dev, MAX_DVB_MINORS); -	return retval; -} - - -static void __exit exit_dvbdev(void) -{ -	class_destroy(dvb_class); -	cdev_del(&dvb_device_cdev); -	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); -} - -subsys_initcall(init_dvbdev); -module_exit(exit_dvbdev); - -MODULE_DESCRIPTION("DVB Core Driver"); -MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h deleted file mode 100644 index fcc6ae98745..00000000000 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ /dev/null @@ -1,172 +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. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#ifndef _DVBDEV_H_ -#define _DVBDEV_H_ - -#include <linux/types.h> -#include <linux/poll.h> -#include <linux/fs.h> -#include <linux/list.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 8 -#endif - -#define DVB_UNSET (-1) - -#define DVB_DEVICE_VIDEO      0 -#define DVB_DEVICE_AUDIO      1 -#define DVB_DEVICE_SEC        2 -#define DVB_DEVICE_FRONTEND   3 -#define DVB_DEVICE_DEMUX      4 -#define DVB_DEVICE_DVR        5 -#define DVB_DEVICE_CA         6 -#define DVB_DEVICE_NET        7 -#define DVB_DEVICE_OSD        8 - -#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 { -	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 */ - -	/* Allow the adapter/bridge driver to perform an action before and/or -	 * after the core handles an ioctl: -	 * -	 * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled. -	 * DVB_FE_IOCTL_POST indicates that the ioctl has been handled. -	 * -	 * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg: -	 * -	 * return 0 to allow dvb-core to handle the ioctl. -	 * return a positive int to prevent dvb-core from handling the ioctl, -	 * 	and exit without error. -	 * return a negative int to prevent dvb-core from handling the ioctl, -	 * 	and return that value as an error. -	 * -	 * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg: -	 * -	 * return 0 to allow the dvb_frontend ioctl handler to exit normally. -	 * return a negative int to cause the dvb_frontend ioctl handler to -	 * 	return that value as an error. -	 */ -#define DVB_FE_IOCTL_PRE 0 -#define DVB_FE_IOCTL_POST 1 -	int (*fe_ioctl_override)(struct dvb_frontend *fe, -				 unsigned int cmd, void *parg, -				 unsigned int stage); -}; - - -struct dvb_device { -	struct list_head list_head; -	const struct file_operations *fops; -	struct dvb_adapter *adapter; -	int 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); - -	void *priv; -}; - - -extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name, -				struct module *module, struct device *device, -				short *adapter_nums); -extern int dvb_unregister_adapter (struct dvb_adapter *adap); - -extern int dvb_register_device (struct dvb_adapter *adap, -				struct dvb_device **pdvbdev, -				const struct dvb_device *template, -				void *priv, -				int type); - -extern void dvb_unregister_device (struct dvb_device *dvbdev); - -extern int dvb_generic_open (struct inode *inode, struct file *file); -extern int dvb_generic_release (struct inode *inode, struct file *file); -extern long dvb_generic_ioctl (struct file *file, -			      unsigned int cmd, unsigned long arg); - -/* we don't mess with video_usercopy() any more, -we simply define out own dvb_usercopy(), which will hopefully become -generic_usercopy()  someday... */ - -extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, -			    int (*func)(struct file *file, unsigned int cmd, void *arg)); - -/** generic DVB attach function. */ -#ifdef CONFIG_MEDIA_ATTACH -#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; \ -}) - -#else -#define dvb_attach(FUNCTION, ARGS...) ({ \ -	FUNCTION(ARGS); \ -}) - -#endif - -#endif /* #ifndef _DVBDEV_H_ */  | 
