diff mbox

[media-ctl,PATCHv4,3/3] libmediactl: get the device name via udev

Message ID 62c72745987f6490497a54512d1569490c173af3.1314968925.git.andriy.shevchenko@linux.intel.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Andy Shevchenko Sept. 2, 2011, 1:09 p.m. UTC
If configured with --with-libudev, the libmediactl is built with libudev
support. It allows to get the device name in right way in the modern linux
systems.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 configure.in    |   22 ++++++++++++++++
 src/Makefile.am |    2 +
 src/media.c     |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/media.h     |    1 +
 4 files changed, 98 insertions(+), 0 deletions(-)

Comments

Laurent Pinchart Sept. 5, 2011, 10:31 a.m. UTC | #1
Hi Andy,

On Friday 02 September 2011 15:09:28 Andy Shevchenko wrote:
> If configured with --with-libudev, the libmediactl is built with libudev
> support. It allows to get the device name in right way in the modern linux
> systems.

Thanks for the patch. We're nearly there :-)

> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  configure.in    |   22 ++++++++++++++++
>  src/Makefile.am |    2 +
>  src/media.c     |   73
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/media.h     | 
>   1 +
>  4 files changed, 98 insertions(+), 0 deletions(-)
> 
> diff --git a/configure.in b/configure.in
> index fd4c70c..983023e 100644
> --- a/configure.in
> +++ b/configure.in
> @@ -13,6 +13,28 @@ AC_PROG_LIBTOOL
> 
>  # Checks for libraries.
> 
> +AC_ARG_WITH([libudev],
> +    AS_HELP_STRING([--with-libudev],
> +        [Enable libudev to detect a device name]))
> +
> +AS_IF([test "x$with_libudev" = "xyes"],
> +    [PKG_CHECK_MODULES(libudev, libudev, have_libudev=yes,
> have_libudev=no)], +    [have_libudev=no])
> +
> +AS_IF([test "x$have_libudev" = "xyes"],
> +    [
> +        AC_DEFINE([HAVE_LIBUDEV], [], [Use libudev])
> +        LIBUDEV_CFLAGS="$libudev_CFLAGS"
> +        LIBUDEV_LIBS="$libudev_LIBS"
> +        AC_SUBST(LIBUDEV_CFLAGS)
> +        AC_SUBST(LIBUDEV_LIBS)
> +    ],
> +    [AS_IF([test "x$with_libudev" = "xyes"],
> +        [AC_MSG_ERROR([libudev requested but not found])
> +    ])
> +])
> +
> +
>  # Kernel headers path.
>  AC_ARG_WITH(kernel-headers,
>      [AC_HELP_STRING([--with-kernel-headers=DIR],
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 267ea83..52628d2 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -5,6 +5,8 @@ mediactl_includedir=$(includedir)/mediactl
>  mediactl_include_HEADERS = media.h subdev.h
> 
>  bin_PROGRAMS = media-ctl
> +media_ctl_CFLAGS = $(LIBUDEV_CFLAGS)
> +media_ctl_LDFLAGS = $(LIBUDEV_LIBS)
>  media_ctl_SOURCES = main.c options.c options.h tools.h
>  media_ctl_LDADD = libmediactl.la libv4l2subdev.la
> 
> diff --git a/src/media.c b/src/media.c
> index 5d3ff7c..dae649a 100644
> --- a/src/media.c
> +++ b/src/media.c
> @@ -17,6 +17,8 @@
>   * with this program; if not, write to the Free Software Foundation, Inc.,
>   */
> 
> +#include "config.h"
> +
>  #include <sys/ioctl.h>
>  #include <sys/stat.h>
>  #include <sys/types.h>
> @@ -245,6 +247,64 @@ static int media_enum_links(struct media_device
> *media) return ret;
>  }
> 
> +#ifdef HAVE_LIBUDEV
> +
> +#include <libudev.h>
> +
> +static inline int media_udev_open(struct media_device *media)
> +{
> +	media->priv = udev_new();
> +	if (media->priv == NULL)
> +		return -ENOMEM;
> +	return 0;
> +}
> +
> +static inline void media_udev_close(struct media_device *media)
> +{
> +	udev_unref(media->priv);
> +}
> +
> +static int media_get_devname_udev(struct media_device *media,
> +		struct media_entity *entity)
> +{
> +	int ret = -ENODEV;
> +	struct udev *udev = media->priv;
> +	dev_t devnum;
> +	struct udev_device *device;
> +	const char *p;
> +
> +	if (udev == NULL)
> +		return -EINVAL;
> +
> +	devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
> +	printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
> +	device = udev_device_new_from_devnum(udev, 'c', devnum);
> +	if (device) {
> +		p = udev_device_get_devnode(device);
> +		if (p)
> +			snprintf(entity->devname, sizeof(entity->devname), "%s", p);
> +		ret = 0;
> +	}
> +
> +	udev_device_unref(device);
> +
> +	return ret;
> +}
> +
> +#else	/* HAVE_LIBUDEV */
> +
> +static inline int media_udev_open(struct media_device *media) { return 0;
> } +
> +static inline void media_udev_close(struct media_device *media) { }
> +
> +static inline int media_get_devname_udev(struct media_device *media,
> +		struct media_entity *entity)
> +{
> +	return -ENOTSUP;
> +}
> +
> +#endif	/* HAVE_LIBUDEV */
> +
>  static int media_get_devname_sysfs(struct media_entity *entity)
>  {
>  	struct stat devstat;
> @@ -324,6 +384,11 @@ static int media_enum_entities(struct media_device
> *media) media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
>  			continue;
> 
> +		/* Try to get the device name via udev */
> +		if (!media_get_devname_udev(media, entity))
> +			continue;
> +
> +		/* Fall back to get the device name via sysfs */
>  		media_get_devname_sysfs(entity);
>  	}
> 
> @@ -351,6 +416,13 @@ struct media_device *media_open(const char *name, int
> verbose) return NULL;
>  	}
> 
> +	ret = media_udev_open(media);
> +	if (ret < 0) {
> +		printf("%s: Can't get udev context\n", __func__);
> +		media_close(media);
> +		return NULL;
> +	}
> +
>  	if (verbose)
>  		printf("Enumerating entities\n");
> 
> @@ -395,6 +467,7 @@ void media_close(struct media_device *media)
>  	}
> 
>  	free(media->entities);
> +	media_udev_close(media);
>  	free(media);
>  }
> 
> diff --git a/src/media.h b/src/media.h
> index b91a2ac..4201451 100644
> --- a/src/media.h
> +++ b/src/media.h
> @@ -54,6 +54,7 @@ struct media_device {
>  	struct media_entity *entities;
>  	unsigned int entities_count;
>  	__u32 padding[6];
> +	void *priv;
>  };
> 
>  /**

This will break binary compatibility if an application creates a struct 
media_device instances itself. On the other hand applications are not supposed 
to do that.

As the struct udev pointer is only used internally, what about passing it 
around between functions explicitly instead ?
Andy Shevchenko Sept. 5, 2011, 2:48 p.m. UTC | #2
On Mon, 2011-09-05 at 12:31 +0200, Laurent Pinchart wrote: 
> Hi Andy,
> 
> On Friday 02 September 2011 15:09:28 Andy Shevchenko wrote:
> > If configured with --with-libudev, the libmediactl is built with libudev
> > support. It allows to get the device name in right way in the modern linux
> > systems.
> 
> Thanks for the patch. We're nearly there :-)
I see.

> This will break binary compatibility if an application creates a struct 
> media_device instances itself. On the other hand applications are not supposed 
> to do that.
> 
> As the struct udev pointer is only used internally, what about passing it 
> around between functions explicitly instead ?
That we will break the API in media_close().
Might be I am a blind, but I can't see the way how to do both 1) don't
provide static global variable and 2) don't break the API/ABI.

So, I'll send 5th version of the patchset with API breakage.
Hope that what you could accept as a final version.
Laurent Pinchart Sept. 5, 2011, 2:57 p.m. UTC | #3
Hi Andy,

On Monday 05 September 2011 16:48:34 Andy Shevchenko wrote:
> On Mon, 2011-09-05 at 12:31 +0200, Laurent Pinchart wrote:
> > Hi Andy,
> > 
> > On Friday 02 September 2011 15:09:28 Andy Shevchenko wrote:
> > > If configured with --with-libudev, the libmediactl is built with
> > > libudev support. It allows to get the device name in right way in the
> > > modern linux systems.
> > 
> > Thanks for the patch. We're nearly there :-)
> 
> I see.
> 
> > This will break binary compatibility if an application creates a struct
> > media_device instances itself. On the other hand applications are not
> > supposed to do that.
> > 
> > As the struct udev pointer is only used internally, what about passing it
> > around between functions explicitly instead ?
> 
> That we will break the API in media_close().
> Might be I am a blind, but I can't see the way how to do both 1) don't
> provide static global variable and 2) don't break the API/ABI.

What about passing the udev pointer explictly to media_enum_entities() (which 
is static), and calling media_udev_close() in media_open() after the 
media_enum_entities() call ?

> So, I'll send 5th version of the patchset with API breakage.
> Hope that what you could accept as a final version.

Sorry for making it so difficult :-/
Andy Shevchenko Sept. 6, 2011, 8:14 a.m. UTC | #4
On Mon, 2011-09-05 at 16:57 +0200, Laurent Pinchart wrote: 
> > > This will break binary compatibility if an application creates a struct
> > > media_device instances itself. On the other hand applications are not
> > > supposed to do that.
> > > 
> > > As the struct udev pointer is only used internally, what about passing it
> > > around between functions explicitly instead ?
> > 
> > That we will break the API in media_close().
> > Might be I am a blind, but I can't see the way how to do both 1) don't
> > provide static global variable and 2) don't break the API/ABI.
> 
> What about passing the udev pointer explictly to media_enum_entities() (which 
> is static), and calling media_udev_close() in media_open() after the 
> media_enum_entities() call ?
I sent the patch series that incorporates your last comments.
diff mbox

Patch

diff --git a/configure.in b/configure.in
index fd4c70c..983023e 100644
--- a/configure.in
+++ b/configure.in
@@ -13,6 +13,28 @@  AC_PROG_LIBTOOL
 
 # Checks for libraries.
 
+AC_ARG_WITH([libudev],
+    AS_HELP_STRING([--with-libudev],
+        [Enable libudev to detect a device name]))
+
+AS_IF([test "x$with_libudev" = "xyes"],
+    [PKG_CHECK_MODULES(libudev, libudev, have_libudev=yes, have_libudev=no)],
+    [have_libudev=no])
+
+AS_IF([test "x$have_libudev" = "xyes"],
+    [
+        AC_DEFINE([HAVE_LIBUDEV], [], [Use libudev])
+        LIBUDEV_CFLAGS="$libudev_CFLAGS"
+        LIBUDEV_LIBS="$libudev_LIBS"
+        AC_SUBST(LIBUDEV_CFLAGS)
+        AC_SUBST(LIBUDEV_LIBS)
+    ],
+    [AS_IF([test "x$with_libudev" = "xyes"],
+        [AC_MSG_ERROR([libudev requested but not found])
+    ])
+])
+
+
 # Kernel headers path.
 AC_ARG_WITH(kernel-headers,
     [AC_HELP_STRING([--with-kernel-headers=DIR],
diff --git a/src/Makefile.am b/src/Makefile.am
index 267ea83..52628d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,8 @@  mediactl_includedir=$(includedir)/mediactl
 mediactl_include_HEADERS = media.h subdev.h
 
 bin_PROGRAMS = media-ctl
+media_ctl_CFLAGS = $(LIBUDEV_CFLAGS)
+media_ctl_LDFLAGS = $(LIBUDEV_LIBS)
 media_ctl_SOURCES = main.c options.c options.h tools.h
 media_ctl_LDADD = libmediactl.la libv4l2subdev.la
 
diff --git a/src/media.c b/src/media.c
index 5d3ff7c..dae649a 100644
--- a/src/media.c
+++ b/src/media.c
@@ -17,6 +17,8 @@ 
  * with this program; if not, write to the Free Software Foundation, Inc.,
  */
 
+#include "config.h"
+
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -245,6 +247,64 @@  static int media_enum_links(struct media_device *media)
 	return ret;
 }
 
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int media_udev_open(struct media_device *media)
+{
+	media->priv = udev_new();
+	if (media->priv == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static inline void media_udev_close(struct media_device *media)
+{
+	udev_unref(media->priv);
+}
+
+static int media_get_devname_udev(struct media_device *media,
+		struct media_entity *entity)
+{
+	int ret = -ENODEV;
+	struct udev *udev = media->priv;
+	dev_t devnum;
+	struct udev_device *device;
+	const char *p;
+
+	if (udev == NULL)
+		return -EINVAL;
+
+	devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+	printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+	device = udev_device_new_from_devnum(udev, 'c', devnum);
+	if (device) {
+		p = udev_device_get_devnode(device);
+		if (p)
+			snprintf(entity->devname, sizeof(entity->devname), "%s", p);
+		ret = 0;
+	}
+
+	udev_device_unref(device);
+
+	return ret;
+}
+
+#else	/* HAVE_LIBUDEV */
+
+static inline int media_udev_open(struct media_device *media) { return 0; }
+
+static inline void media_udev_close(struct media_device *media) { }
+
+static inline int media_get_devname_udev(struct media_device *media,
+		struct media_entity *entity)
+{
+	return -ENOTSUP;
+}
+
+#endif	/* HAVE_LIBUDEV */
+
 static int media_get_devname_sysfs(struct media_entity *entity)
 {
 	struct stat devstat;
@@ -324,6 +384,11 @@  static int media_enum_entities(struct media_device *media)
 		    media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
 			continue;
 
+		/* Try to get the device name via udev */
+		if (!media_get_devname_udev(media, entity))
+			continue;
+
+		/* Fall back to get the device name via sysfs */
 		media_get_devname_sysfs(entity);
 	}
 
@@ -351,6 +416,13 @@  struct media_device *media_open(const char *name, int verbose)
 		return NULL;
 	}
 
+	ret = media_udev_open(media);
+	if (ret < 0) {
+		printf("%s: Can't get udev context\n", __func__);
+		media_close(media);
+		return NULL;
+	}
+
 	if (verbose)
 		printf("Enumerating entities\n");
 
@@ -395,6 +467,7 @@  void media_close(struct media_device *media)
 	}
 
 	free(media->entities);
+	media_udev_close(media);
 	free(media);
 }
 
diff --git a/src/media.h b/src/media.h
index b91a2ac..4201451 100644
--- a/src/media.h
+++ b/src/media.h
@@ -54,6 +54,7 @@  struct media_device {
 	struct media_entity *entities;
 	unsigned int entities_count;
 	__u32 padding[6];
+	void *priv;
 };
 
 /**