Re: [PATCH v4l-utils v7 4/7] mediactl: Add media_device creation helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jacek,

On Thu, Nov 24, 2016 at 02:50:39PM +0100, Jacek Anaszewski wrote:
> Hi Sakari,
> 
> Thanks for the review.
> 
> On 11/24/2016 01:17 PM, Sakari Ailus wrote:
> >Hi Jacek,
> >
> >Thanks for the patchset.
> >
> >On Wed, Oct 12, 2016 at 04:35:19PM +0200, Jacek Anaszewski wrote:
> >>Add helper functions that allow for easy instantiation of media_device
> >>object basing on whether the media device contains v4l2 subdev with
> >>given file descriptor.
> >
> >Doesn't this work with video nodes as well? That's what you seem to be using
> >it for later on. And I think that's actually more useful.
> 
> Exactly, thanks for spotting this.
> 
> s/v4l2 subdev/video device opened/
> 
> >
> >The existing implementation uses udev to look up devices. Could you use
> >libudev device enumeration API to find the media devices, and fall back to
> >sysfs if udev doesn't work? There seems to be a reasonable-looking example
> >here:
> >
> ><URL:http://stackoverflow.com/questions/25361042/how-to-list-usb-mass-storage-devices-programatically-using-libudev-in-linux>
> 
> I'll check that, thanks.
> 
> >>
> >>Signed-off-by: Jacek Anaszewski <j.anaszewski@xxxxxxxxxxx>
> >>Acked-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
> >>---
> >> utils/media-ctl/libmediactl.c | 131 +++++++++++++++++++++++++++++++++++++++++-
> >> utils/media-ctl/mediactl.h    |  27 +++++++++
> >> 2 files changed, 156 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/utils/media-ctl/libmediactl.c b/utils/media-ctl/libmediactl.c
> >>index 155b65f..d347a40 100644
> >>--- a/utils/media-ctl/libmediactl.c
> >>+++ b/utils/media-ctl/libmediactl.c
> >>@@ -27,6 +27,7 @@
> >> #include <sys/sysmacros.h>
> >>
> >> #include <ctype.h>
> >>+#include <dirent.h>
> >> #include <errno.h>
> >> #include <fcntl.h>
> >> #include <stdbool.h>
> >>@@ -440,8 +441,9 @@ static int media_get_devname_udev(struct udev *udev,
> >> 		return -EINVAL;
> >>
> >> 	devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
> >>-	media_dbg(entity->media, "looking up device: %u:%u\n",
> >>-		  major(devnum), minor(devnum));
> >>+	if (entity->media)
> >>+		media_dbg(entity->media, "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);
> >>@@ -523,6 +525,7 @@ static int media_get_devname_sysfs(struct media_entity *entity)
> >> 	return 0;
> >> }
> >>
> >>+
> >
> >Unrelated change.
> >
> >> static int media_enum_entities(struct media_device *media)
> >> {
> >> 	struct media_entity *entity;
> >>@@ -707,6 +710,92 @@ struct media_device *media_device_new(const char *devnode)
> >> 	return media;
> >> }
> >>
> >>+struct media_device *media_device_new_by_subdev_fd(int fd, struct media_entity **fd_entity)
> >>+{
> >>+	char video_devname[32], device_dir_path[256], media_dev_path[256], media_major_minor[10];
> >>+	struct media_device *media = NULL;
> >>+	struct dirent *entry;
> >>+	struct media_entity tmp_entity;
> >>+	DIR *device_dir;
> >>+	struct udev *udev;
> >>+	char *p;
> >>+	int ret, i;
> >>+
> >>+	if (fd_entity == NULL)
> >>+		return NULL;
> >>+
> >>+	ret = media_get_devname_by_fd(fd, video_devname);
> >>+	if (ret < 0)
> >>+		return NULL;
> >>+
> >>+	p = strrchr(video_devname, '/');
> >>+	if (p == NULL)
> >>+		return NULL;
> >>+
> >>+	ret = media_udev_open(&udev);
> >>+	if (ret < 0)
> >>+		return NULL;
> >>+
> >>+	sprintf(device_dir_path, "/sys/class/video4linux/%s/device/", p + 1);
> >>+
> >>+	device_dir = opendir(device_dir_path);
> >>+	if (device_dir == NULL)
> >>+		return NULL;
> >>+
> >>+	while ((entry = readdir(device_dir))) {
> >>+		if (strncmp(entry->d_name, "media", 4))
> >
> >Why 4? And isn't entry->d_name nul-terminated, so you could use strcmp()?
> 
> Media devices, as other devices, have numerical postfix, which is
> not of our interest.

Right. But still 5 would be the right number as we should also check the
last "a".

> 
> >>+			continue;
> >>+
> >>+		sprintf(media_dev_path, "%s%s/dev", device_dir_path, entry->d_name);
> >>+
> >>+		fd = open(media_dev_path, O_RDONLY);
> >>+		if (fd < 0)
> >>+			continue;
> >>+
> >>+		ret = read(fd, media_major_minor, sizeof(media_major_minor));
> >>+		if (ret < 0)
> >>+			continue;
> >>+
> >>+		sscanf(media_major_minor, "%d:%d", &tmp_entity.info.dev.major, &tmp_entity.info.dev.minor);
> >
> >This would be better split on two lines.
> 
> OK.
> 
> >>+
> >>+		/* Try to get the device name via udev */
> >>+		if (media_get_devname_udev(udev, &tmp_entity)) {
> >>+			/* Fall back to get the device name via sysfs */
> >>+			if (media_get_devname_sysfs(&tmp_entity))
> >>+				continue;
> >>+		}
> >>+
> >>+		media = media_device_new(tmp_entity.devname);
> >>+		if (media == NULL)
> >>+			continue;
> >>+
> >>+		ret = media_device_enumerate(media);
> >>+		if (ret < 0) {
> >>+			media_dbg(media, "Failed to enumerate %s (%d)\n",
> >>+				  tmp_entity.devname, ret);
> >>+			media_device_unref(media);
> >>+			media = NULL;
> >>+			continue;
> >>+		}
> >>+
> >>+		/* Get the entity associated with given fd */
> >>+		for (i = 0; i < media->entities_count; i++) {
> >>+			struct media_entity *entity = &media->entities[i];
> >>+
> >>+			if (!strcmp(entity->devname, video_devname)) {
> >>+				*fd_entity = &media->entities[i];
> >>+				break;
> >>+			}
> >>+		}
> >
> >What if you exit the loop without finding the entity you were looking for?
> 
> Ah, right, this case is unhandled.
> 
> Adding below condition should cover that:
> 
> if (i == media->entities_count)
>     media = NULL;

and media_device_unref()?

You could have a label for handling that at the end of the loop basic block
so you could implement handling of that just once to avoid such issues in
the future.

> 
> >>+
> >>+		break;
> 
> This break should be removed and the one in the inner for loop above
> should be replaced with goto here. Are you OK with that?

Um, yeah. There are indeed two loops. In Perl you could get out nicely but
in C we have to do something else. Two labels perhaps?

> 
> >>+	}
> >>+
> >>+	media_udev_close(udev);
> >>+
> >>+	return media;
> >>+}
> >>+
> >> struct media_device *media_device_new_emulated(struct media_device_info *info)
> >> {
> >> 	struct media_device *media;

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@xxxxxx	XMPP: sailus@xxxxxxxxxxxxxx
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux