--- /dev/null
+diff --git a/contrib/sasc-ng/dvbloopback/module/dvb_loopback.c b/contrib/sasc-ng/dvbloopback/module/dvb_loopback.c
+index 5299dbe..a8500dd 100644
+--- a/contrib/sasc-ng/dvbloopback/module/dvb_loopback.c
++++ b/contrib/sasc-ng/dvbloopback/module/dvb_loopback.c
+@@ -49,6 +49,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/pagemap.h>
++#include <linux/slab.h>
+ #include <linux/dvb/ca.h>
+ #include <linux/dvb/frontend.h>
+ #include <linux/dvb/version.h>
+diff --git a/contrib/sasc-ng/dvbloopback/module/dvblb_proc.c b/contrib/sasc-ng/dvbloopback/module/dvblb_proc.c
+index c78aa33..2c3637f 100644
+--- a/contrib/sasc-ng/dvbloopback/module/dvblb_proc.c
++++ b/contrib/sasc-ng/dvbloopback/module/dvblb_proc.c
+@@ -23,14 +23,16 @@
+ */
+ #include <linux/version.h> /* >= 2.6.14 LINUX_VERSION_CODE */
+ #include <linux/errno.h>
++#include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/seq_file.h>
+
+ #include <linux/proc_fs.h>
+ #include "dvblb_internal.h"
+
+ static struct proc_dir_entry *procdir;
+-
++/*
+ static int dvblb_procfs_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+ {
+@@ -41,7 +43,18 @@ static int dvblb_procfs_read(char *page, char **start, off_t off, int count,
+ val = (lbdev->forward_dev) ? 1 : 0;
+ return sprintf(page, "%03d", val);
+ }
+-
++*/
++static int dvblb_procfs_read(struct seq_file *s, void* v)
++{
++ struct dvblb_devinfo *lbdev = s->private;
++ int val;
++ if (lbdev == NULL)
++ return 0;
++ val = (lbdev->forward_dev) ? 1 : 0;
++ seq_printf(s, "%03d", val);
++ return 0;
++}
++/*
+ static int dvblb_procfs_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+ {
+@@ -95,7 +108,64 @@ static int dvblb_procfs_write(struct file *file, const char *buffer,
+ }
+ return count;
+ }
+-
++*/
++static ssize_t dvblb_procfs_write(struct file *file, const char *buffer,
++ size_t count, loff_t *pos)
++{
++ // TODO: maybe update *pos at end???
++ char str[10];
++ int val, v1, v2, v3, fm;
++ //struct dvblb_devinfo *lbdev = (struct dvblb_devinfo *)data;
++ struct seq_file *s = file->private_data;
++ struct dvblb_devinfo* lbdev = s->private;
++ if (lbdev == NULL)
++ return count;
++ if (lbdev->parent->link == -1)
++ return count;
++ if (count > 10)
++ count = 10;
++ if (copy_from_user(str, buffer, count)) {
++ return -EFAULT;
++ }
++ val = simple_strtoul(str, NULL, 0);
++ v1 = val /100;
++ v2 = (val - v1*100) / 10;
++ v3 = val - v1*100 - v2*10;
++ if (v1 < 0 || v1 > 2)
++ return -EFAULT;
++ if((fm = inuse_filemap(lbdev))) {
++ int type = lbdev->lb_dev->type;
++ printk("dvbloopback: Can't change forward on adapter%d."
++ " Device %s still has %d users!\n",
++ lbdev->parent->adapter.num, dnames[type], fm);
++ return count;
++ }
++ if (v3 == 1) {
++ struct list_head *entry;
++ list_for_each (entry, lbdev->parent->adapter_ll) {
++ struct dvb_adapter *adap;
++ adap = list_entry (entry, struct dvb_adapter,
++ list_head);
++ if (adap->num == lbdev->parent->link) {
++ struct list_head *entry0;
++ list_for_each (entry0,
++ &adap->device_list) {
++ struct dvb_device *dev;
++ dev = list_entry (entry0,
++ struct dvb_device, list_head);
++ if (dev->type == lbdev->lb_dev->type) {
++ lbdev->forward_dev = dev;
++ return count;
++ }
++ }
++ }
++ }
++ } else if (v3 == 0) {
++ lbdev->forward_dev = NULL;
++ }
++ return count;
++}
++/*
+ static int dvblb_procfs_adapter_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+@@ -104,7 +174,16 @@ static int dvblb_procfs_adapter_read(char *page, char **start, off_t off,
+ return 0;
+ return sprintf(page, "%d", dvblb->link);
+ }
+-
++*/
++static int dvblb_procfs_adapter_read(struct seq_file *s, void* v)
++{
++ struct dvblb *dvblb = s->private;
++ if (dvblb == NULL)
++ return 0;
++ seq_printf(s, "%d", dvblb->link);
++ return 0;
++}
++/*
+ static int dvblb_procfs_adapter_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+ {
+@@ -121,6 +200,54 @@ static int dvblb_procfs_adapter_write(struct file *file, const char *buffer,
+ val = simple_strtol(str, NULL, 0);
+
+ if(val == -999) {
++ //This is a debug case. Try to force close all open fds
++ //This is known not to be very reliable, but better than
++ //nothing
++
++ for(i = 0; i < DVBLB_NUM_DEVS; i++) {
++ while((fm = inuse_filemap(&dvbdev->devinfo[i]))) {
++ filp_close(dvbdev->devinfo[i].dbgfilemap[fm],
++ NULL);
++ dvbdev->devinfo[i].filemap[fm] = NULL;
++ }
++ }
++ return count;
++ }
++ for(i = 0; i < DVBLB_NUM_DEVS; i++) {
++ if(dvbdev->devinfo[i].forward_dev == NULL)
++ continue;
++ if((fm = inuse_filemap(&dvbdev->devinfo[i]))) {
++ int type = dvbdev->devinfo[i].lb_dev->type;
++ printk("dvbloopback: Can't change forward on adapter%d."
++ " Device %s still has %d users!\n",
++ dvbdev->adapter.num, dnames[type], fm);
++ return count;
++ }
++ }
++ for(i = 0; i < DVBLB_NUM_DEVS; i++)
++ dvbdev->devinfo[i].forward_dev = NULL;
++ dvbdev->link = val;
++ return count;
++}
++*/
++static ssize_t dvblb_procfs_adapter_write(struct file *file, const char *buffer,
++ size_t count, loff_t *pos)
++{
++ // TODO: maybe update *pos at end???
++ char str[10];
++ int val, i, fm;
++ struct seq_file *s = file->private_data;
++ struct dvblb* dvbdev = s->private;
++ if (dvbdev == NULL)
++ return count;
++ if (count > 10)
++ count = 10;
++ if (copy_from_user(str, buffer, count)) {
++ return -EFAULT;
++ }
++ val = simple_strtol(str, NULL, 0);
++
++ if(val == -999) {
+ /*This is a debug case. Try to force close all open fds
+ This is known not to be very reliable, but better than
+ nothing
+@@ -154,31 +281,47 @@ static int dvblb_procfs_adapter_write(struct file *file, const char *buffer,
+ int dvblb_remove_procfs(struct proc_dir_entry *pdir,
+ struct proc_dir_entry *parent)
+ {
+- char name[20];
+- memcpy(name, pdir->name, pdir->namelen);
+- name[pdir->namelen] = '\0';
+- // printk("Removing proc: %s\n", name);
+- remove_proc_entry(name, parent);
++ proc_remove(pdir);
+ return 0;
+ }
+ EXPORT_SYMBOL(dvblb_remove_procfs);
+
++static int dvblb_procfs_open(struct inode *inode, struct file *filep)
++{
++ return single_open(filep, dvblb_procfs_read, PDE_DATA(inode));
++}
++
++static const struct file_operations dvblb_procfs_fops = {
++ .owner = THIS_MODULE,
++ .open = dvblb_procfs_open,
++ .read = seq_read,
++ .write = dvblb_procfs_write,
++ .release = single_release,
++};
++
+ int dvblb_init_procfs_device(struct dvblb *dvblb, struct dvblb_devinfo *lbdev)
+ {
+- int type = lbdev->lb_dev->type;
+- lbdev->procfile = create_proc_entry(dnames[type], 0644, dvblb->procdir);
+- if (lbdev->procfile == NULL)
+- return -ENOMEM;
+- lbdev->procfile->data = lbdev;
+- lbdev->procfile->read_proc = dvblb_procfs_read;
+- lbdev->procfile->write_proc = dvblb_procfs_write;
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+- lbdev->procfile->owner = THIS_MODULE;
+-#endif
+- return 0;
++ int type = lbdev->lb_dev->type;
++ lbdev->procfile = proc_create_data(dnames[type], 0644, dvblb->procdir, &dvblb_procfs_fops, lbdev);
++ if (lbdev->procfile == NULL)
++ return -ENOMEM;
++ return 0;
+ }
+ EXPORT_SYMBOL(dvblb_init_procfs_device);
+
++static int dvblb_procfs_adapter_open(struct inode *inode, struct file *filep)
++{
++ return single_open(filep, dvblb_procfs_adapter_read, PDE_DATA(inode));
++}
++
++static const struct file_operations dvblb_procfs_adapter_fops = {
++ .owner = THIS_MODULE,
++ .open = dvblb_procfs_adapter_open,
++ .read = seq_read,
++ .write = dvblb_procfs_adapter_write,
++ .release = single_release,
++};
++
+ int dvblb_init_procfs_adapter(struct dvblb *dvblb)
+ {
+ char name[10];
+@@ -186,20 +329,12 @@ int dvblb_init_procfs_adapter(struct dvblb *dvblb)
+ dvblb->procdir = proc_mkdir(name, procdir);
+ if (dvblb->procdir == NULL)
+ return -ENOMEM;
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+- dvblb->procdir->owner = THIS_MODULE;
+-#endif
+- dvblb->procfile = create_proc_entry("adapter", 0644, dvblb->procdir);
++ //dvblb->procfile = create_proc_entry("adapter", 0644, dvblb->procdir);
++ dvblb->procfile = proc_create_data("adapter", 0644, dvblb->procdir, &dvblb_procfs_adapter_fops, dvblb);
+ if (dvblb->procfile == NULL) {
+ dvblb_remove_procfs(dvblb->procdir, procdir);
+ return -ENOMEM;
+ }
+- dvblb->procfile->data = dvblb;
+- dvblb->procfile->read_proc = dvblb_procfs_adapter_read;
+- dvblb->procfile->write_proc = dvblb_procfs_adapter_write;
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+- dvblb->procfile->owner = THIS_MODULE;
+-#endif
+ dvblb->init |= DVBLB_STATUS_PROC;
+
+ return 0;