udev-plugin
Technical documentation
01/20/2011
UDEV [1294879658.960734] add /devices/pci0000:00/0000:00:08.0/video4linux/video0 (video4linux) UDEV_LOG=3 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:08.0/video4linux/video0 SUBSYSTEM=video4linux DEVNAME=/dev/video0 SEQNUM=1380 ID_V4L_VERSION=2 ID_V4L_PRODUCT=Hauppauge WinTV PVR-350 ID_V4L_CAPABILITIES=:capture:video_output:audio:tuner:radio: ID_PATH=pci-0000:00:08.0 ACL_MANAGE=1 MAJOR=81 MINOR=0 DEVLINKS=/dev/char/81:0 /dev/v4l/by-path/pci-0000:00:08.0-video-index0
UDEV [1294879659.237625] add /devices/pci0000:00/0000:00:09.0/dvb/dvb0.frontend0 (dvb) UDEV_LOG=3 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:09.0/dvb/dvb0.frontend0 SUBSYSTEM=dvb DEVNAME=/dev/dvb/adapter0/frontend0 DVB_ADAPTER_NUM=0 DVB_DEVICE_TYPE=frontend DVB_DEVICE_NUM=0 SEQNUM=1396 ACL_MANAGE=1 MAJOR=212 MINOR=3 DEVLINKS=/dev/char/212:3
/*******************************************
libudev example.
This example prints out properties of
each of the hidraw devices. It then
creates a monitor which will report when
hidraw devices are connected or removed
from the system.
This code is meant to be a teaching
resource. It can be used for anyone for
any reason, including embedding into
a commercial product.
The document describing this file, and
updated versions can be found at:
http://www.signal11.us/oss/udev/
Alan Ott
Signal 11 Software
2010-05-22 - Initial Revision
2010-05-27 - Monitoring initializaion
moved to before enumeration.
*******************************************/
#include <libudev.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <unistd.h>
int main (void)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev;
struct udev_monitor *mon;
int fd;
/* Create the udev object */
udev = udev_new();
if (!udev) {
printf("Can't create udev\n");
exit(1);
}
/* This section sets up a monitor which will report events when
devices attached to the system change. Events include "add",
"remove", "change", "online", and "offline".
This section sets up and starts the monitoring. Events are
polled for (and delivered) later in the file.
It is important that the monitor be set up before the call to
udev_enumerate_scan_devices() so that events (and devices) are
not missed. For example, if enumeration happened first, there
would be no event generated for a device which was attached after
enumeration but before monitoring began.
Note that a filter is added so that we only get events for
"hidraw" devices. */
/* Set up a monitor to monitor hidraw devices */
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "hidraw", NULL);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
fd = udev_monitor_get_fd(mon);
/* Create a list of the devices in the 'hidraw' subsystem. */
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
/* For each item enumerated, print out its information.
udev_list_entry_foreach is a macro which expands to
a loop. The loop will be executed for each member in
devices, setting dev_list_entry to a list entry
which contains the device's path in /sys. */
udev_list_entry_foreach(dev_list_entry, devices) {
const char *path;
/* Get the filename of the /sys entry for the device
and create a udev_device object (dev) representing it */
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, path);
/* usb_device_get_devnode() returns the path to the device node
itself in /dev. */
printf("Device Node Path: %s\n", udev_device_get_devnode(dev));
/* The device pointed to by dev contains information about
the hidraw device. In order to get information about the
USB device, get the parent device with the
subsystem/devtype pair of "usb"/"usb_device". This will
be several levels up the tree, but the function will find
it.*/
dev = udev_device_get_parent_with_subsystem_devtype(
dev,
"usb",
"usb_device");
if (!dev) {
printf("Unable to find parent usb device.");
exit(1);
}
/* From here, we can call get_sysattr_value() for each file
in the device's /sys entry. The strings passed into these
functions (idProduct, idVendor, serial, etc.) correspond
directly to the files in the /sys directory which
represents the USB device. Note that USB strings are
Unicode, UCS2 encoded, but the strings returned from
udev_device_get_sysattr_value() are UTF-8 encoded. */
printf(" VID/PID: %s %s\n",
udev_device_get_sysattr_value(dev,"idVendor"),
udev_device_get_sysattr_value(dev, "idProduct"));
printf(" %s\n %s\n",
udev_device_get_sysattr_value(dev,"manufacturer"),
udev_device_get_sysattr_value(dev,"product"));
printf(" serial: %s\n",
udev_device_get_sysattr_value(dev, "serial"));
udev_device_unref(dev);
}
/* Free the enumerator object */
udev_enumerate_unref(enumerate);
/* Begin polling for udev events. Events occur when devices
attached to the system are added, removed, or change state.
udev_monitor_receive_device() will return a device
object representing the device which changed and what type of
change occured.
The select() system call is used to ensure that the call to
udev_monitor_receive_device() will not block.
The monitor was set up earler in this file, and monitoring is
already underway.
This section will run continuously, calling usleep() at the end
of each pass. This is to demonstrate how to use a udev_monitor
in a non-blocking way. */
while (1) {
/* Set up the call to select(). In this case, select() will
only operate on a single file descriptor, the one
associated with our udev_monitor. Note that the timeval
object is set to 0, which will cause select() to not
block. */
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
ret = select(fd+1, &fds, NULL, NULL, &tv);
/* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(fd, &fds)) {
printf("\nselect() says there should be data\n");
/* Make the call to receive the device.
select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
if (dev) {
printf("Got Device\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Subsystem: %s\n", udev_device_get_subsystem(dev));
printf(" Devtype: %s\n", udev_device_get_devtype(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
udev_device_unref(dev);
}
else {
printf("No Device from receive_device(). An error occured.\n");
}
}
usleep(250*1000);
printf(".");
fflush(stdout);
}
udev_unref(udev);
return 0;
}
.......................
select() says there should be data
Got Device
Node: /dev/bus/usb/001/007
Subsystem: usb
Devtype: usb_device
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1
prop{SUBSYSTEM} = usb
prop{DEVNAME} = /dev/bus/usb/001/007
prop{DEVTYPE} = usb_device
prop{PRODUCT} = 7ca/850a/101
prop{TYPE} = 0/0/0
prop{BUSNUM} = 001
prop{DEVNUM} = 007
prop{SEQNUM} = 1666
prop{ID_VENDOR} = AVerMedia
prop{ID_VENDOR_ENC} = AVerMedia
prop{ID_VENDOR_ID} = 07ca
prop{ID_MODEL} = A850_DVBT
prop{ID_MODEL_ENC} = A850\x20DVBT
prop{ID_MODEL_ID} = 850a
prop{ID_REVISION} = 0101
prop{ID_SERIAL} = AVerMedia_A850_DVBT_302471301133000
prop{ID_SERIAL_SHORT} = 302471301133000
prop{ID_BUS} = usb
prop{ID_USB_INTERFACES} = :ff0000:
prop{MAJOR} = 189
prop{MINOR} = 6
prop{DEVLINKS} = /dev/char/189:6
.
select() says there should be data
Got Device
Node: (null)
Subsystem: usb
Devtype: usb_interface
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0
prop{SUBSYSTEM} = usb
prop{DEVTYPE} = usb_interface
prop{PRODUCT} = 7ca/850a/101
prop{TYPE} = 0/0/0
prop{INTERFACE} = 255/0/0
prop{MODALIAS} = usb:v07CAp850Ad0101dc00dsc00dp00icFFisc00ip00
prop{SEQNUM} = 1667
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/dvr0
Subsystem: dvb
Devtype: (null)
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.dvr0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/dvr0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = dvr
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1672
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 1
prop{DEVLINKS} = /dev/char/212:1
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/net0
Subsystem: dvb
Devtype: (null)
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.net0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/net0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = net
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1673
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 2
prop{DEVLINKS} = /dev/char/212:2
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/demux0
Subsystem: dvb
Devtype: (null)
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.demux0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/demux0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = demux
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1671
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 0
prop{DEVLINKS} = /dev/char/212:0
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/frontend0
Subsystem: dvb
Devtype: (null)
Action: add
prop{UDEV_LOG} = 3
prop{ACTION} = add
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.frontend0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/frontend0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = frontend
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1675
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 3
prop{DEVLINKS} = /dev/char/212:3
...............
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/frontend0
Subsystem: dvb
Devtype: (null)
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.frontend0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/frontend0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = frontend
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1677
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 3
prop{DEVLINKS} = /dev/char/212:3
.
select() says there should be data
Got Device
Node: (null)
Subsystem: usb
Devtype: usb_interface
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0
prop{SUBSYSTEM} = usb
prop{DEVTYPE} = usb_interface
prop{PRODUCT} = 7ca/850a/101
prop{TYPE} = 0/0/0
prop{INTERFACE} = 255/0/0
prop{MODALIAS} = usb:v07CAp850Ad0101dc00dsc00dp00icFFisc00ip00
prop{SEQNUM} = 1682
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/dvr0
Subsystem: dvb
Devtype: (null)
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.dvr0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/dvr0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = dvr
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1680
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 1
prop{DEVLINKS} = /dev/char/212:1
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/demux0
Subsystem: dvb
Devtype: (null)
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.demux0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/demux0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = demux
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1679
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 0
prop{DEVLINKS} = /dev/char/212:0
.
select() says there should be data
Got Device
Node: /dev/dvb/adapter0/net0
Subsystem: dvb
Devtype: (null)
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1/dvb/dvb0.net0
prop{SUBSYSTEM} = dvb
prop{DEVNAME} = /dev/dvb/adapter0/net0
prop{DVB_ADAPTER_NUM} = 0
prop{DVB_DEVICE_TYPE} = net
prop{DVB_DEVICE_NUM} = 0
prop{SEQNUM} = 1678
prop{ACL_MANAGE} = 1
prop{MAJOR} = 212
prop{MINOR} = 2
prop{DEVLINKS} = /dev/char/212:2
.
select() says there should be data
Got Device
Node: /dev/bus/usb/001/007
Subsystem: usb
Devtype: usb_device
Action: remove
prop{UDEV_LOG} = 3
prop{ACTION} = remove
prop{DEVPATH} = /devices/pci0000:00/0000:00:1d.7/usb1/1-1
prop{SUBSYSTEM} = usb
prop{DEVNAME} = /dev/bus/usb/001/007
prop{DEVTYPE} = usb_device
prop{PRODUCT} = 7ca/850a/101
prop{TYPE} = 0/0/0
prop{BUSNUM} = 001
prop{DEVNUM} = 007
prop{SEQNUM} = 1683
prop{ID_VENDOR} = AVerMedia
prop{ID_VENDOR_ENC} = AVerMedia
prop{ID_VENDOR_ID} = 07ca
prop{ID_MODEL} = A850_DVBT
prop{ID_MODEL_ENC} = A850\x20DVBT
prop{ID_MODEL_ID} = 850a
prop{ID_REVISION} = 0101
prop{ID_SERIAL} = AVerMedia_A850_DVBT_302471301133000
prop{ID_SERIAL_SHORT} = 302471301133000
prop{ID_BUS} = usb
prop{ID_USB_INTERFACES} = :ff0000:
prop{MAJOR} = 189
prop{MINOR} = 6
prop{DEVLINKS} = /dev/char/189:6