udev_device_get_property_value и udev_device_get_sysattr_value возвращают null
для атрибутов дескриптора udev, таких как VID, PID, серийный номер в последних ядрах Linux (Ubuntu 18.04, CentOS 7 с ядром версии 4.2 и выше). Следующая программа работает нормально со всеми дистрибутивами со старыми версиями ядра, но не с более новыми версиями ядра.
/* List and monitor USB devices using libudev.
* *
* * gcc -o udev_monitor_usb udev_monitor_usb.c -ludev
* * ./udev_monitor_usb
* */
#include <libudev.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define SUBSYSTEM "usb"
static void print_device(struct udev_device* dev)
{
const char* action = udev_device_get_action(dev);
if (! action)
action = "exists";
const char* vendor = udev_device_get_sysattr_value(dev, "idVendor");
if (! vendor)
vendor = "0000";
const char* product = udev_device_get_sysattr_value(dev, "idProduct");
if (! product)
product = "0000";
printf("\n*****************************************************\n");
printf("****** using : udev_device_get_sysattr_value \n");
printf("VID/PID: %s %s\n", udev_device_get_sysattr_value(dev, "idVendor"),
udev_device_get_sysattr_value(dev, "idProduct"));
printf("manufacturer & Product: %s %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"));
printf("*****************************************************\n");
/**struct udev_list_entry *devs, *devs_list_entry;
devs = udev_device_get_sysattr_list_entry( dev );
udev_list_entry_foreach( devs_list_entry, devs )
{
const char *attr;
attr = udev_list_entry_get_name( devs_list_entry );
printf("Attribute name: %s\n", attr);
}*/
printf("****** using : udev_device_get_property_value \n");
const char *pid = NULL;
pid = udev_device_get_property_value(dev, "ID_MODEL_ID");
if(NULL != pid)
{
printf("PID is :%s\n", pid);
}
else
{
printf("PID is NULL: %s\n", pid);
}
const char *vid = NULL;
vid = udev_device_get_property_value(dev, "ID_VENDOR_ID");
if(NULL != vid)
{
printf("VID is :%s\n", vid);
}
else
{
char *errorCode = strerror(errno);
printf("strerror: %s\n", errorCode);
printf("VID is NULL: %s\n", vid);
}
printf("*****************************************************\n");
printf("%s %s %6s %s:%s %s\n",
udev_device_get_subsystem(dev),
udev_device_get_devtype(dev),
action,
vendor,
product,
udev_device_get_devnode(dev));
}
static void process_device(struct udev_device* dev)
{
if (dev) {
if (udev_device_get_devnode(dev))
print_device(dev);
udev_device_unref(dev);
}
}
static void enumerate_devices(struct udev* udev)
{
struct udev_enumerate* enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, SUBSYSTEM);
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry* entry;
udev_list_entry_foreach(entry, devices) {
const char* path = udev_list_entry_get_name(entry);
struct udev_device* dev = udev_device_new_from_syspath(udev, path);
process_device(dev);
}
udev_enumerate_unref(enumerate);
}
static void monitor_devices(struct udev* udev)
{
struct udev_monitor* mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, SUBSYSTEM, "usb_device");
udev_monitor_enable_receiving(mon);
int fd = udev_monitor_get_fd(mon);
while (1) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
int ret = select(fd+1, &fds, NULL, NULL, NULL);
if (ret <= 0)
break;
if (FD_ISSET(fd, &fds)) {
struct udev_device* dev = udev_monitor_receive_device(mon);
process_device(dev);
}
}
}
int main(void)
{
struct udev* udev = udev_new();
if (!udev) {
fprintf(stderr, "udev_new() failed\n");
return 1;
}
enumerate_devices(udev);
monitor_devices(udev);
udev_unref(udev);
return 0;
}
Программа выдает следующий вывод на Ubuntu 18.04 (ядро 4.15.0-20-generic) при отключении USB-устройства
*****************************************************
****** using : udev_device_get_sysattr_value
VID/PID: (null) (null)
manufacturer & Product: (null) (null)
Serial: (null)
*****************************************************
****** using : udev_device_get_property_value
PID is NULL: (null)
strerror: No such file or directory
VID is NULL: (null)
*****************************************************
usb usb_device unbind 0000:0000 /dev/bus/usb/003/007
*****************************************************
****** using : udev_device_get_sysattr_value
VID/PID: (null) (null)
manufacturer & Product: (null) (null)
Serial: (null)
*****************************************************
****** using : udev_device_get_property_value
PID is NULL: (null)
strerror: No such file or directory
VID is NULL: (null)
*****************************************************
usb usb_device remove 0000:0000 /dev/bus/usb/003/007
есть 2 события, сгенерированные udev, которые называются remove и unbind. значения, заданные как {null} для обоих событий.
из-за этого я не могу уничтожить использованные объекты при отсоединении устройства. я делаю неправильный способ получить значения атрибута?