summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/dvb-core
diff options
context:
space:
mode:
authorOliver Endriss <devnull@localhost>2003-02-18 13:18:02 +0000
committerOliver Endriss <devnull@localhost>2003-02-18 13:18:02 +0000
commit5a12e644ad2ddfb5732cec455600de7f0a108305 (patch)
tree7d4a2e9bde73500e3c21d2174829085a0c5c7a49 /linux/drivers/media/dvb/dvb-core
parent218b5ed2dd2770dff18c55b0c813ade613293a1d (diff)
downloadmediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.gz
mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.bz2
ring buffer cleanup
Diffstat (limited to 'linux/drivers/media/dvb/dvb-core')
-rw-r--r--linux/drivers/media/dvb/dvb-core/Makefile4
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c176
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h127
3 files changed, 305 insertions, 2 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/Makefile b/linux/drivers/media/dvb/dvb-core/Makefile
index aac79617c..ec55e17d5 100644
--- a/linux/drivers/media/dvb/dvb-core/Makefile
+++ b/linux/drivers/media/dvb/dvb-core/Makefile
@@ -2,9 +2,9 @@
# Makefile for the kernel DVB device drivers.
#
-export-objs := dvb_ksyms.o
+export-objs := dvb_ksyms.o dvb_ringbuffer.o
dvb-core-objs = dvbdev.o compat.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o
+ dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
new file mode 100644
index 000000000..58918a466
--- /dev/null
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -0,0 +1,176 @@
+/*
+ *
+ * dvb_ringbuffer.c: ring buffer implementation for the dvb driver
+ *
+ * Copyright (C) 2003 Oliver Endriss
+ *
+ * based on code originally found in av7110.c:
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org/dvb/
+ */
+
+
+
+#define __KERNEL_SYSCALLS__
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+#include "dvb_ringbuffer.h"
+
+
+
+void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len)
+{
+ rbuf->pread=rbuf->pwrite=0;
+ rbuf->data=data;
+ rbuf->size=len;
+
+ init_waitqueue_head(&rbuf->queue);
+
+ spin_lock_init(&(rbuf->lock));
+ rbuf->lock=SPIN_LOCK_UNLOCKED;
+}
+
+
+
+int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf)
+{
+ return (rbuf->pread==rbuf->pwrite);
+}
+
+
+
+ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf)
+{
+ ssize_t free;
+
+ free = rbuf->pread - rbuf->pwrite;
+ if (free <= 0)
+ free += rbuf->size;
+ return free-1;
+}
+
+
+
+ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf)
+{
+ ssize_t avail;
+
+ avail = rbuf->pwrite - rbuf->pread;
+ if (avail < 0)
+ avail += rbuf->size;
+ return avail;
+}
+
+
+
+void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf)
+{
+ rbuf->pread = rbuf->pwrite;
+}
+
+
+
+void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rbuf->lock, flags);
+ dvb_ringbuffer_flush(rbuf);
+ spin_unlock_irqrestore(&rbuf->lock, flags);
+
+ wake_up(&rbuf->queue);
+}
+
+
+
+ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, size_t len, int usermem)
+{
+ size_t todo = len;
+ size_t split;
+
+ split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+ if (split > 0) {
+ if (!usermem)
+ memcpy(buf, rbuf->data+rbuf->pread, split);
+ else
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+ return -EFAULT;
+ buf += split;
+ todo -= split;
+ rbuf->pread = 0;
+ }
+ if (!usermem)
+ memcpy(buf, rbuf->data+rbuf->pread, todo);
+ else
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
+ return -EFAULT;
+
+ rbuf->pread = (rbuf->pread + len) % rbuf->size;
+
+ return len;
+}
+
+
+
+ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf,
+ size_t len, int usermem)
+{
+ size_t todo = len;
+ size_t split;
+
+ split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
+
+ if (split > 0) {
+ if (!usermem)
+ memcpy(rbuf->data+rbuf->pwrite, buf, split);
+ else
+ if (copy_from_user(rbuf->data+rbuf->pwrite,
+ buf, split))
+ return -EFAULT;
+ buf += split;
+ todo -= split;
+ rbuf->pwrite = 0;
+ }
+ if (!usermem)
+ memcpy(rbuf->data+rbuf->pwrite, buf, todo);
+ else
+ if (copy_from_user(rbuf->data+rbuf->pwrite, buf, todo))
+ return -EFAULT;
+
+ rbuf->pwrite = (rbuf->pwrite + len) % rbuf->size;
+
+ return len;
+}
+
+
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_init);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_empty);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_free);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_avail);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_read);
+EXPORT_SYMBOL_GPL(dvb_ringbuffer_write);
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
new file mode 100644
index 000000000..19322ee1e
--- /dev/null
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -0,0 +1,127 @@
+/*
+ *
+ * dvb_ringbuffer.h: ring buffer implementation for the dvb driver
+ *
+ * Copyright (C) 2003 Oliver Endriss
+ *
+ * based on code originally found in av7110.c:
+ * Copyright (C) 1999-2002 Ralph Metzler
+ * & Marcus Metzler for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org/dvb/
+ */
+
+#ifndef _DVB_RINGBUFFER_H_
+#define _DVB_RINGBUFFER_H_
+
+
+typedef struct dvb_ringbuffer_s {
+ u8 *data;
+ ssize_t size;
+ ssize_t pread;
+ ssize_t pwrite;
+
+ wait_queue_head_t queue;
+ spinlock_t lock;
+} dvb_ringbuffer_t;
+
+
+/*
+** Notes:
+** ------
+** (1) For performance reasons read and write routines don't check buffer sizes
+** and/or number of bytes free/available. This has to be done before these
+** routines are called. For example:
+**
+** *** write <buflen> bytes ***
+** free = dvb_ringbuffer_free(rbuf);
+** if (free >= buflen)
+** count = dvb_ringbuffer_write(rbuf, buffer, buflen, 0);
+** else
+** ...
+**
+** *** read min. 1000, max. <bufsize> bytes ***
+** avail = dvb_ringbuffer_available(rbuf);
+** if (avail >= 1000)
+** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0);
+** else
+** ...
+**
+** (2) If there is exactly one reader and one writer, there is no need
+** to lock read or write operations.
+** Two or more readers must be locked against each other.
+** Flushing the buffer counts as a read operation.
+** Two or more writers must be locked against each other.
+*/
+
+/* initialize ring buffer, lock and queue */
+extern void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len);
+
+/* test whether buffer is empty */
+extern int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf);
+
+/* return the number of free bytes in the buffer */
+extern ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf);
+
+/* return the number of bytes waiting in the buffer */
+extern ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf);
+
+
+/* read routines & macros */
+/* ---------------------- */
+/* flush buffer */
+extern void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf);
+
+/* flush buffer protected by spinlock and wake-up waiting task(s) */
+extern void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf);
+
+/* peek at byte <offs> in the buffer */
+#define DVB_RINGBUFFER_PEEK(rbuf,offs) \
+ (rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
+
+/* advance read ptr by <num> bytes */
+#define DVB_RINGBUFFER_SKIP(rbuf,num) \
+ (rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
+
+/*
+** read <len> bytes from ring buffer into <buf>
+** <usermem> specifies whether <buf> resides in user space
+** returns number of bytes transferred or -EFAULT
+*/
+extern ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf,
+ size_t len, int usermem);
+
+
+/* write routines & macros */
+/* ----------------------- */
+/* write single byte to ring buffer */
+#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \
+ { (rbuf)->data[(rbuf)->pwrite]=(byte); \
+ (rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
+/*
+** write <len> bytes to ring buffer
+** <usermem> specifies whether <buf> resides in user space
+** returns number of bytes transferred or -EFAULT
+*/
+extern ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf,
+ size_t len, int usermem);
+
+#endif /* _DVB_RINGBUFFER_H_ */