Re: hal, udev and video4linux probers

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

 



On Fri, May 8, 2009 at 10:06 PM, Kay Sievers <kay.sievers@xxxxxxxx> wrote:
> On Fri, 2009-05-08 at 19:04 +0200, Filippo Argiolas wrote:
>> Probably a dedicated Devicekit-video thing
>> would be overengineered for a simple task like this, so udev-extras
>> should be the new place for it.
>
> If you want, try this:
>  $ gcc -Wall -o v4l_id v4l_id.c
>  $ cp v4l_id /lib/udev
>  $ cp 70-v4l_id.rules /lib/udev/rules.d/
>
> After you un-plugged/plugged a device, you will see the properties at
> the device:
>  /sbin/udevadm info --query=env --name=video0
>  ...
>  ID_V4L_VERSION=2
>  ID_V4L_PRODUCT=UVC Camera (17ef:4807)
>  ID_V4L_VIDEO_CAPTURE=1
>  ...

Seems fine to me. Actually I had some spare time this evening and come
up with a similar program myself :P
Glad to see I was almost right on the way to do it. Attaching it here,
feel free to choose the one you like most (yours seems more simple,
probably is better).
Mine lists the capability into a single variable like
ID_V4L_CAPS=capture:radio:tuner and it takes the device path as
argument just because I copied it from usb_id.c :)

>> Being honest I'm not so sure I will use libudev, I'm currently looking
>> for a way to do the device probing directly from gstreamer, but it
>> would be nice to preserve that v4l probing stuff somewhere with HAL
>> going away (furthermore, I doubt we're the only users of that prober).
>
> No sure, how else you can get that information. :)
>
> You can query that properties at program startup with libudev, by
> "enumerate"-ing all video4linux devices.
>
> You can listen to events for new devices with a "monitor", which
> retrieves all new video4linux devices as soon as they are connected.
>
> If the prober is what you are looking for, let me know, and I will put
> it in udev-extras.

Give me some more time to find out if the gstreamer-only way is a
viable one (I'm almost sure I will lose at least the monitor
functionality, I'm not using it at the moment but could be nice).
By the way the HAL prober is copyrighted by Nokia, does anybody know
why they wrote and if there is still anyone using it other than
Cheese?
Maybe it could be worth just adding it into udev-extras anyway so that
there is almost no regression (at least on linux) when HAL will
actually go away.

Cheers,
Filippo
/*
 * v4l_caps - export video4linux capabilities
 *
 * Copyright (c) 2009 Filippo Argiolas
 *
 *	This program is free software; you can redistribute it and/or modify it
 *	under the terms of the GNU General Public License as published by the
 *	Free Software Foundation version 2 of the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <stdint.h>


#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>

#include "../../udev/udev.h"

int debug;

#define SEP     ":"
#define CAPTURE "capture"
#define OUTPUT  "video_output"
#define OVERLAY "video_overlay"
#define AUDIO   "audio"
#define TUNER   "tuner"
#define RADIO   "radio"

static void log_fn(struct udev *udev, int priority,
		   const char *file, int line, const char *fn,
		   const char *format, va_list args)
{
	if (debug) {
		fprintf(stderr, "%s: ", fn != NULL ? fn : file);
		vfprintf(stderr, format, args);
	} else {
		vsyslog(priority, format, args);
	}
}

int main(int argc, char **argv)
{
	static const struct option options[] = {
		{ "export", no_argument, NULL, 'x' },
		{ "debug", no_argument, NULL, 'd' },
		{ "help", no_argument, NULL, 'h' },
		{}
	};
	struct udev *udev;
	struct udev_device *dev = NULL;
        char syspath[UTIL_PATH_SIZE];
	const char *devpath;
	static int export;
        int fd = -1;
        char device[UTIL_NAME_SIZE];
        char subsystem[UTIL_NAME_SIZE];
	struct video_capability v1cap;
	struct v4l2_capability v2cap;
        char *capability = NULL;
        char caps[512] = "";


	udev = udev_new();
	if (udev == NULL)
		goto exit;

	logging_init("v4l_caps");
	udev_set_log_fn(udev, log_fn);

	while (1) {
		int option;

		option = getopt_long(argc, argv, "dxh", options, NULL);
		if (option == -1)
			break;

		switch (option) {
		case 'd':
			debug = 1;
			if (udev_get_log_priority(udev) < LOG_INFO)
				udev_set_log_priority(udev, LOG_INFO);
			break;
		case 'x':
			export = 1;
			break;
		case 'h':
			printf("Usage: v4l_caps [--export] [--help] <devpath>\n"
			       "  --export    print values as environment keys\n"
			       "  --help      print this help text\n\n");
		default:
			goto exit;
		}
	}

	devpath = argv[optind];
	if (devpath == NULL) {
		fprintf(stderr, "No device specified\n");
		goto exit;
	}

	util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath));
	util_strlcat(syspath, devpath, sizeof(syspath));
	dev = udev_device_new_from_syspath(udev, syspath);
	if (dev == NULL) {
		err(udev, "unable to access '%s'\n", devpath);
		return 1;
	}
        util_strlcpy(device, udev_device_get_devnode (dev), sizeof(device));
        util_strlcpy(subsystem, udev_device_get_subsystem (dev), sizeof(subsystem));

        if (strcmp (subsystem, "video4linux") != 0) {
                err(udev, "not a video4linux device\n");
                goto exit;
        }

        if (!export) goto exit;

        fd = open(device, O_RDONLY);
        if (fd < 0) {
		err(udev, "unable to open %s: %s\n", device, strerror (errno));
		goto exit;
	}
        if (ioctl (fd, VIDIOC_QUERYCAP, &v2cap) == 0) {
                printf("ID_V4L_VERSION=%d\n", 2);
                if ((v2cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0) {
                        capability = (strlen(caps) > 0) ? SEP CAPTURE : CAPTURE;
                        util_strlcat (caps, capability, sizeof(caps));
                }
                if ((v2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0) {
                        capability = (strlen(caps) > 0) ? SEP OUTPUT : OUTPUT;
                        util_strlcat (caps, capability, sizeof(caps));
                }
		if ((v2cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) {
                        capability = (strlen(caps) > 0) ? SEP OVERLAY : OVERLAY;
                        util_strlcat (caps, capability, sizeof(caps));
                }
		if ((v2cap.capabilities & V4L2_CAP_AUDIO) > 0) {
                        capability = (strlen(caps) > 0) ? SEP AUDIO : AUDIO;
                        util_strlcat (caps, capability, sizeof(caps));
                }
		if ((v2cap.capabilities & V4L2_CAP_TUNER) > 0) {
                        capability = (strlen(caps) > 0) ? SEP TUNER : TUNER;
                        util_strlcat (caps, capability, sizeof(caps));
                }
		if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0) {
                        capability = (strlen(caps) > 0) ? SEP RADIO : RADIO;
                        util_strlcat (caps, capability, sizeof(caps));
                }
                printf("ID_V4L_CAPABILITIES=%s\n", caps);
        } else {
                info(udev, "VIDIOC_QUERYCAP failed, v4l1 device?\n");
		if (ioctl (fd, VIDIOCGCAP, &v1cap) == 0) {
                        printf("ID_V4L_VERSION=%d\n", 1);
			if ((v1cap.type & VID_TYPE_CAPTURE) > 0) {
                                capability = (strlen(caps) > 0) ? SEP CAPTURE : CAPTURE;
                                util_strlcat (caps, capability, sizeof(caps));
                        }
			if ((v1cap.type & VID_TYPE_OVERLAY) > 0) {
                                capability = (strlen(caps) > 0) ? SEP OVERLAY : OVERLAY;
                                util_strlcat (caps, capability, sizeof(caps));
                        }
			if (v1cap.audios > 0) {
                                capability = (strlen(caps) > 0) ? SEP AUDIO : AUDIO;
                                util_strlcat (caps, capability, sizeof(caps));
                        }
			if ((v1cap.type & VID_TYPE_TUNER) > 0) {
                                capability = (strlen(caps) > 0) ? SEP TUNER : TUNER;
                                util_strlcat (caps, capability, sizeof(caps));
                        }
                        printf("ID_V4L_CAPABILITIES=%s\n", caps);
                }
                else {
                        err(udev, "VIDIOCGCAP failed too. Probably not v4l device\n");
                }
        }

        close (fd);
exit:
	udev_device_unref(dev);
	udev_unref(udev);
	logging_close();
	return 0;
}

[Index of Archives]     [Linux Kernel]     [Linux DVB]     [Asterisk Internet PBX]     [DCCP]     [Netdev]     [X.org]     [Util Linux NG]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux