|
SASC
DVBSoftCAM
|
00001 /* 00002 * dvblb_forward.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/fs.h> 00030 #include <linux/file.h> 00031 #include <linux/cdev.h> 00032 #include <linux/err.h> 00033 #include "dvblb_internal.h" 00034 00035 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) 00036 00037 // forward to correct device 00038 static struct file *find_forwardmap(struct dvblb_devinfo *lbdev, 00039 struct dvb_device **f) 00040 { 00041 int i; 00042 for(i = 0; i < DVBLB_MAXFD; i++) 00043 if(lbdev->forwardmap[i].f == f) 00044 return lbdev->forwardmap[i].map; 00045 return ERR_PTR(-1); 00046 } 00047 00048 static int set_forwardmap(struct dvblb_devinfo *lbdev, struct dvb_device **f, 00049 struct file *map) { 00050 int i; 00051 for(i = 0; i < DVBLB_MAXFD; i++) 00052 if(lbdev->forwardmap[i].f == NULL) { 00053 lbdev->forwardmap[i].f = f; 00054 lbdev->forwardmap[i].map = map; 00055 return i; 00056 } 00057 return -1; 00058 } 00059 00060 static void clear_forwardmap(struct dvblb_devinfo *lbdev, struct dvb_device **f) 00061 { 00062 int i; 00063 for(i = 0; i < DVBLB_MAXFD; i++) 00064 if(lbdev->forwardmap[i].f == f) { 00065 lbdev->forwardmap[i].f = NULL; 00066 return; 00067 } 00068 } 00069 00070 int dvblb_forward_open(struct dvblb_devinfo *lbdev, struct inode *inode, 00071 struct file *f) 00072 { 00073 // int minor; 00074 // struct inode *tmpinode; 00075 // struct dentry *dentry; 00076 struct file *ftmp; 00077 char tmpstr[35]; 00078 00079 if (! inode->i_cdev || ! inode->i_cdev->ops || 00080 ! inode->i_cdev->ops->open) { 00081 printk("dvblb_forward_open: " 00082 "device wasn't correctly initialized\n"); 00083 return -EFAULT; 00084 } 00085 sprintf(tmpstr, "/dev/dvb/adapter%d/%s%d", lbdev->forward_dev->adapter->num, dnames[lbdev->forward_dev->type], lbdev->forward_dev->id); 00086 /* printk("linking to %s\n", tmpstr); */ 00087 ftmp = filp_open(tmpstr, f->f_flags, f->f_mode); 00088 00089 /* It would be nice to find a way to open the device without relying 00090 on a fixed path, but the attempt below certainly isn't it */ 00091 /* 00092 minor = nums2minor(lbdev->forward_dev->adapter->num, 00093 lbdev->forward_dev->type, lbdev->forward_dev->id); 00094 tmpinode = iget_locked(inode->i_sb, MKDEV(DVB_MAJOR, minor)); 00095 if (! tmpinode) 00096 return -EFAULT; 00097 if (is_bad_inode(tmpinode)) { 00098 iput(tmpinode); 00099 return -EFAULT; 00100 } 00101 dentry = d_alloc_anon(tmpinode); 00102 if (!dentry) { 00103 iput(tmpinode); 00104 return -EFAULT; 00105 } 00106 ftmp = dentry_open(dentry, f->f_vfsmnt, f->f_flags); 00107 */ 00108 if (!ftmp || IS_ERR(ftmp)) { 00109 int fd = PTR_ERR(ftmp); 00110 printk("open failed: %d\n", fd); 00111 return fd; 00112 } 00113 if (! ftmp->f_op || ! lbdev->forward_dev->fops || 00114 ftmp->f_op->open != lbdev->forward_dev->fops->open) { 00115 printk("DVB device din't initialize correctly\n"); 00116 filp_close(ftmp, NULL); 00117 return -EFAULT; 00118 } 00119 if (set_forwardmap(lbdev, f->private_data, ftmp) == -1) { 00120 printk("Didn't find a valid forwardmap\n"); 00121 filp_close(ftmp, NULL); 00122 return -EFAULT; 00123 } 00124 return 0; 00125 } 00126 00127 int dvblb_forward_release(struct dvblb_devinfo *lbdev, struct file *f) 00128 { 00129 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00130 if (!ftmp || IS_ERR(ftmp)) 00131 return -EFAULT; 00132 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->release) { 00133 filp_close(ftmp, NULL); 00134 clear_forwardmap(lbdev, f->private_data); 00135 } 00136 return -EFAULT; 00137 } 00138 00139 ssize_t dvblb_forward_write(struct dvblb_devinfo *lbdev, struct file *f, 00140 const char *buf, size_t count, loff_t *offset) 00141 { 00142 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00143 if (!ftmp || IS_ERR(ftmp)) 00144 return -EFAULT; 00145 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->write) 00146 return lbdev->forward_dev->fops->write( 00147 ftmp, buf, count, offset); 00148 return -EFAULT; 00149 } 00150 00151 ssize_t dvblb_forward_read (struct dvblb_devinfo *lbdev, struct file *f, 00152 char * buf, size_t count, loff_t *offset) 00153 { 00154 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00155 if (!ftmp || IS_ERR(ftmp)) 00156 return -EFAULT; 00157 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->read) 00158 return lbdev->forward_dev->fops->read( 00159 ftmp, buf, count, offset); 00160 return -EFAULT; 00161 } 00162 00163 int dvblb_forward_ioctl(struct dvblb_devinfo *lbdev, struct file *f, 00164 unsigned int cmd, unsigned long arg) 00165 { 00166 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00167 if (!ftmp || IS_ERR(ftmp)) 00168 return -EFAULT; 00169 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) 00170 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->unlocked_ioctl) 00171 return lbdev->forward_dev->fops->unlocked_ioctl( 00172 ftmp, cmd, arg); 00173 #else 00174 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->ioctl) 00175 return lbdev->forward_dev->fops->ioctl( 00176 ftmp->f_dentry->d_inode, ftmp, cmd, arg); 00177 #endif 00178 return -EFAULT; 00179 } 00180 00181 int dvblb_forward_mmap(struct dvblb_devinfo *lbdev, struct file *f, 00182 struct vm_area_struct *vma) 00183 { 00184 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00185 if (!ftmp || IS_ERR(ftmp)) 00186 return -EFAULT; 00187 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->mmap) 00188 return lbdev->forward_dev->fops->mmap(ftmp, vma); 00189 return -EFAULT; 00190 } 00191 00192 int dvblb_forward_poll(struct dvblb_devinfo *lbdev, struct file *f, 00193 struct poll_table_struct *wait) 00194 { 00195 struct file *ftmp = find_forwardmap(lbdev, f->private_data); 00196 if (!ftmp || IS_ERR(ftmp)) 00197 return -EFAULT; 00198 if (lbdev->forward_dev->fops &&lbdev->forward_dev->fops->poll) 00199 return lbdev->forward_dev->fops->poll(ftmp, wait); 00200 return -EFAULT; 00201 }