SASC-NG
DVBSoftCAM

dvblb_proc.c

Go to the documentation of this file.
00001 /*
00002  *      dvblb_proc.c
00003  *
00004  *      DVBLoopback Copyright Alan Nisota 2006
00005  *
00006  *      Portions of this code also have copyright:
00007  *      Video Loopback Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2000
00008  *
00009  *      Published under the GNU Public License.
00010  *      DVBLoopback is free software; you can redistribute it and/or modify
00011  *      it under the terms of the GNU General Public License as published by
00012  *      the Free Software Foundation; either version 2 of the License, or
00013  *      (at your option) any later version.
00014  *
00015  *      DVBLoopback is distributed in the hope that it will be useful,
00016  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *      GNU General Public License for more details.
00019  *
00020  *      You should have received a copy of the GNU General Public License
00021  *      along with Foobar; if not, write to the Free Software
00022  *      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00023  */
00024 #include <linux/version.h>      /* >= 2.6.14 LINUX_VERSION_CODE */
00025 #include <linux/errno.h>
00026 #include <linux/kernel.h>
00027 #include <linux/module.h>
00028 
00029 #include <linux/proc_fs.h>
00030 #include "dvblb_internal.h"
00031 
00032 static struct proc_dir_entry *procdir;
00033 
00034 static int dvblb_procfs_read(char *page, char **start, off_t off, int count,
00035                              int *eof, void *data)
00036 {
00037         struct dvblb_devinfo *lbdev = (struct dvblb_devinfo *)data;
00038         int val;
00039         if (lbdev == NULL)
00040                 return 0;
00041         val = (lbdev->forward_dev) ? 1 : 0;
00042         return sprintf(page, "%03d", val);
00043 }
00044 
00045 static int dvblb_procfs_write(struct file *file, const char *buffer,
00046                               unsigned long count, void *data)
00047 {
00048         char str[10];
00049         int val, v1, v2, v3, fm;
00050         struct dvblb_devinfo *lbdev = (struct dvblb_devinfo *)data;
00051         if (lbdev == NULL)
00052                 return count;
00053         if (lbdev->parent->link == -1)
00054                 return count;
00055         if (count > 10)
00056                 count = 10;
00057         if (copy_from_user(str, buffer, count)) {
00058                 return -EFAULT;
00059         }
00060         val = simple_strtoul(str, NULL, 0);
00061         v1 = val /100;
00062         v2 = (val - v1*100) / 10;
00063         v3 = val - v1*100 - v2*10;
00064         if (v1 < 0 || v1 > 2) 
00065                 return -EFAULT;
00066         if((fm = inuse_filemap(lbdev))) {
00067                 int type = lbdev->lb_dev->type;
00068                 printk("dvbloopback: Can't change forward on adapter%d."
00069                        " Device %s still has %d users!\n",
00070                        lbdev->parent->adapter.num, dnames[type], fm);
00071                 return count;
00072         }
00073         if (v3 == 1) {
00074                 struct list_head *entry;
00075                 list_for_each (entry, lbdev->parent->adapter_ll) {
00076                         struct dvb_adapter *adap;
00077                         adap = list_entry (entry, struct dvb_adapter,
00078                                            list_head);
00079                         if (adap->num == lbdev->parent->link) {
00080                                 struct list_head *entry0;
00081                                 list_for_each (entry0,
00082                                                &adap->device_list) {
00083                                         struct dvb_device *dev;
00084                                         dev = list_entry (entry0,
00085                                                struct dvb_device, list_head);
00086                                         if (dev->type == lbdev->lb_dev->type) {
00087                                                 lbdev->forward_dev = dev;
00088                                                 return count;
00089                                         }
00090                                 }
00091                         }
00092                 }
00093         } else if (v3 == 0) {
00094                 lbdev->forward_dev = NULL;
00095         }
00096         return count;
00097 }
00098 
00099 static int dvblb_procfs_adapter_read(char *page, char **start, off_t off,
00100                                      int count, int *eof, void *data)
00101 {
00102         struct dvblb *dvblb = (struct dvblb *)data;
00103         if (dvblb == NULL)
00104                 return 0;
00105         return sprintf(page, "%d", dvblb->link);
00106 }
00107 
00108 static int dvblb_procfs_adapter_write(struct file *file, const char *buffer,
00109                                       unsigned long count, void *data)
00110 {
00111         char str[10];
00112         int val, i, fm;
00113         struct dvblb *dvbdev = (struct dvblb *)data;
00114         if (dvbdev == NULL)
00115                 return count;
00116         if (count > 10)
00117                 count = 10;
00118         if (copy_from_user(str, buffer, count)) {
00119                 return -EFAULT;
00120         }
00121         val = simple_strtol(str, NULL, 0);
00122 
00123         if(val == -999) {
00124                 /*This is a debug case.  Try to force close all open fds
00125                   This is known not to be very reliable, but better than
00126                   nothing
00127                 */
00128                 for(i = 0; i < DVBLB_NUM_DEVS; i++) {
00129                         while((fm = inuse_filemap(&dvbdev->devinfo[i]))) {
00130                                 filp_close(dvbdev->devinfo[i].dbgfilemap[fm],
00131                                            NULL);
00132                                 dvbdev->devinfo[i].filemap[fm] = NULL;
00133                         }
00134                 }
00135                 return count;
00136         }
00137         for(i = 0; i < DVBLB_NUM_DEVS; i++) {
00138                 if(dvbdev->devinfo[i].forward_dev == NULL)
00139                         continue;
00140                 if((fm = inuse_filemap(&dvbdev->devinfo[i]))) {
00141                         int type = dvbdev->devinfo[i].lb_dev->type;
00142                         printk("dvbloopback: Can't change forward on adapter%d."
00143                                " Device %s still has %d users!\n",
00144                                dvbdev->adapter.num, dnames[type], fm);
00145                         return count;
00146                 }
00147         }
00148         for(i = 0; i < DVBLB_NUM_DEVS; i++)
00149                 dvbdev->devinfo[i].forward_dev = NULL;
00150         dvbdev->link = val;
00151         return count;
00152 }
00153 
00154 int dvblb_remove_procfs(struct proc_dir_entry *pdir,
00155                         struct proc_dir_entry *parent)
00156 {
00157         char name[20];
00158         memcpy(name, pdir->name, pdir->namelen);
00159         name[pdir->namelen] = '\0';
00160         // printk("Removing proc: %s\n", name);
00161         remove_proc_entry(name, parent);
00162         return 0;
00163 }
00164 EXPORT_SYMBOL(dvblb_remove_procfs);
00165 
00166 int dvblb_init_procfs_device(struct dvblb *dvblb, struct dvblb_devinfo *lbdev)
00167 {
00168         int type = lbdev->lb_dev->type;
00169         lbdev->procfile = create_proc_entry(dnames[type], 0644, dvblb->procdir);
00170         if (lbdev->procfile == NULL)
00171                 return -ENOMEM;
00172         lbdev->procfile->data = lbdev;
00173         lbdev->procfile->read_proc = dvblb_procfs_read;
00174         lbdev->procfile->write_proc = dvblb_procfs_write;
00175 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
00176         lbdev->procfile->owner = THIS_MODULE;
00177 #endif
00178         return 0;
00179 }
00180 EXPORT_SYMBOL(dvblb_init_procfs_device);
00181 
00182 int dvblb_init_procfs_adapter(struct dvblb *dvblb)
00183 {
00184         char name[10];
00185         sprintf(name, "adapter%d", dvblb->adapter.num);
00186         dvblb->procdir = proc_mkdir(name, procdir);
00187         if (dvblb->procdir == NULL)
00188                 return -ENOMEM;
00189 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
00190         dvblb->procdir->owner = THIS_MODULE;
00191 #endif
00192         dvblb->procfile = create_proc_entry("adapter", 0644, dvblb->procdir);
00193         if (dvblb->procfile == NULL) {
00194                 dvblb_remove_procfs(dvblb->procdir, procdir);
00195                 return -ENOMEM;
00196         }
00197         dvblb->procfile->data = dvblb;
00198         dvblb->procfile->read_proc = dvblb_procfs_adapter_read;
00199         dvblb->procfile->write_proc = dvblb_procfs_adapter_write;
00200 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
00201         dvblb->procfile->owner = THIS_MODULE;
00202 #endif
00203         dvblb->init |= DVBLB_STATUS_PROC;
00204 
00205         return 0;
00206 }
00207 EXPORT_SYMBOL(dvblb_init_procfs_adapter);
00208 
00209 int dvblb_remove_procfs_adapter(struct dvblb *dvblb)
00210 {
00211         if(dvblb->init & DVBLB_STATUS_PROC) {
00212                 dvblb_remove_procfs(dvblb->procfile, dvblb->procdir);
00213                 dvblb_remove_procfs(dvblb->procdir, procdir);
00214                 printk("removing dvblb proc adapter\n");
00215         }
00216         dvblb->init &= ~DVBLB_STATUS_PROC;
00217         printk("dvblb init = %x\n", dvblb->init);
00218         return 0;
00219 }
00220 EXPORT_SYMBOL(dvblb_remove_procfs_adapter);
00221 
00222 int dvblb_init_procfs(void)
00223 {
00224         procdir = proc_mkdir("dvbloopback", NULL);
00225         if (procdir == NULL)
00226                 return -ENOMEM;
00227 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
00228         procdir->owner = THIS_MODULE;
00229 #endif
00230         return 0;
00231 }
00232 EXPORT_SYMBOL(dvblb_init_procfs);
00233 
00234 int dvblb_uninit_procfs(void)
00235 {
00236         dvblb_remove_procfs(procdir, NULL);
00237         return 0;
00238 }
00239 EXPORT_SYMBOL(dvblb_uninit_procfs);
00240 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines