aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrandon@ifup.org <brandon@ifup.org>2008-06-20 21:58:53 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:10:27 -0400
commit539a7555b31e65e66fb84c881d07d2bf18c974d0 (patch)
tree6986fc5c76388c2b07b15911eca0b52100d68f15
parentbbfc4c234e240b67ccd9cdca72d76267bad0dc96 (diff)
V4L/DVB (8078): Introduce "index" attribute for persistent video4linux device nodes
A number of V4L drivers have a mod param to specify their preferred minors. This is because it is often desirable for applications to have a static /dev name for a particular device. However, using minors has several disadvantages: 1) the requested minor may already be taken 2) using a mod param is driver specific 3) it requires every driver to add a param 4) requires configuration by hand This patch introduces an "index" attribute that when combined with udev rules can create static device paths like this: /dev/v4l/by-path/pci-0000\:00\:1d.2-usb-0\:1\:1.0-video0 /dev/v4l/by-path/pci-0000\:00\:1d.2-usb-0\:1\:1.0-video1 /dev/v4l/by-path/pci-0000\:00\:1d.2-usb-0\:1\:1.0-video2 $ ls -la /dev/v4l/by-path/pci-0000\:00\:1d.2-usb-0\:1\:1.0-video0 lrwxrwxrwx 1 root root 12 2008-04-28 00:02 /dev/v4l/by-path/pci-0000:00:1d.2-usb-0:1:1.0-video0 -> ../../video1 These paths are steady across reboots and should be resistant to rearranging across Kernel versions. video_register_device_index is available to drivers to request a specific index number. Signed-off-by: Brandon Philips <bphilips@suse.de> Signed-off-by: Kees Cook <kees@outflux.net> Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/videodev.c98
-rw-r--r--include/media/v4l2-dev.h4
2 files changed, 100 insertions, 2 deletions
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 6cf6ad7193d9..9c539eb33811 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -372,6 +372,14 @@ EXPORT_SYMBOL(v4l_printk_ioctl);
372 * sysfs stuff 372 * sysfs stuff
373 */ 373 */
374 374
375static ssize_t show_index(struct device *cd,
376 struct device_attribute *attr, char *buf)
377{
378 struct video_device *vfd = container_of(cd, struct video_device,
379 class_dev);
380 return sprintf(buf, "%i\n", vfd->index);
381}
382
375static ssize_t show_name(struct device *cd, 383static ssize_t show_name(struct device *cd,
376 struct device_attribute *attr, char *buf) 384 struct device_attribute *attr, char *buf)
377{ 385{
@@ -410,6 +418,7 @@ static void video_release(struct device *cd)
410 418
411static struct device_attribute video_device_attrs[] = { 419static struct device_attribute video_device_attrs[] = {
412 __ATTR(name, S_IRUGO, show_name, NULL), 420 __ATTR(name, S_IRUGO, show_name, NULL),
421 __ATTR(index, S_IRUGO, show_index, NULL),
413 __ATTR_NULL 422 __ATTR_NULL
414}; 423};
415 424
@@ -1900,8 +1909,82 @@ out:
1900} 1909}
1901EXPORT_SYMBOL(video_ioctl2); 1910EXPORT_SYMBOL(video_ioctl2);
1902 1911
1912struct index_info {
1913 struct device *dev;
1914 unsigned int used[VIDEO_NUM_DEVICES];
1915};
1916
1917static int __fill_index_info(struct device *cd, void *data)
1918{
1919 struct index_info *info = data;
1920 struct video_device *vfd = container_of(cd, struct video_device,
1921 class_dev);
1922
1923 if (info->dev == vfd->dev)
1924 info->used[vfd->index] = 1;
1925
1926 return 0;
1927}
1928
1929/**
1930 * assign_index - assign stream number based on parent device
1931 * @vdev: video_device to assign index number to, vdev->dev should be assigned
1932 * @num: -1 if auto assign, requested number otherwise
1933 *
1934 *
1935 * returns -ENFILE if num is already in use, a free index number if
1936 * successful.
1937 */
1938static int get_index(struct video_device *vdev, int num)
1939{
1940 struct index_info *info;
1941 int i;
1942 int ret = 0;
1943
1944 if (num >= VIDEO_NUM_DEVICES)
1945 return -EINVAL;
1946
1947 info = kzalloc(sizeof(*info), GFP_KERNEL);
1948 if (!info)
1949 return -ENOMEM;
1950
1951 info->dev = vdev->dev;
1952
1953 ret = class_for_each_device(&video_class, info,
1954 __fill_index_info);
1955
1956 if (ret < 0)
1957 goto out;
1958
1959 if (num >= 0) {
1960 if (!info->used[num])
1961 ret = num;
1962 else
1963 ret = -ENFILE;
1964
1965 goto out;
1966 }
1967
1968 for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
1969 if (info->used[i])
1970 continue;
1971 ret = i;
1972 goto out;
1973 }
1974
1975out:
1976 kfree(info);
1977 return ret;
1978}
1979
1903static const struct file_operations video_fops; 1980static const struct file_operations video_fops;
1904 1981
1982int video_register_device(struct video_device *vfd, int type, int nr)
1983{
1984 return video_register_device_index(vfd, type, nr, -1);
1985}
1986EXPORT_SYMBOL(video_register_device);
1987
1905/** 1988/**
1906 * video_register_device - register video4linux devices 1989 * video_register_device - register video4linux devices
1907 * @vfd: video device structure we want to register 1990 * @vfd: video device structure we want to register
@@ -1927,7 +2010,8 @@ static const struct file_operations video_fops;
1927 * %VFL_TYPE_RADIO - A radio card 2010 * %VFL_TYPE_RADIO - A radio card
1928 */ 2011 */
1929 2012
1930int video_register_device(struct video_device *vfd, int type, int nr) 2013int video_register_device_index(struct video_device *vfd, int type, int nr,
2014 int index)
1931{ 2015{
1932 int i=0; 2016 int i=0;
1933 int base; 2017 int base;
@@ -1984,6 +2068,16 @@ int video_register_device(struct video_device *vfd, int type, int nr)
1984 } 2068 }
1985 video_device[i]=vfd; 2069 video_device[i]=vfd;
1986 vfd->minor=i; 2070 vfd->minor=i;
2071
2072 ret = get_index(vfd, index);
2073 if (ret < 0) {
2074 printk(KERN_ERR "%s: get_index failed\n",
2075 __func__);
2076 goto fail_minor;
2077 }
2078
2079 vfd->index = ret;
2080
1987 mutex_unlock(&videodev_lock); 2081 mutex_unlock(&videodev_lock);
1988 mutex_init(&vfd->lock); 2082 mutex_init(&vfd->lock);
1989 2083
@@ -2017,7 +2111,7 @@ fail_minor:
2017 mutex_unlock(&videodev_lock); 2111 mutex_unlock(&videodev_lock);
2018 return ret; 2112 return ret;
2019} 2113}
2020EXPORT_SYMBOL(video_register_device); 2114EXPORT_SYMBOL(video_register_device_index);
2021 2115
2022/** 2116/**
2023 * video_unregister_device - unregister a video4linux device 2117 * video_unregister_device - unregister a video4linux device
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 40b0810a595a..9e6e4f18e948 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -96,6 +96,8 @@ struct video_device
96 int type; /* v4l1 */ 96 int type; /* v4l1 */
97 int type2; /* v4l2 */ 97 int type2; /* v4l2 */
98 int minor; 98 int minor;
99 /* attribute to diferentiate multiple indexs on one physical device */
100 int index;
99 101
100 int debug; /* Activates debug level*/ 102 int debug; /* Activates debug level*/
101 103
@@ -347,6 +349,8 @@ void *priv;
347 349
348/* Version 2 functions */ 350/* Version 2 functions */
349extern int video_register_device(struct video_device *vfd, int type, int nr); 351extern int video_register_device(struct video_device *vfd, int type, int nr);
352int video_register_device_index(struct video_device *vfd, int type, int nr,
353 int index);
350void video_unregister_device(struct video_device *); 354void video_unregister_device(struct video_device *);
351extern int video_ioctl2(struct inode *inode, struct file *file, 355extern int video_ioctl2(struct inode *inode, struct file *file,
352 unsigned int cmd, unsigned long arg); 356 unsigned int cmd, unsigned long arg);