2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* dmxdev.c - DVB demultiplexer device
|
|
|
|
*
|
2006-03-11 02:22:31 +08:00
|
|
|
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
|
|
|
|
* for convergence integrated media GmbH
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-10-13 17:47:54 +08:00
|
|
|
#define pr_fmt(fmt) "dmxdev: " fmt
|
|
|
|
|
2009-10-04 20:11:37 +08:00
|
|
|
#include <linux/sched.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#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>
|
2016-12-25 03:46:01 +08:00
|
|
|
#include <linux/uaccess.h>
|
2017-12-29 02:03:51 +08:00
|
|
|
#include <media/dmxdev.h>
|
|
|
|
#include <media/dvb_vb2.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static int debug;
|
|
|
|
|
|
|
|
module_param(debug, int, 0644);
|
|
|
|
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
|
|
|
|
2016-10-13 17:47:54 +08:00
|
|
|
#define dprintk(fmt, arg...) do { \
|
|
|
|
if (debug) \
|
|
|
|
printk(KERN_DEBUG pr_fmt("%s: " fmt), \
|
|
|
|
__func__, ##arg); \
|
|
|
|
} while (0)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
|
|
|
|
const u8 *src, size_t len)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-03-15 04:31:01 +08:00
|
|
|
ssize_t free;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!len)
|
|
|
|
return 0;
|
|
|
|
if (!buf->data)
|
|
|
|
return 0;
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
free = dvb_ringbuffer_free(buf);
|
|
|
|
if (len > free) {
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("buffer overflow\n");
|
2006-03-15 04:31:01 +08:00
|
|
|
return -EOVERFLOW;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-03-15 04:31:01 +08:00
|
|
|
|
|
|
|
return dvb_ringbuffer_write(buf, src, len);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
|
2006-03-11 02:22:31 +08:00
|
|
|
int non_blocking, char __user *buf,
|
|
|
|
size_t count, loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-03-15 04:31:01 +08:00
|
|
|
size_t todo;
|
|
|
|
ssize_t avail;
|
|
|
|
ssize_t ret = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!src->data)
|
|
|
|
return 0;
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
if (src->error) {
|
|
|
|
ret = src->error;
|
|
|
|
dvb_ringbuffer_flush(src);
|
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
for (todo = count; todo > 0; todo -= ret) {
|
|
|
|
if (non_blocking && dvb_ringbuffer_empty(src)) {
|
|
|
|
ret = -EWOULDBLOCK;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
ret = wait_event_interruptible(src->queue,
|
|
|
|
!dvb_ringbuffer_empty(src) ||
|
|
|
|
(src->error != 0));
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
if (src->error) {
|
|
|
|
ret = src->error;
|
|
|
|
dvb_ringbuffer_flush(src);
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
avail = dvb_ringbuffer_avail(src);
|
2006-03-11 02:22:31 +08:00
|
|
|
if (avail > todo)
|
|
|
|
avail = todo;
|
2006-03-15 04:31:01 +08:00
|
|
|
|
2008-06-23 01:20:29 +08:00
|
|
|
ret = dvb_ringbuffer_read_user(src, buf, avail);
|
2006-03-15 04:31:01 +08:00
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
buf += ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-03-15 04:31:01 +08:00
|
|
|
|
|
|
|
return (count - todo) ? (count - todo) : ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct list_head *head, *pos;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
head = demux->get_frontends(demux);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!head)
|
|
|
|
return NULL;
|
|
|
|
list_for_each(pos, head)
|
2006-03-11 02:22:31 +08:00
|
|
|
if (DMX_FE_ENTRY(pos)->source == type)
|
2005-04-17 06:20:36 +08:00
|
|
|
return DMX_FE_ENTRY(pos);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct dmx_frontend *front;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
bool need_ringbuffer = false;
|
|
|
|
#else
|
|
|
|
const bool need_ringbuffer = true;
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("%s\n", __func__);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
2007-04-14 21:19:18 +08:00
|
|
|
if (dmxdev->exit) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
|
|
|
|
need_ringbuffer = true;
|
|
|
|
#else
|
2006-03-11 02:22:31 +08:00
|
|
|
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
|
|
|
if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
}
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
if (need_ringbuffer) {
|
2006-03-31 02:53:32 +08:00
|
|
|
void *mem;
|
2016-12-18 21:52:55 +08:00
|
|
|
|
2006-03-31 02:53:32 +08:00
|
|
|
if (!dvbdev->readers) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
mem = vmalloc(DVR_BUFFER_SIZE);
|
2006-03-15 04:31:01 +08:00
|
|
|
if (!mem) {
|
2006-03-11 02:22:31 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2006-03-15 04:31:01 +08:00
|
|
|
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
|
|
|
|
file->f_flags & O_NONBLOCK);
|
2006-03-31 02:53:32 +08:00
|
|
|
dvbdev->readers--;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
|
|
|
dmxdev->dvr_orig_fe = dmxdev->demux->frontend;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!dmxdev->demux->write) {
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
front = get_fe(dmxdev->demux, DMX_MEMORY_FE);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!front) {
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
dmxdev->demux->disconnect_frontend(dmxdev->demux);
|
|
|
|
dmxdev->demux->connect_frontend(dmxdev->demux, front);
|
|
|
|
}
|
2007-04-14 21:19:18 +08:00
|
|
|
dvbdev->users++;
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
bool need_ringbuffer = false;
|
|
|
|
#else
|
|
|
|
const bool need_ringbuffer = true;
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-03-10 17:21:25 +08:00
|
|
|
mutex_lock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
2005-04-17 06:20:36 +08:00
|
|
|
dmxdev->demux->disconnect_frontend(dmxdev->demux);
|
|
|
|
dmxdev->demux->connect_frontend(dmxdev->demux,
|
|
|
|
dmxdev->dvr_orig_fe);
|
|
|
|
}
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
|
|
|
|
need_ringbuffer = true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (need_ringbuffer) {
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
|
|
|
|
dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
|
|
|
|
dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
|
2006-03-31 02:53:32 +08:00
|
|
|
dvbdev->readers++;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (dmxdev->dvr_buffer.data) {
|
2006-03-11 02:22:31 +08:00
|
|
|
void *mem = dmxdev->dvr_buffer.data;
|
2016-12-18 21:52:55 +08:00
|
|
|
/*memory barrier*/
|
2005-04-17 06:20:36 +08:00
|
|
|
mb();
|
|
|
|
spin_lock_irq(&dmxdev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdev->dvr_buffer.data = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&dmxdev->lock);
|
|
|
|
vfree(mem);
|
|
|
|
}
|
|
|
|
}
|
2007-04-14 21:19:18 +08:00
|
|
|
/* TODO */
|
|
|
|
dvbdev->users--;
|
2010-07-19 02:34:18 +08:00
|
|
|
if (dvbdev->users == 1 && dmxdev->exit == 1) {
|
2007-04-14 21:19:18 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
wake_up(&dvbdev->wait_queue);
|
|
|
|
} else
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
|
2006-03-11 02:22:31 +08:00
|
|
|
size_t count, loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2005-04-17 06:20:36 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!dmxdev->demux->write)
|
|
|
|
return -EOPNOTSUPP;
|
2006-03-11 02:22:31 +08:00
|
|
|
if ((file->f_flags & O_ACCMODE) != O_WRONLY)
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EINVAL;
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
2007-04-14 21:19:18 +08:00
|
|
|
|
|
|
|
if (dmxdev->exit) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dmxdev->demux->write(dmxdev->demux, buf, count);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
|
2006-03-11 02:22:31 +08:00
|
|
|
loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-05-13 04:39:28 +08:00
|
|
|
if (dmxdev->exit)
|
2007-04-14 21:19:18 +08:00
|
|
|
return -ENODEV;
|
|
|
|
|
2009-05-13 04:39:28 +08:00
|
|
|
return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
|
|
|
|
file->f_flags & O_NONBLOCK,
|
|
|
|
buf, count, ppos);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2008-04-21 06:14:51 +08:00
|
|
|
static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
|
|
|
|
unsigned long size)
|
|
|
|
{
|
|
|
|
struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
|
|
|
|
void *newmem;
|
|
|
|
void *oldmem;
|
|
|
|
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("%s\n", __func__);
|
2008-04-21 06:14:51 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
|
|
|
|
*dmxdevfilter, int state)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
spin_lock_irq(&dmxdevfilter->dev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->state = state;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
|
|
|
|
unsigned long size)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-03-15 04:31:01 +08:00
|
|
|
struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
|
2008-04-21 06:14:51 +08:00
|
|
|
void *newmem;
|
|
|
|
void *oldmem;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (buf->size == size)
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
2008-04-21 06:14:51 +08:00
|
|
|
if (!size)
|
|
|
|
return -EINVAL;
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state >= DMXDEV_STATE_GO)
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EBUSY;
|
2008-04-21 06:14:51 +08:00
|
|
|
|
|
|
|
newmem = vmalloc(size);
|
|
|
|
if (!newmem)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
oldmem = buf->data;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_lock_irq(&dmxdevfilter->dev->lock);
|
2008-04-21 06:14:51 +08:00
|
|
|
buf->data = newmem;
|
2006-03-11 02:22:31 +08:00
|
|
|
buf->size = size;
|
2008-04-21 05:37:45 +08:00
|
|
|
|
|
|
|
/* reset and not flush in case the buffer shrinks */
|
|
|
|
dvb_ringbuffer_reset(buf);
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
|
|
|
|
2008-04-21 06:14:51 +08:00
|
|
|
vfree(oldmem);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-17 07:10:47 +08:00
|
|
|
static void dvb_dmxdev_filter_timeout(struct timer_list *t)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2017-10-17 07:10:47 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->buffer.error = -ETIMEDOUT;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_lock_irq(&dmxdevfilter->dev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
|
|
|
wake_up(&dmxdevfilter->buffer.queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
|
|
|
{
|
2006-03-11 02:22:31 +08:00
|
|
|
struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
del_timer(&dmxdevfilter->timer);
|
|
|
|
if (para->timeout) {
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->timer.expires =
|
|
|
|
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
|
2005-04-17 06:20:36 +08:00
|
|
|
add_timer(&dmxdevfilter->timer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
2006-03-11 02:22:31 +08:00
|
|
|
const u8 *buffer2, size_t buffer2_len,
|
2015-10-07 06:53:02 +08:00
|
|
|
struct dmx_section_filter *filter)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = filter->priv;
|
2005-04-17 06:20:36 +08:00
|
|
|
int ret;
|
|
|
|
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
|
|
|
|
dmxdevfilter->buffer.error) {
|
2005-04-17 06:20:36 +08:00
|
|
|
wake_up(&dmxdevfilter->buffer.queue);
|
|
|
|
return 0;
|
|
|
|
}
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_lock(&dmxdevfilter->dev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_unlock(&dmxdevfilter->dev->lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
del_timer(&dmxdevfilter->timer);
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("section callback %*ph\n", 6, buffer1);
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
|
|
|
|
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
|
|
|
|
buffer1, buffer1_len);
|
|
|
|
if (ret == buffer1_len)
|
|
|
|
ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
|
|
|
|
buffer2, buffer2_len);
|
|
|
|
} else {
|
|
|
|
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
|
|
|
|
buffer1, buffer1_len);
|
|
|
|
if (ret == buffer1_len) {
|
|
|
|
ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
|
|
|
|
buffer2, buffer2_len);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2013-06-06 08:26:23 +08:00
|
|
|
if (ret < 0)
|
2006-03-15 04:31:01 +08:00
|
|
|
dmxdevfilter->buffer.error = ret;
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
|
|
|
|
dmxdevfilter->state = DMXDEV_STATE_DONE;
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_unlock(&dmxdevfilter->dev->lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
wake_up(&dmxdevfilter->buffer.queue);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
2006-03-11 02:22:31 +08:00
|
|
|
const u8 *buffer2, size_t buffer2_len,
|
2015-10-07 06:53:02 +08:00
|
|
|
struct dmx_ts_feed *feed)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
2006-03-15 04:31:01 +08:00
|
|
|
struct dvb_ringbuffer *buffer;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
struct dvb_vb2_ctx *ctx;
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
int ret;
|
|
|
|
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_lock(&dmxdevfilter->dev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_unlock(&dmxdevfilter->dev->lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
|
|
|
|
dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
|
2006-03-11 02:22:31 +08:00
|
|
|
buffer = &dmxdevfilter->buffer;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
ctx = &dmxdevfilter->vb2_ctx;
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
} else {
|
2006-03-11 02:22:31 +08:00
|
|
|
buffer = &dmxdevfilter->dev->dvr_buffer;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dvb_vb2_is_streaming(ctx)) {
|
|
|
|
ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
|
|
|
|
if (ret == buffer1_len)
|
|
|
|
ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
|
|
|
|
} else {
|
|
|
|
if (buffer->error) {
|
|
|
|
spin_unlock(&dmxdevfilter->dev->lock);
|
|
|
|
wake_up(&buffer->queue);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
|
|
|
|
if (ret == buffer1_len)
|
|
|
|
ret = dvb_dmxdev_buffer_write(buffer,
|
|
|
|
buffer2, buffer2_len);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2013-06-06 08:26:23 +08:00
|
|
|
if (ret < 0)
|
2006-03-15 04:31:01 +08:00
|
|
|
buffer->error = ret;
|
V4L/DVB (10572): Revert commit dda06a8e4610757def753ee3a541a0b1a1feb36b
On Mon, 02 Feb 2009, Hartmut wrote:
This change set is wrong. The affected functions cannot be called from
an interrupt context, because they may process large buffers. In this
case, interrupts are disabled for a long time. Functions, like
dvb_dmx_swfilter_packets(), could be called only from a tasklet.
This change set does hide some strong design bugs in dm1105.c and
au0828-dvb.c.
Please revert this change set and do fix the bugs in dm1105.c and
au0828-dvb.c (and other files).
On Sun, 15 Feb 2009, Oliver Endriss wrote:
This changeset _must_ be reverted! It breaks all kernels since 2.6.27
for applications which use DVB and require a low interrupt latency.
It is a very bad idea to call the demuxer to process data buffers with
interrupts disabled!
On Mon, 16 Feb 2009, Trent Piepho wrote:
I agree, this is bad. The demuxer is far too much work to be done with
IRQs off. IMHO, even doing it under a spin-lock is excessive. It should
be a mutex. Drivers should use a work-queue to feed the demuxer.
Thank you for testing this changeset and discovering the issues on it.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Cc: Hartmut <e9hack@googlemail.com>
Cc: Oliver Endriss <o.endriss@gmx.de>
Cc: Andreas Oberritter <obi@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-02-17 02:27:44 +08:00
|
|
|
spin_unlock(&dmxdevfilter->dev->lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
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)
|
|
|
|
{
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmxdev_feed *feed;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
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:
|
2009-07-15 07:28:50 +08:00
|
|
|
list_for_each_entry(feed, &dmxdevfilter->feed.ts, next)
|
|
|
|
feed->ts->stop_filtering(feed->ts);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* start feed associated with the specified filter */
|
|
|
|
static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
|
|
|
|
{
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmxdev_feed *feed;
|
|
|
|
int ret;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
switch (filter->type) {
|
|
|
|
case DMXDEV_TYPE_SEC:
|
|
|
|
return filter->feed.sec->start_filtering(filter->feed.sec);
|
|
|
|
case DMXDEV_TYPE_PES:
|
2009-07-15 07:28:50 +08:00
|
|
|
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;
|
2005-04-17 06:20:36 +08:00
|
|
|
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;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
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) {
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_feed_start(&dmxdev->filter[i]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
filter->dev->demux->release_section_feed(dmxdev->demux,
|
|
|
|
filter->feed.sec);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
|
|
|
|
{
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmxdev_feed *feed;
|
|
|
|
struct dmx_demux *demux;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state < DMXDEV_STATE_GO)
|
2005-04-17 06:20:36 +08:00
|
|
|
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->
|
2006-03-11 02:22:31 +08:00
|
|
|
release_filter(dmxdevfilter->feed.sec,
|
|
|
|
dmxdevfilter->filter.sec);
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_feed_restart(dmxdevfilter);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->feed.sec = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case DMXDEV_TYPE_PES:
|
|
|
|
dvb_dmxdev_feed_stop(dmxdevfilter);
|
2009-07-15 07:28:50 +08:00
|
|
|
demux = dmxdevfilter->dev->demux;
|
|
|
|
list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
|
|
|
|
demux->release_ts_feed(demux, feed->ts);
|
|
|
|
feed->ts = NULL;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
default:
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2006-03-15 04:31:01 +08:00
|
|
|
|
|
|
|
dvb_ringbuffer_flush(&dmxdevfilter->buffer);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
|
|
|
|
{
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state < DMXDEV_STATE_SET)
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
if (dmxdevfilter->type == DMXDEV_TYPE_PES)
|
|
|
|
dvb_dmxdev_delete_pids(dmxdevfilter);
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->type = DMXDEV_TYPE_NONE;
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
|
|
|
|
struct dmxdev_filter *filter,
|
|
|
|
struct dmxdev_feed *feed)
|
|
|
|
{
|
2016-12-25 19:30:41 +08:00
|
|
|
ktime_t timeout = 0;
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmx_pes_filter_params *para = &filter->params.pes;
|
2017-09-01 18:09:14 +08:00
|
|
|
enum dmx_output otype;
|
2009-07-15 07:28:50 +08:00
|
|
|
int ret;
|
|
|
|
int ts_type;
|
2013-04-05 00:25:30 +08:00
|
|
|
enum dmx_ts_pes ts_pes;
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmx_ts_feed *tsfeed;
|
|
|
|
|
|
|
|
feed->ts = NULL;
|
|
|
|
otype = para->output;
|
|
|
|
|
2010-12-27 22:41:14 +08:00
|
|
|
ts_pes = para->pes_type;
|
2009-07-15 07:28:50 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-10-13 18:14:38 +08:00
|
|
|
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout);
|
2009-07-15 07:28:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
|
|
|
|
{
|
|
|
|
struct dmxdev *dmxdev = filter->dev;
|
2009-07-15 07:28:50 +08:00
|
|
|
struct dmxdev_feed *feed;
|
2005-04-17 06:20:36 +08:00
|
|
|
void *mem;
|
|
|
|
int ret, i;
|
|
|
|
|
|
|
|
if (filter->state < DMXDEV_STATE_SET)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (filter->state >= DMXDEV_STATE_GO)
|
|
|
|
dvb_dmxdev_filter_stop(filter);
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
if (!filter->buffer.data) {
|
2005-04-17 06:20:36 +08:00
|
|
|
mem = vmalloc(filter->buffer.size);
|
2006-03-15 04:31:01 +08:00
|
|
|
if (!mem)
|
|
|
|
return -ENOMEM;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_lock_irq(&filter->dev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
filter->buffer.data = mem;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&filter->dev->lock);
|
|
|
|
}
|
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
dvb_ringbuffer_flush(&filter->buffer);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
switch (filter->type) {
|
|
|
|
case DMXDEV_TYPE_SEC:
|
|
|
|
{
|
2006-03-11 02:22:31 +08:00
|
|
|
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;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* find active filter/feed with same PID */
|
2006-03-11 02:22:31 +08:00
|
|
|
for (i = 0; i < dmxdev->filternum; i++) {
|
2005-04-17 06:20:36 +08:00
|
|
|
if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
|
2006-03-11 02:21:28 +08:00
|
|
|
dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
|
|
|
|
dmxdev->filter[i].params.sec.pid == para->pid) {
|
2005-04-17 06:20:36 +08:00
|
|
|
*secfeed = dmxdev->filter[i].feed.sec;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if no feed found, try to allocate new one */
|
|
|
|
if (!*secfeed) {
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
|
|
|
|
secfeed,
|
|
|
|
dvb_dmxdev_section_callback);
|
|
|
|
if (ret < 0) {
|
2016-10-13 17:47:54 +08:00
|
|
|
pr_err("DVB (%s): could not alloc feed\n",
|
2008-04-09 10:20:00 +08:00
|
|
|
__func__);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-13 18:14:38 +08:00
|
|
|
ret = (*secfeed)->set(*secfeed, para->pid,
|
2006-03-11 02:22:31 +08:00
|
|
|
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
|
|
|
|
if (ret < 0) {
|
2016-10-13 17:47:54 +08:00
|
|
|
pr_err("DVB (%s): could not set feed\n",
|
2008-04-09 10:20:00 +08:00
|
|
|
__func__);
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_feed_restart(filter);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dvb_dmxdev_feed_stop(filter);
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dvb_dmxdev_feed_restart(filter);
|
|
|
|
filter->feed.sec->start_filtering(*secfeed);
|
2006-03-11 02:22:31 +08:00
|
|
|
dprintk("could not get filter\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*secfilter)->priv = filter;
|
|
|
|
|
|
|
|
memcpy(&((*secfilter)->filter_value[3]),
|
2006-03-11 02:22:31 +08:00
|
|
|
&(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
memcpy(&(*secfilter)->filter_mask[3],
|
2006-03-11 02:22:31 +08:00
|
|
|
¶->filter.mask[1], DMX_FILTER_SIZE - 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
memcpy(&(*secfilter)->filter_mode[3],
|
2006-03-11 02:22:31 +08:00
|
|
|
¶->filter.mode[1], DMX_FILTER_SIZE - 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
(*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;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
filter->todo = 0;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = filter->feed.sec->start_filtering(filter->feed.sec);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
dvb_dmxdev_filter_timer(filter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DMXDEV_TYPE_PES:
|
2009-07-15 07:28:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2005-07-08 08:57:38 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
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)
|
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2005-04-17 06:20:36 +08:00
|
|
|
int i;
|
|
|
|
struct dmxdev_filter *dmxdevfilter;
|
|
|
|
|
|
|
|
if (!dmxdev->filter)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
for (i = 0; i < dmxdev->filternum; i++)
|
|
|
|
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (i == dmxdev->filternum) {
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EMFILE;
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter = &dmxdev->filter[i];
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_init(&dmxdevfilter->mutex);
|
2006-03-11 02:22:31 +08:00
|
|
|
file->private_data = dmxdevfilter;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
|
|
|
|
file->f_flags & O_NONBLOCK);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->type = DMXDEV_TYPE_NONE;
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
|
2017-10-17 07:10:47 +08:00
|
|
|
timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-04-14 21:19:18 +08:00
|
|
|
dvbdev->users++;
|
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
|
|
|
|
struct dmxdev_filter *dmxdevfilter)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-03-10 17:21:25 +08:00
|
|
|
mutex_lock(&dmxdev->mutex);
|
|
|
|
mutex_lock(&dmxdevfilter->mutex);
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
|
|
|
|
dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx);
|
|
|
|
dvb_vb2_release(&dmxdevfilter->vb2_ctx);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dvb_dmxdev_filter_stop(dmxdevfilter);
|
|
|
|
dvb_dmxdev_filter_reset(dmxdevfilter);
|
|
|
|
|
|
|
|
if (dmxdevfilter->buffer.data) {
|
2006-03-11 02:22:31 +08:00
|
|
|
void *mem = dmxdevfilter->buffer.data;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
spin_lock_irq(&dmxdev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->buffer.data = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irq(&dmxdev->lock);
|
|
|
|
vfree(mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
|
|
|
|
wake_up(&dmxdevfilter->buffer.queue);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-01 18:09:14 +08:00
|
|
|
static inline void invert_mode(struct dmx_filter *filter)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
for (i = 0; i < DMX_FILTER_SIZE; i++)
|
|
|
|
filter->mode[i] ^= 0xff;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
|
2006-03-11 02:22:31 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter,
|
|
|
|
struct dmx_sct_filter_params *params)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("%s: PID=0x%04x, flags=%02x, timeout=%d\n",
|
2013-03-02 02:20:25 +08:00
|
|
|
__func__, params->pid, params->flags, params->timeout);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dvb_dmxdev_filter_stop(dmxdevfilter);
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->type = DMXDEV_TYPE_SEC;
|
2005-04-17 06:20:36 +08:00
|
|
|
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);
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (params->flags & DMX_IMMEDIATE_START)
|
2005-04-17 06:20:36 +08:00
|
|
|
return dvb_dmxdev_filter_start(dmxdevfilter);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
|
2006-03-11 02:22:31 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter,
|
|
|
|
struct dmx_pes_filter_params *params)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2009-07-15 07:28:50 +08:00
|
|
|
int ret;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_dmxdev_filter_stop(dmxdevfilter);
|
2009-07-15 07:28:50 +08:00
|
|
|
dvb_dmxdev_filter_reset(dmxdevfilter);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-12-18 21:52:55 +08:00
|
|
|
if ((unsigned int)params->pes_type > DMX_PES_OTHER)
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdevfilter->type = DMXDEV_TYPE_PES;
|
|
|
|
memcpy(&dmxdevfilter->params, params,
|
|
|
|
sizeof(struct dmx_pes_filter_params));
|
2010-02-07 20:49:58 +08:00
|
|
|
INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter,
|
|
|
|
dmxdevfilter->params.pes.pid);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (params->flags & DMX_IMMEDIATE_START)
|
2005-04-17 06:20:36 +08:00
|
|
|
return dvb_dmxdev_filter_start(dmxdevfilter);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
|
2006-03-11 02:22:31 +08:00
|
|
|
struct file *file, char __user *buf,
|
|
|
|
size_t count, loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int result, hcount;
|
2006-03-11 02:22:31 +08:00
|
|
|
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;
|
2005-04-17 06:20:36 +08:00
|
|
|
return result;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EFAULT;
|
2006-03-11 02:22:31 +08:00
|
|
|
buf += result;
|
|
|
|
done = result;
|
|
|
|
count -= result;
|
|
|
|
dfil->todo -= result;
|
|
|
|
if (dfil->todo > -3)
|
2005-04-17 06:20:36 +08:00
|
|
|
return done;
|
2006-03-11 02:22:31 +08:00
|
|
|
dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!count)
|
|
|
|
return done;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
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)
|
2005-04-17 06:20:36 +08:00
|
|
|
return result;
|
2006-03-11 02:22:31 +08:00
|
|
|
dfil->todo -= result;
|
|
|
|
return (result + done);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2006-03-11 02:22:31 +08:00
|
|
|
dvb_demux_read(struct file *file, char __user *buf, size_t count,
|
|
|
|
loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-03-11 02:22:31 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
|
|
|
int ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
|
|
|
|
ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
|
2005-04-17 06:20:36 +08:00
|
|
|
else
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
|
|
|
|
file->f_flags & O_NONBLOCK,
|
|
|
|
buf, count, ppos);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-04-27 06:24:00 +08:00
|
|
|
static int dvb_demux_do_ioctl(struct file *file,
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned int cmd, void *parg)
|
|
|
|
{
|
2005-07-08 08:57:39 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
2006-03-11 02:22:31 +08:00
|
|
|
struct dmxdev *dmxdev = dmxdevfilter->dev;
|
|
|
|
unsigned long arg = (unsigned long)parg;
|
|
|
|
int ret = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case DMX_START:
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
if (dmxdevfilter->state < DMXDEV_STATE_SET)
|
2005-04-17 06:20:36 +08:00
|
|
|
ret = -EINVAL;
|
|
|
|
else
|
|
|
|
ret = dvb_dmxdev_filter_start(dmxdevfilter);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_STOP:
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dvb_dmxdev_filter_stop(dmxdevfilter);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_SET_FILTER:
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_SET_PES_FILTER:
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_SET_BUFFER_SIZE:
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_GET_PES_PIDS:
|
|
|
|
if (!dmxdev->demux->get_pes_pids) {
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = -EINVAL;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_GET_STC:
|
|
|
|
if (!dmxdev->demux->get_stc) {
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = -EINVAL;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ret = dmxdev->demux->get_stc(dmxdev->demux,
|
2006-03-11 02:22:31 +08:00
|
|
|
((struct dmx_stc *)parg)->num,
|
|
|
|
&((struct dmx_stc *)parg)->stc,
|
|
|
|
&((struct dmx_stc *)parg)->base);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
2009-07-15 07:28:50 +08:00
|
|
|
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;
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
case DMX_REQBUFS:
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg);
|
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_QUERYBUF:
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg);
|
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_EXPBUF:
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg);
|
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_QBUF:
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg);
|
|
|
|
if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
|
|
|
|
ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx);
|
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_DQBUF:
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
|
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
break;
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-04-27 06:24:00 +08:00
|
|
|
static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
|
|
|
|
unsigned long arg)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2010-09-12 01:56:45 +08:00
|
|
|
return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 15:02:56 +08:00
|
|
|
static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-07-08 08:57:39 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
2017-07-03 15:02:56 +08:00
|
|
|
__poll_t mask = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2014-09-04 01:32:26 +08:00
|
|
|
if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
|
2018-02-12 06:34:03 +08:00
|
|
|
return EPOLLERR;
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
|
|
|
|
return dvb_vb2_poll(&dmxdevfilter->vb2_ctx, file, wait);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
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)
|
2018-02-12 06:34:03 +08:00
|
|
|
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
|
2018-02-12 06:34:03 +08:00
|
|
|
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-07-08 08:57:39 +08:00
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct dmxdev *dmxdev = dmxdevfilter->dev;
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
|
|
|
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
}
|
|
|
|
ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
mutex_unlock(&dmxdevfilter->mutex);
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
|
|
|
|
static int dvb_demux_release(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
struct dmxdev_filter *dmxdevfilter = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dmxdevfilter->dev;
|
2007-04-14 21:19:18 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
|
|
|
|
|
|
|
|
mutex_lock(&dmxdev->mutex);
|
|
|
|
dmxdev->dvbdev->users--;
|
2016-12-18 21:52:55 +08:00
|
|
|
if (dmxdev->dvbdev->users == 1 && dmxdev->exit == 1) {
|
2007-04-14 21:19:18 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
wake_up(&dmxdev->dvbdev->wait_queue);
|
|
|
|
} else
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
|
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2009-01-11 17:12:43 +08:00
|
|
|
static const struct file_operations dvb_demux_fops = {
|
2006-03-11 02:22:31 +08:00
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.read = dvb_demux_read,
|
2010-04-27 06:24:00 +08:00
|
|
|
.unlocked_ioctl = dvb_demux_ioctl,
|
2006-03-11 02:22:31 +08:00
|
|
|
.open = dvb_demux_open,
|
|
|
|
.release = dvb_demux_release,
|
|
|
|
.poll = dvb_demux_poll,
|
llseek: automatically add .llseek fop
All file_operations should get a .llseek operation so we can make
nonseekable_open the default for future file operations without a
.llseek pointer.
The three cases that we can automatically detect are no_llseek, seq_lseek
and default_llseek. For cases where we can we can automatically prove that
the file offset is always ignored, we use noop_llseek, which maintains
the current behavior of not returning an error from a seek.
New drivers should normally not use noop_llseek but instead use no_llseek
and call nonseekable_open at open time. Existing drivers can be converted
to do the same when the maintainer knows for certain that no user code
relies on calling seek on the device file.
The generated code is often incorrectly indented and right now contains
comments that clarify for each added line why a specific variant was
chosen. In the version that gets submitted upstream, the comments will
be gone and I will manually fix the indentation, because there does not
seem to be a way to do that using coccinelle.
Some amount of new code is currently sitting in linux-next that should get
the same modifications, which I will do at the end of the merge window.
Many thanks to Julia Lawall for helping me learn to write a semantic
patch that does all this.
===== begin semantic patch =====
// This adds an llseek= method to all file operations,
// as a preparation for making no_llseek the default.
//
// The rules are
// - use no_llseek explicitly if we do nonseekable_open
// - use seq_lseek for sequential files
// - use default_llseek if we know we access f_pos
// - use noop_llseek if we know we don't access f_pos,
// but we still want to allow users to call lseek
//
@ open1 exists @
identifier nested_open;
@@
nested_open(...)
{
<+...
nonseekable_open(...)
...+>
}
@ open exists@
identifier open_f;
identifier i, f;
identifier open1.nested_open;
@@
int open_f(struct inode *i, struct file *f)
{
<+...
(
nonseekable_open(...)
|
nested_open(...)
)
...+>
}
@ read disable optional_qualifier exists @
identifier read_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
expression E;
identifier func;
@@
ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
{
<+...
(
*off = E
|
*off += E
|
func(..., off, ...)
|
E = *off
)
...+>
}
@ read_no_fpos disable optional_qualifier exists @
identifier read_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
@@
ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
{
... when != off
}
@ write @
identifier write_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
expression E;
identifier func;
@@
ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
{
<+...
(
*off = E
|
*off += E
|
func(..., off, ...)
|
E = *off
)
...+>
}
@ write_no_fpos @
identifier write_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
@@
ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
{
... when != off
}
@ fops0 @
identifier fops;
@@
struct file_operations fops = {
...
};
@ has_llseek depends on fops0 @
identifier fops0.fops;
identifier llseek_f;
@@
struct file_operations fops = {
...
.llseek = llseek_f,
...
};
@ has_read depends on fops0 @
identifier fops0.fops;
identifier read_f;
@@
struct file_operations fops = {
...
.read = read_f,
...
};
@ has_write depends on fops0 @
identifier fops0.fops;
identifier write_f;
@@
struct file_operations fops = {
...
.write = write_f,
...
};
@ has_open depends on fops0 @
identifier fops0.fops;
identifier open_f;
@@
struct file_operations fops = {
...
.open = open_f,
...
};
// use no_llseek if we call nonseekable_open
////////////////////////////////////////////
@ nonseekable1 depends on !has_llseek && has_open @
identifier fops0.fops;
identifier nso ~= "nonseekable_open";
@@
struct file_operations fops = {
... .open = nso, ...
+.llseek = no_llseek, /* nonseekable */
};
@ nonseekable2 depends on !has_llseek @
identifier fops0.fops;
identifier open.open_f;
@@
struct file_operations fops = {
... .open = open_f, ...
+.llseek = no_llseek, /* open uses nonseekable */
};
// use seq_lseek for sequential files
/////////////////////////////////////
@ seq depends on !has_llseek @
identifier fops0.fops;
identifier sr ~= "seq_read";
@@
struct file_operations fops = {
... .read = sr, ...
+.llseek = seq_lseek, /* we have seq_read */
};
// use default_llseek if there is a readdir
///////////////////////////////////////////
@ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier readdir_e;
@@
// any other fop is used that changes pos
struct file_operations fops = {
... .readdir = readdir_e, ...
+.llseek = default_llseek, /* readdir is present */
};
// use default_llseek if at least one of read/write touches f_pos
/////////////////////////////////////////////////////////////////
@ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read.read_f;
@@
// read fops use offset
struct file_operations fops = {
... .read = read_f, ...
+.llseek = default_llseek, /* read accesses f_pos */
};
@ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier write.write_f;
@@
// write fops use offset
struct file_operations fops = {
... .write = write_f, ...
+ .llseek = default_llseek, /* write accesses f_pos */
};
// Use noop_llseek if neither read nor write accesses f_pos
///////////////////////////////////////////////////////////
@ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read_no_fpos.read_f;
identifier write_no_fpos.write_f;
@@
// write fops use offset
struct file_operations fops = {
...
.write = write_f,
.read = read_f,
...
+.llseek = noop_llseek, /* read and write both use no f_pos */
};
@ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier write_no_fpos.write_f;
@@
struct file_operations fops = {
... .write = write_f, ...
+.llseek = noop_llseek, /* write uses no f_pos */
};
@ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read_no_fpos.read_f;
@@
struct file_operations fops = {
... .read = read_f, ...
+.llseek = noop_llseek, /* read uses no f_pos */
};
@ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
@@
struct file_operations fops = {
...
+.llseek = noop_llseek, /* no read or write fn */
};
===== End semantic patch =====
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Julia Lawall <julia@diku.dk>
Cc: Christoph Hellwig <hch@infradead.org>
2010-08-16 00:52:59 +08:00
|
|
|
.llseek = default_llseek,
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
.mmap = dvb_demux_mmap,
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2015-01-03 09:28:53 +08:00
|
|
|
static const struct dvb_device dvbdev_demux = {
|
2006-03-11 02:22:31 +08:00
|
|
|
.priv = NULL,
|
|
|
|
.users = 1,
|
|
|
|
.writers = 1,
|
2015-01-03 09:28:53 +08:00
|
|
|
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
2015-02-18 23:09:27 +08:00
|
|
|
.name = "dvb-demux",
|
2015-01-03 09:28:53 +08:00
|
|
|
#endif
|
2006-03-11 02:22:31 +08:00
|
|
|
.fops = &dvb_demux_fops
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2010-04-27 06:24:00 +08:00
|
|
|
static int dvb_dvr_do_ioctl(struct file *file,
|
2006-03-11 02:22:31 +08:00
|
|
|
unsigned int cmd, void *parg)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2008-04-21 06:14:51 +08:00
|
|
|
unsigned long arg = (unsigned long)parg;
|
2006-03-11 02:22:31 +08:00
|
|
|
int ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case DMX_SET_BUFFER_SIZE:
|
2008-04-21 06:14:51 +08:00
|
|
|
ret = dvb_dvr_set_buffer_size(dmxdev, arg);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
case DMX_REQBUFS:
|
|
|
|
ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_QUERYBUF:
|
|
|
|
ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_EXPBUF:
|
|
|
|
ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_QBUF:
|
|
|
|
ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg);
|
|
|
|
if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
|
|
|
|
ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_DQBUF:
|
|
|
|
ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
|
|
|
|
break;
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
2006-03-11 02:22:31 +08:00
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_unlock(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-04-27 06:24:00 +08:00
|
|
|
static long dvb_dvr_ioctl(struct file *file,
|
2006-03-11 02:22:31 +08:00
|
|
|
unsigned int cmd, unsigned long arg)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2010-09-12 01:56:45 +08:00
|
|
|
return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 15:02:56 +08:00
|
|
|
static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-05-17 12:54:24 +08:00
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
2017-07-03 15:02:56 +08:00
|
|
|
__poll_t mask = 0;
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
bool need_ringbuffer = false;
|
|
|
|
#else
|
|
|
|
const bool need_ringbuffer = true;
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-10-13 17:47:54 +08:00
|
|
|
dprintk("%s\n", __func__);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2014-08-21 10:05:40 +08:00
|
|
|
if (dmxdev->exit)
|
2018-02-12 06:34:03 +08:00
|
|
|
return EPOLLERR;
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
|
|
|
|
return dvb_vb2_poll(&dmxdev->dvr_vb2_ctx, file, wait);
|
2014-08-21 10:05:40 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifndef DVB_MMAP
|
|
|
|
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
|
|
|
|
need_ringbuffer = true;
|
|
|
|
#endif
|
|
|
|
if (need_ringbuffer) {
|
2005-04-17 06:20:36 +08:00
|
|
|
if (dmxdev->dvr_buffer.error)
|
2018-02-12 06:34:03 +08:00
|
|
|
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
|
2018-02-12 06:34:03 +08:00
|
|
|
mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else
|
2018-02-12 06:34:03 +08:00
|
|
|
mask |= (EPOLLOUT | EPOLLWRNORM | EPOLLPRI);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
|
|
|
|
{
|
|
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
|
|
struct dmxdev *dmxdev = dvbdev->priv;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (dmxdev->exit)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
|
|
|
|
ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma);
|
|
|
|
mutex_unlock(&dmxdev->mutex);
|
|
|
|
return ret;
|
|
|
|
}
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
|
2009-10-02 06:43:56 +08:00
|
|
|
static const struct file_operations dvb_dvr_fops = {
|
2006-03-11 02:22:31 +08:00
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.read = dvb_dvr_read,
|
|
|
|
.write = dvb_dvr_write,
|
2010-04-27 06:24:00 +08:00
|
|
|
.unlocked_ioctl = dvb_dvr_ioctl,
|
2006-03-11 02:22:31 +08:00
|
|
|
.open = dvb_dvr_open,
|
|
|
|
.release = dvb_dvr_release,
|
|
|
|
.poll = dvb_dvr_poll,
|
llseek: automatically add .llseek fop
All file_operations should get a .llseek operation so we can make
nonseekable_open the default for future file operations without a
.llseek pointer.
The three cases that we can automatically detect are no_llseek, seq_lseek
and default_llseek. For cases where we can we can automatically prove that
the file offset is always ignored, we use noop_llseek, which maintains
the current behavior of not returning an error from a seek.
New drivers should normally not use noop_llseek but instead use no_llseek
and call nonseekable_open at open time. Existing drivers can be converted
to do the same when the maintainer knows for certain that no user code
relies on calling seek on the device file.
The generated code is often incorrectly indented and right now contains
comments that clarify for each added line why a specific variant was
chosen. In the version that gets submitted upstream, the comments will
be gone and I will manually fix the indentation, because there does not
seem to be a way to do that using coccinelle.
Some amount of new code is currently sitting in linux-next that should get
the same modifications, which I will do at the end of the merge window.
Many thanks to Julia Lawall for helping me learn to write a semantic
patch that does all this.
===== begin semantic patch =====
// This adds an llseek= method to all file operations,
// as a preparation for making no_llseek the default.
//
// The rules are
// - use no_llseek explicitly if we do nonseekable_open
// - use seq_lseek for sequential files
// - use default_llseek if we know we access f_pos
// - use noop_llseek if we know we don't access f_pos,
// but we still want to allow users to call lseek
//
@ open1 exists @
identifier nested_open;
@@
nested_open(...)
{
<+...
nonseekable_open(...)
...+>
}
@ open exists@
identifier open_f;
identifier i, f;
identifier open1.nested_open;
@@
int open_f(struct inode *i, struct file *f)
{
<+...
(
nonseekable_open(...)
|
nested_open(...)
)
...+>
}
@ read disable optional_qualifier exists @
identifier read_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
expression E;
identifier func;
@@
ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
{
<+...
(
*off = E
|
*off += E
|
func(..., off, ...)
|
E = *off
)
...+>
}
@ read_no_fpos disable optional_qualifier exists @
identifier read_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
@@
ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
{
... when != off
}
@ write @
identifier write_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
expression E;
identifier func;
@@
ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
{
<+...
(
*off = E
|
*off += E
|
func(..., off, ...)
|
E = *off
)
...+>
}
@ write_no_fpos @
identifier write_f;
identifier f, p, s, off;
type ssize_t, size_t, loff_t;
@@
ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
{
... when != off
}
@ fops0 @
identifier fops;
@@
struct file_operations fops = {
...
};
@ has_llseek depends on fops0 @
identifier fops0.fops;
identifier llseek_f;
@@
struct file_operations fops = {
...
.llseek = llseek_f,
...
};
@ has_read depends on fops0 @
identifier fops0.fops;
identifier read_f;
@@
struct file_operations fops = {
...
.read = read_f,
...
};
@ has_write depends on fops0 @
identifier fops0.fops;
identifier write_f;
@@
struct file_operations fops = {
...
.write = write_f,
...
};
@ has_open depends on fops0 @
identifier fops0.fops;
identifier open_f;
@@
struct file_operations fops = {
...
.open = open_f,
...
};
// use no_llseek if we call nonseekable_open
////////////////////////////////////////////
@ nonseekable1 depends on !has_llseek && has_open @
identifier fops0.fops;
identifier nso ~= "nonseekable_open";
@@
struct file_operations fops = {
... .open = nso, ...
+.llseek = no_llseek, /* nonseekable */
};
@ nonseekable2 depends on !has_llseek @
identifier fops0.fops;
identifier open.open_f;
@@
struct file_operations fops = {
... .open = open_f, ...
+.llseek = no_llseek, /* open uses nonseekable */
};
// use seq_lseek for sequential files
/////////////////////////////////////
@ seq depends on !has_llseek @
identifier fops0.fops;
identifier sr ~= "seq_read";
@@
struct file_operations fops = {
... .read = sr, ...
+.llseek = seq_lseek, /* we have seq_read */
};
// use default_llseek if there is a readdir
///////////////////////////////////////////
@ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier readdir_e;
@@
// any other fop is used that changes pos
struct file_operations fops = {
... .readdir = readdir_e, ...
+.llseek = default_llseek, /* readdir is present */
};
// use default_llseek if at least one of read/write touches f_pos
/////////////////////////////////////////////////////////////////
@ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read.read_f;
@@
// read fops use offset
struct file_operations fops = {
... .read = read_f, ...
+.llseek = default_llseek, /* read accesses f_pos */
};
@ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier write.write_f;
@@
// write fops use offset
struct file_operations fops = {
... .write = write_f, ...
+ .llseek = default_llseek, /* write accesses f_pos */
};
// Use noop_llseek if neither read nor write accesses f_pos
///////////////////////////////////////////////////////////
@ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read_no_fpos.read_f;
identifier write_no_fpos.write_f;
@@
// write fops use offset
struct file_operations fops = {
...
.write = write_f,
.read = read_f,
...
+.llseek = noop_llseek, /* read and write both use no f_pos */
};
@ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier write_no_fpos.write_f;
@@
struct file_operations fops = {
... .write = write_f, ...
+.llseek = noop_llseek, /* write uses no f_pos */
};
@ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
identifier read_no_fpos.read_f;
@@
struct file_operations fops = {
... .read = read_f, ...
+.llseek = noop_llseek, /* read uses no f_pos */
};
@ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
identifier fops0.fops;
@@
struct file_operations fops = {
...
+.llseek = noop_llseek, /* no read or write fn */
};
===== End semantic patch =====
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Julia Lawall <julia@diku.dk>
Cc: Christoph Hellwig <hch@infradead.org>
2010-08-16 00:52:59 +08:00
|
|
|
.llseek = default_llseek,
|
2017-12-28 22:24:20 +08:00
|
|
|
#ifdef DVB_MMAP
|
media: videobuf2: Add new uAPI for DVB streaming I/O
Adds a new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2, using those new ioctls:
- DMX_REQBUFS: Request kernel to allocate buffers which count and size
are dedicated by user.
- DMX_QUERYBUF: Get the buffer information like a memory offset which
will mmap() and be shared with user-space.
- DMX_EXPBUF: Just for testing whether buffer-exporting success or not.
- DMX_QBUF: Pass the buffer to kernel-space.
- DMX_DQBUF: Get back the buffer which may contain TS data.
Originally developed by: Junghak Sung <jh1009.sung@samsung.com>, as
seen at:
https://patchwork.linuxtv.org/patch/31613/
https://patchwork.kernel.org/patch/7334301/
The original patch was written before merging VB2-core functionalities
upstream. When such series was added, several adjustments were made,
fixing some issues with V4L2, causing the original patch to be
non-trivially rebased.
After rebased, a few bugs in the patch were fixed. The patch was
also enhanced it and polling functionality got added.
The main changes over the original patch are:
dvb_vb2_fill_buffer():
- Set the size of the outgoing buffer after while loop using
vb2_set_plane_payload;
- Added NULL check for source buffer as per normal convention
of demux driver, this is called twice, first time with valid
buffer second time with NULL pointer, if its not handled,
it will result in crash
- Restricted spinlock for only list_* operations
dvb_vb2_init():
- Restricted q->io_modes to only VB2_MMAP as its the only
supported mode
dvb_vb2_release():
- Replaced the && in if condiion with &, because otherwise
it was always getting satisfied.
dvb_vb2_stream_off():
- Added list_del code for enqueud buffers upon stream off
dvb_vb2_poll():
- Added this new function in order to support polling
dvb_demux_poll() and dvb_dvr_poll()
- dvb_vb2_poll() is now called from these functions
- Ported this patch and latest videobuf2 to lower kernel versions and
tested auto scan.
Co-developed-by: Junghak Sung <jh1009.sung@samsung.com>
[mchehab@s-opensource.com: checkpatch fixes]
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Satendra Singh Thakur <satendra.t@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-12-19 11:35:53 +08:00
|
|
|
.mmap = dvb_dvr_mmap,
|
2017-12-28 22:24:20 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2015-01-03 09:28:53 +08:00
|
|
|
static const struct dvb_device dvbdev_dvr = {
|
2006-03-11 02:22:31 +08:00
|
|
|
.priv = NULL,
|
2006-03-31 02:53:32 +08:00
|
|
|
.readers = 1,
|
2007-04-14 21:19:18 +08:00
|
|
|
.users = 1,
|
2015-01-03 09:28:53 +08:00
|
|
|
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
2015-02-18 23:09:27 +08:00
|
|
|
.name = "dvb-dvr",
|
2015-01-03 09:28:53 +08:00
|
|
|
#endif
|
2006-03-11 02:22:31 +08:00
|
|
|
.fops = &dvb_dvr_fops
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
2006-03-11 02:22:31 +08:00
|
|
|
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (dmxdev->demux->open(dmxdev->demux) < 0)
|
|
|
|
return -EUSERS;
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!dmxdev->filter)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2006-02-07 16:49:14 +08:00
|
|
|
mutex_init(&dmxdev->mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_lock_init(&dmxdev->lock);
|
2006-03-11 02:22:31 +08:00
|
|
|
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);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
2015-08-22 03:18:18 +08:00
|
|
|
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
2006-03-11 02:22:31 +08:00
|
|
|
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
2015-08-22 03:18:18 +08:00
|
|
|
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-15 04:31:01 +08:00
|
|
|
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
EXPORT_SYMBOL(dvb_dmxdev_init);
|
|
|
|
|
2006-03-11 02:22:31 +08:00
|
|
|
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2016-12-18 21:52:55 +08:00
|
|
|
dmxdev->exit = 1;
|
2007-04-14 21:19:18 +08:00
|
|
|
if (dmxdev->dvbdev->users > 1) {
|
|
|
|
wait_event(dmxdev->dvbdev->wait_queue,
|
2016-12-18 21:52:55 +08:00
|
|
|
dmxdev->dvbdev->users == 1);
|
2007-04-14 21:19:18 +08:00
|
|
|
}
|
|
|
|
if (dmxdev->dvr_dvbdev->users > 1) {
|
|
|
|
wait_event(dmxdev->dvr_dvbdev->wait_queue,
|
2016-12-18 21:52:55 +08:00
|
|
|
dmxdev->dvr_dvbdev->users == 1);
|
2007-04-14 21:19:18 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
dvb_unregister_device(dmxdev->dvbdev);
|
|
|
|
dvb_unregister_device(dmxdev->dvr_dvbdev);
|
|
|
|
|
|
|
|
vfree(dmxdev->filter);
|
2006-03-11 02:22:31 +08:00
|
|
|
dmxdev->filter = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
dmxdev->demux->close(dmxdev->demux);
|
|
|
|
}
|
2006-03-11 02:22:31 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
EXPORT_SYMBOL(dvb_dmxdev_release);
|