0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0022
0023 #include <linux/errno.h>
0024 #include <linux/init.h>
0025 #include <linux/module.h>
0026 #include <linux/kernel.h>
0027 #include <linux/kmod.h>
0028 #include <linux/slab.h>
0029 #include <linux/mm.h>
0030 #include <linux/string.h>
0031 #include <linux/types.h>
0032 #include <linux/uaccess.h>
0033
0034 #include <media/media-devnode.h>
0035 #include <media/media-device.h>
0036
0037 #define MEDIA_NUM_DEVICES 256
0038 #define MEDIA_NAME "media"
0039
0040 static dev_t media_dev_t;
0041
0042
0043
0044
0045 static DEFINE_MUTEX(media_devnode_lock);
0046 static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
0047
0048
0049 static void media_devnode_release(struct device *cd)
0050 {
0051 struct media_devnode *devnode = to_media_devnode(cd);
0052
0053 mutex_lock(&media_devnode_lock);
0054
0055 clear_bit(devnode->minor, media_devnode_nums);
0056 mutex_unlock(&media_devnode_lock);
0057
0058
0059 if (devnode->release)
0060 devnode->release(devnode);
0061
0062 kfree(devnode);
0063 pr_debug("%s: Media Devnode Deallocated\n", __func__);
0064 }
0065
0066 static struct bus_type media_bus_type = {
0067 .name = MEDIA_NAME,
0068 };
0069
0070 static ssize_t media_read(struct file *filp, char __user *buf,
0071 size_t sz, loff_t *off)
0072 {
0073 struct media_devnode *devnode = media_devnode_data(filp);
0074
0075 if (!devnode->fops->read)
0076 return -EINVAL;
0077 if (!media_devnode_is_registered(devnode))
0078 return -EIO;
0079 return devnode->fops->read(filp, buf, sz, off);
0080 }
0081
0082 static ssize_t media_write(struct file *filp, const char __user *buf,
0083 size_t sz, loff_t *off)
0084 {
0085 struct media_devnode *devnode = media_devnode_data(filp);
0086
0087 if (!devnode->fops->write)
0088 return -EINVAL;
0089 if (!media_devnode_is_registered(devnode))
0090 return -EIO;
0091 return devnode->fops->write(filp, buf, sz, off);
0092 }
0093
0094 static __poll_t media_poll(struct file *filp,
0095 struct poll_table_struct *poll)
0096 {
0097 struct media_devnode *devnode = media_devnode_data(filp);
0098
0099 if (!media_devnode_is_registered(devnode))
0100 return EPOLLERR | EPOLLHUP;
0101 if (!devnode->fops->poll)
0102 return DEFAULT_POLLMASK;
0103 return devnode->fops->poll(filp, poll);
0104 }
0105
0106 static long
0107 __media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
0108 long (*ioctl_func)(struct file *filp, unsigned int cmd,
0109 unsigned long arg))
0110 {
0111 struct media_devnode *devnode = media_devnode_data(filp);
0112
0113 if (!ioctl_func)
0114 return -ENOTTY;
0115
0116 if (!media_devnode_is_registered(devnode))
0117 return -EIO;
0118
0119 return ioctl_func(filp, cmd, arg);
0120 }
0121
0122 static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
0123 {
0124 struct media_devnode *devnode = media_devnode_data(filp);
0125
0126 return __media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
0127 }
0128
0129 #ifdef CONFIG_COMPAT
0130
0131 static long media_compat_ioctl(struct file *filp, unsigned int cmd,
0132 unsigned long arg)
0133 {
0134 struct media_devnode *devnode = media_devnode_data(filp);
0135
0136 return __media_ioctl(filp, cmd, arg, devnode->fops->compat_ioctl);
0137 }
0138
0139 #endif
0140
0141
0142 static int media_open(struct inode *inode, struct file *filp)
0143 {
0144 struct media_devnode *devnode;
0145 int ret;
0146
0147
0148
0149
0150
0151
0152
0153 mutex_lock(&media_devnode_lock);
0154 devnode = container_of(inode->i_cdev, struct media_devnode, cdev);
0155
0156
0157 if (!media_devnode_is_registered(devnode)) {
0158 mutex_unlock(&media_devnode_lock);
0159 return -ENXIO;
0160 }
0161
0162 get_device(&devnode->dev);
0163 mutex_unlock(&media_devnode_lock);
0164
0165 filp->private_data = devnode;
0166
0167 if (devnode->fops->open) {
0168 ret = devnode->fops->open(filp);
0169 if (ret) {
0170 put_device(&devnode->dev);
0171 filp->private_data = NULL;
0172 return ret;
0173 }
0174 }
0175
0176 return 0;
0177 }
0178
0179
0180 static int media_release(struct inode *inode, struct file *filp)
0181 {
0182 struct media_devnode *devnode = media_devnode_data(filp);
0183
0184 if (devnode->fops->release)
0185 devnode->fops->release(filp);
0186
0187 filp->private_data = NULL;
0188
0189
0190
0191 put_device(&devnode->dev);
0192
0193 pr_debug("%s: Media Release\n", __func__);
0194 return 0;
0195 }
0196
0197 static const struct file_operations media_devnode_fops = {
0198 .owner = THIS_MODULE,
0199 .read = media_read,
0200 .write = media_write,
0201 .open = media_open,
0202 .unlocked_ioctl = media_ioctl,
0203 #ifdef CONFIG_COMPAT
0204 .compat_ioctl = media_compat_ioctl,
0205 #endif
0206 .release = media_release,
0207 .poll = media_poll,
0208 .llseek = no_llseek,
0209 };
0210
0211 int __must_check media_devnode_register(struct media_device *mdev,
0212 struct media_devnode *devnode,
0213 struct module *owner)
0214 {
0215 int minor;
0216 int ret;
0217
0218
0219 mutex_lock(&media_devnode_lock);
0220 minor = find_first_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES);
0221 if (minor == MEDIA_NUM_DEVICES) {
0222 mutex_unlock(&media_devnode_lock);
0223 pr_err("could not get a free minor\n");
0224 kfree(devnode);
0225 return -ENFILE;
0226 }
0227
0228 set_bit(minor, media_devnode_nums);
0229 mutex_unlock(&media_devnode_lock);
0230
0231 devnode->minor = minor;
0232 devnode->media_dev = mdev;
0233
0234
0235 devnode->dev.bus = &media_bus_type;
0236 devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
0237 devnode->dev.release = media_devnode_release;
0238 if (devnode->parent)
0239 devnode->dev.parent = devnode->parent;
0240 dev_set_name(&devnode->dev, "media%d", devnode->minor);
0241 device_initialize(&devnode->dev);
0242
0243
0244 cdev_init(&devnode->cdev, &media_devnode_fops);
0245 devnode->cdev.owner = owner;
0246 kobject_set_name(&devnode->cdev.kobj, "media%d", devnode->minor);
0247
0248
0249 ret = cdev_device_add(&devnode->cdev, &devnode->dev);
0250 if (ret < 0) {
0251 pr_err("%s: cdev_device_add failed\n", __func__);
0252 goto cdev_add_error;
0253 }
0254
0255
0256 set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
0257
0258 return 0;
0259
0260 cdev_add_error:
0261 mutex_lock(&media_devnode_lock);
0262 clear_bit(devnode->minor, media_devnode_nums);
0263 devnode->media_dev = NULL;
0264 mutex_unlock(&media_devnode_lock);
0265
0266 put_device(&devnode->dev);
0267 return ret;
0268 }
0269
0270 void media_devnode_unregister_prepare(struct media_devnode *devnode)
0271 {
0272
0273 if (!media_devnode_is_registered(devnode))
0274 return;
0275
0276 mutex_lock(&media_devnode_lock);
0277 clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
0278 mutex_unlock(&media_devnode_lock);
0279 }
0280
0281 void media_devnode_unregister(struct media_devnode *devnode)
0282 {
0283 mutex_lock(&media_devnode_lock);
0284
0285 cdev_device_del(&devnode->cdev, &devnode->dev);
0286 devnode->media_dev = NULL;
0287 mutex_unlock(&media_devnode_lock);
0288
0289 put_device(&devnode->dev);
0290 }
0291
0292
0293
0294
0295 static int __init media_devnode_init(void)
0296 {
0297 int ret;
0298
0299 pr_info("Linux media interface: v0.10\n");
0300 ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES,
0301 MEDIA_NAME);
0302 if (ret < 0) {
0303 pr_warn("unable to allocate major\n");
0304 return ret;
0305 }
0306
0307 ret = bus_register(&media_bus_type);
0308 if (ret < 0) {
0309 unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
0310 pr_warn("bus_register failed\n");
0311 return -EIO;
0312 }
0313
0314 return 0;
0315 }
0316
0317 static void __exit media_devnode_exit(void)
0318 {
0319 bus_unregister(&media_bus_type);
0320 unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
0321 }
0322
0323 subsys_initcall(media_devnode_init);
0324 module_exit(media_devnode_exit)
0325
0326 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
0327 MODULE_DESCRIPTION("Device node registration for media drivers");
0328 MODULE_LICENSE("GPL");