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