コード例 #1
0
QString Device::driver() const
{
    if (!d)
        return QString();

    return QString::fromLatin1(udev_device_get_driver(d->udev));
}
コード例 #2
0
ファイル: udevadm-info.c プロジェクト: kwirk/systemd
static int print_device_chain(struct udev_device *device)
{
        struct udev_device *device_parent;
        const char *str;

        printf("\n"
               "Udevadm info starts with the device specified by the devpath and then\n"
               "walks up the chain of parent devices. It prints for every device\n"
               "found, all possible attributes in the udev rules key format.\n"
               "A rule to match, can be composed by the attributes of the device\n"
               "and the attributes from one single parent device.\n"
               "\n");

        printf("  looking at device '%s':\n", udev_device_get_devpath(device));
        printf("    KERNEL==\"%s\"\n", udev_device_get_sysname(device));
        str = udev_device_get_subsystem(device);
        if (str == NULL)
                str = "";
        printf("    SUBSYSTEM==\"%s\"\n", str);
        str = udev_device_get_driver(device);
        if (str == NULL)
                str = "";
        printf("    DRIVER==\"%s\"\n", str);
        print_all_attributes(device, "ATTR");

        device_parent = device;
        do {
                device_parent = udev_device_get_parent(device_parent);
                if (device_parent == NULL)
                        break;
                printf("  looking at parent device '%s':\n", udev_device_get_devpath(device_parent));
                printf("    KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent));
                str = udev_device_get_subsystem(device_parent);
                if (str == NULL)
                        str = "";
                printf("    SUBSYSTEMS==\"%s\"\n", str);
                str = udev_device_get_driver(device_parent);
                if (str == NULL)
                        str = "";
                printf("    DRIVERS==\"%s\"\n", str);
                print_all_attributes(device_parent, "ATTRS");
        } while (device_parent != NULL);

        return 0;
}
コード例 #3
0
ファイル: test-libudev.c プロジェクト: samveen/uselessd
static void print_device(struct udev_device *device)
{
    const char *str;
    dev_t devnum;
    int count;
    struct udev_list_entry *list_entry;

    printf("*** device: %p ***\n", device);
    str = udev_device_get_action(device);
    if (str != NULL)
        printf("action:    '%s'\n", str);

    str = udev_device_get_syspath(device);
    printf("syspath:   '%s'\n", str);

    str = udev_device_get_sysname(device);
    printf("sysname:   '%s'\n", str);

    str = udev_device_get_sysnum(device);
    if (str != NULL)
        printf("sysnum:    '%s'\n", str);

    str = udev_device_get_devpath(device);
    printf("devpath:   '%s'\n", str);

    str = udev_device_get_subsystem(device);
    if (str != NULL)
        printf("subsystem: '%s'\n", str);

    str = udev_device_get_devtype(device);
    if (str != NULL)
        printf("devtype:   '%s'\n", str);

    str = udev_device_get_driver(device);
    if (str != NULL)
        printf("driver:    '%s'\n", str);

    str = udev_device_get_devnode(device);
    if (str != NULL)
        printf("devname:   '%s'\n", str);

    devnum = udev_device_get_devnum(device);
    if (major(devnum) > 0)
        printf("devnum:    %u:%u\n", major(devnum), minor(devnum));

    count = 0;
    udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
        printf("link:      '%s'\n", udev_list_entry_get_name(list_entry));
        count++;
    }
コード例 #4
0
ファイル: udev.cpp プロジェクト: theopolis/osquery
UdevEventContextRef UdevEventPublisher::createEventContextFrom(
    struct udev_device* device) {
  auto ec = createEventContext();
  ec->device = device;
  // Map the action string to the eventing enum.
  ec->action = UDEV_EVENT_ACTION_UNKNOWN;
  ec->action_string = std::string(udev_device_get_action(device));
  if (ec->action_string == "add") {
    ec->action = UDEV_EVENT_ACTION_ADD;
  } else if (ec->action_string == "remove") {
    ec->action = UDEV_EVENT_ACTION_REMOVE;
  } else if (ec->action_string == "change") {
    ec->action = UDEV_EVENT_ACTION_CHANGE;
  }

  // Set the subscription-aware variables for the event.
  auto value = udev_device_get_subsystem(device);
  if (value != nullptr) {
    ec->subsystem = std::string(value);
  }

  value = udev_device_get_devnode(device);
  if (value != nullptr) {
    ec->devnode = std::string(value);
  }

  value = udev_device_get_devtype(device);
  if (value != nullptr) {
    ec->devtype = std::string(value);
  }

  value = udev_device_get_driver(device);
  if (value != nullptr) {
    ec->driver = std::string(value);
  }

  return ec;
}
コード例 #5
0
ファイル: wiimote-pad.c プロジェクト: BadDude/wiimote-pad
int dev_create(struct wiimote_dev *dev) {
	int ret = 0;
	struct udev *udev;
	struct udev_device *d, *p;
	struct stat st;
	const char *root, *snum, *driver, *subs;
	int num;

	if (!dev->device) {
		ret = EINVAL;
		goto exit;
	}

	if (stat(dev->device, &st)) {
		ret = errno;
		goto exit;
	}

	udev = udev_new();
	if (!udev) {
		fputs("could not connect to udev\n", stderr);
		ret = errno;
		goto exit;
	}

	d = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
	if (!d) {
		fputs("could not find udev device\n", stderr);
		ret = errno;
		goto exit_udev;
	}

	p = udev_device_get_parent_with_subsystem_devtype(d, "hid", NULL);
	if (!p) {
		fputs("could not find parent HID device\n", stderr);
		ret = errno;
		goto exit_dev;
	}

	driver = udev_device_get_driver(p);
	subs = udev_device_get_subsystem(p);
	if (!driver || strcmp(driver, "wiimote") || !subs || strcmp(subs, "hid")) {
		fputs("parent is not a HID Wiimote\n", stderr);
		ret = errno;
		goto exit_dev;
	}

	root = udev_device_get_syspath(p);
	snum = udev_device_get_sysname(p);
	snum = snum ? strchr(snum, '.') : NULL;
	if (!root || !snum) {
		fputs("Could not get root path\n", stderr);
		ret = errno;
		goto exit_dev;
	}

	num = strtol(&snum[1], NULL, 16);
	if (num < 0) {
		fputs("Negative device number!\n", stderr);
		ret = errno;
		goto exit_dev;
	}
	dev->dev_id = num;

	dev->root = strdup(root);
	if (!dev->root) {
		fputs("Could not set device root\n", stderr);
		ret = errno;
		goto exit_dev;
	}

	printf("using device %d from root %s for %s\n",
		dev->dev_id, dev->root, dev->device);

	dev->ifs = XWII_IFACE_CORE | XWII_IFACE_ACCEL;
	ret = xwii_iface_new(&dev->iface, dev->root);
	if (ret) {
		fputs("Could not create xwiimote interface\n", stderr);
		ret = errno;
		goto exit_wii;
	}

	ret = xwii_iface_open(dev->iface, dev->ifs);
	if (ret) {
		fputs("Could not open xwiimote interface\n", stderr);
		ret = errno;
		goto exit_wii;
	}
	if (xwii_iface_opened(dev->iface) != dev->ifs) {
		fputs("Some interfaces failed to open\n", stderr);
		ret = errno;
		goto exit_wii;
	}

	dev->fd = xwii_iface_get_fd(dev->iface);

	goto exit_dev;

exit_wii:
	free(dev->root);
	dev->root = NULL;

exit_dev:
	udev_device_unref(d);
exit_udev:
	udev_unref(udev);
exit:
	return ret;
}
コード例 #6
0
ファイル: usbip_bind.c プロジェクト: 020gzh/linux
/* buggy driver may cause dead lock */
static int unbind_other(char *busid)
{
	enum unbind_status status = UNBIND_ST_OK;

	char attr_name[] = "unbind";
	char unbind_attr_path[SYSFS_PATH_MAX];
	int rc = -1;

	struct udev *udev;
	struct udev_device *dev;
	const char *driver;
	const char *bDevClass;

	/* Create libudev context. */
	udev = udev_new();

	/* Get the device. */
	dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
	if (!dev) {
		dbg("unable to find device with bus ID %s", busid);
		goto err_close_busid_dev;
	}

	/* Check what kind of device it is. */
	bDevClass  = udev_device_get_sysattr_value(dev, "bDeviceClass");
	if (!bDevClass) {
		dbg("unable to get bDevClass device attribute");
		goto err_close_busid_dev;
	}

	if (!strncmp(bDevClass, "09", strlen(bDevClass))) {
		dbg("skip unbinding of hub");
		goto err_close_busid_dev;
	}

	/* Get the device driver. */
	driver = udev_device_get_driver(dev);
	if (!driver) {
		/* No driver bound to this device. */
		goto out;
	}

	if (!strncmp(USBIP_HOST_DRV_NAME, driver,
				strlen(USBIP_HOST_DRV_NAME))) {
		/* Already bound to usbip-host. */
		status = UNBIND_ST_USBIP_HOST;
		goto out;
	}

	/* Unbind device from driver. */
	snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
		 SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
		 SYSFS_DRIVERS_NAME, driver, attr_name);

	rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
	if (rc < 0) {
		err("error unbinding device %s from driver", busid);
		goto err_close_busid_dev;
	}

	goto out;

err_close_busid_dev:
	status = UNBIND_ST_FAILED;
out:
	udev_device_unref(dev);
	udev_unref(udev);

	return status;
}
コード例 #7
0
/*
 * Find the name of the driver which is currently associated with the given HID device.
 *
 * A HID device can be on usb, bluetooth or pseudo. For Linux we walk down the
 * sysfs tree until a driver is found for the given device node.
 */
jstring linux_find_driver_for_given_hiddevice(JNIEnv *env, jstring hidDevNode) {

	const char* hid_name_to_match = NULL;
	jstring driver_name = NULL;
	int check_for_parent = -1;
	struct udev *udev_ctx;
	struct udev_enumerate *enumerator;
	struct udev_list_entry *devices, *dev_list_entry;
	const char *prop_val_driver_name;
	const char *device_node;
	const char *path;
	struct udev_device *udev_device;
	struct udev_device *parent_device;

	hid_name_to_match = (*env)->GetStringUTFChars(env, hidDevNode, NULL);
	if((hid_name_to_match == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR);
		return NULL;
	}

	udev_ctx = udev_new();
	enumerator = udev_enumerate_new(udev_ctx);
	udev_enumerate_add_match_subsystem(enumerator, "hidraw");
	udev_enumerate_scan_devices(enumerator);
	devices = udev_enumerate_get_list_entry(enumerator);

	udev_list_entry_foreach(dev_list_entry, devices) {

		/* from the sysfs filename create a udev_device object representing it. */
		path = udev_list_entry_get_name(dev_list_entry);
		udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path);
		if(udev_device == NULL) {
			continue;
		}

		/* get the device node for this udev device. */
		device_node = udev_device_get_devnode(udev_device);

		/* If the device node name matches what we are looking for get driver for it.
		 * if we fail to get driver name than return empty string (prop_val_driver_name
		 * will be NULL when control reaches at the end of this function). */
		if(device_node != NULL) {
			if(strcmp(hid_name_to_match, device_node) == 0) {
				prop_val_driver_name = udev_device_get_driver(udev_device);
				if(prop_val_driver_name != NULL) {
					driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
					if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						(*env)->ExceptionClear(env);
						udev_device_unref(udev_device);
						udev_enumerate_unref(enumerator);
						udev_unref(udev_ctx);
						(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
						throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
						return NULL;
					}
					check_for_parent = -1;
				}else {
					check_for_parent = 1;
				}

				if(check_for_parent == 1) {
					parent_device = udev_device_get_parent(udev_device);
					if(parent_device != NULL) {
						prop_val_driver_name = udev_device_get_driver(parent_device);
						if(prop_val_driver_name != NULL) {
							driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
							if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
								(*env)->ExceptionClear(env);
								udev_device_unref(udev_device);
								udev_enumerate_unref(enumerator);
								udev_unref(udev_ctx);
								(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
								throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
								return NULL;
							}else {
								/* if both the parent and driver found, return driver name to caller. */
								check_for_parent = -1;
							}
						}else {
							/* if the parent is found but driver not found then analyze next parent device. */
							check_for_parent = 1;
						}
					}else {
						/* if the parent does not exist, make no more attempts to analyze parent devices further down the tree. */
						check_for_parent = -1;
					}
				}

				if(check_for_parent == 1) {
					parent_device = udev_device_get_parent(parent_device );
					if(parent_device != NULL) {
						prop_val_driver_name = udev_device_get_driver(parent_device);
						if(prop_val_driver_name != NULL) {
							driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
							if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
								(*env)->ExceptionClear(env);
								udev_device_unref(udev_device);
								udev_enumerate_unref(enumerator);
								udev_unref(udev_ctx);
								(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
								throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
								return NULL;
							}else {
								check_for_parent = -1;
							}
						}else {
							check_for_parent = 1;
						}
					}else {
						check_for_parent = -1;
					}
				}

				if(check_for_parent == 1) {
					parent_device = udev_device_get_parent(parent_device);
					if(parent_device != NULL) {
						prop_val_driver_name = udev_device_get_driver(parent_device);
						if(prop_val_driver_name != NULL) {
							driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
							if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
								(*env)->ExceptionClear(env);
								udev_device_unref(udev_device);
								udev_enumerate_unref(enumerator);
								udev_unref(udev_ctx);
								(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
								throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
								return NULL;
							}else {
								check_for_parent = -1;
							}
						}else {
							check_for_parent = 1;
						}
					}else {
						check_for_parent = -1;
					}
				}

				if(check_for_parent == 1) {
					parent_device = udev_device_get_parent(udev_device);
					if(parent_device != NULL) {
						prop_val_driver_name = udev_device_get_driver(parent_device );
						if(prop_val_driver_name != NULL) {
							driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
							if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
								(*env)->ExceptionClear(env);
								udev_device_unref(udev_device);
								udev_enumerate_unref(enumerator);
								udev_unref(udev_ctx);
								(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
								throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
								return NULL;
							}else {
								check_for_parent = -1;
							}
						}else {
							check_for_parent = 1;
						}
					}else {
						check_for_parent = -1;
					}
				}

				if(check_for_parent == 1) {
					parent_device = udev_device_get_parent(parent_device);
					if(parent_device != NULL) {
						prop_val_driver_name = udev_device_get_driver(parent_device);
						if(prop_val_driver_name != NULL) {
							driver_name = (*env)->NewStringUTF(env, prop_val_driver_name);
							if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
								(*env)->ExceptionClear(env);
								udev_device_unref(udev_device);
								udev_enumerate_unref(enumerator);
								udev_unref(udev_ctx);
								(*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match);
								throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
								return NULL;
							}
						}
					}
				}

				/* whether prop_val_driver_name is NULL (return empty string) or not
				 * (return driver name found), no more iteration is needed. */
				udev_device_unref(udev_device);
				break;
			}
		}

		/* released only after desired property value has been saved to some
		 * other memory region like one got from NewStringUTF(). */
		udev_device_unref(udev_device);
	}
コード例 #8
0
ファイル: udev_subsystem.cpp プロジェクト: brojudd/ubuntu
void
UdevSubsystem::print_info(udev_device* device)
{
  log_debug("/---------------------------------------------");
  log_debug("devpath: " << udev_device_get_devpath(device));

  if (udev_device_get_action(device))
    log_debug("action: " << udev_device_get_action(device));
  //log_debug("init: " << udev_device_get_is_initialized(device));

  if (udev_device_get_subsystem(device))
    log_debug("subsystem: " << udev_device_get_subsystem(device));

  if (udev_device_get_devtype(device))
    log_debug("devtype:   " << udev_device_get_devtype(device));

  if (udev_device_get_syspath(device))
    log_debug("syspath:   " << udev_device_get_syspath(device));

  if (udev_device_get_sysname(device))
    log_debug("sysname:   " << udev_device_get_sysname(device));

  if (udev_device_get_sysnum(device))
    log_debug("sysnum:    " << udev_device_get_sysnum(device));

  if (udev_device_get_devnode(device))
    log_debug("devnode:   " << udev_device_get_devnode(device));

  if (udev_device_get_driver(device))
    log_debug("driver:    " << udev_device_get_driver(device));

  if (udev_device_get_action(device))
    log_debug("action:    " << udev_device_get_action(device));

  //udev_device_get_sysattr_value(device, "busnum");
  //udev_device_get_sysattr_value(device, "devnum");

#if 0
  // FIXME: only works with newer versions of libudev
  {
    log_debug("list: ");
    struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }

  {
    log_debug("properties: ");
    struct udev_list_entry* it = udev_device_get_properties_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }

  {
    log_debug("devlist: ");
    struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
    while((it = udev_list_entry_get_next(it)) != 0)
    {
      log_debug("  "
                << udev_list_entry_get_name(it) << " = "
                << udev_list_entry_get_value(it)
        );
    }
  }
#endif

  log_debug("\\----------------------------------------------");
}
コード例 #9
0
static int unbind_device(char *busid)
{
	char bus_type[] = "usb";
	int rc, ret = -1;

	char unbind_attr_name[] = "unbind";
	char unbind_attr_path[SYSFS_PATH_MAX];
	char rebind_attr_name[] = "rebind";
	char rebind_attr_path[SYSFS_PATH_MAX];

	struct udev *udev;
	struct udev_device *dev;
	const char *driver;

	/* Create libudev context. */
	udev = udev_new();

	/* Check whether the device with this bus ID exists. */
	dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
	if (!dev) {
		err("device with the specified bus ID does not exist");
		goto err_close_udev;
	}

	/* Check whether the device is using usbip-host driver. */
	driver = udev_device_get_driver(dev);
	if (!driver || strcmp(driver, "usbip-host")) {
		err("device is not bound to usbip-host driver");
		goto err_close_udev;
	}

	/* Unbind device from driver. */
	snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
		 SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
		 USBIP_HOST_DRV_NAME, unbind_attr_name);

	rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
	if (rc < 0) {
		err("error unbinding device %s from driver", busid);
		goto err_close_udev;
	}

	/* Notify driver of unbind. */
	rc = modify_match_busid(busid, 0);
	if (rc < 0) {
		err("unable to unbind device on %s", busid);
		goto err_close_udev;
	}

	/* Trigger new probing. */
	snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
			SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
			USBIP_HOST_DRV_NAME, rebind_attr_name);

	rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
	if (rc < 0) {
		err("error rebinding");
		goto err_close_udev;
	}

	ret = 0;
	info("unbind device on busid %s: complete", busid);

err_close_udev:
	udev_device_unref(dev);
	udev_unref(udev);

	return ret;
}
コード例 #10
0
ファイル: libudev-fs.c プロジェクト: bjb/vdev
int main( int argc, char** argv ) {
   
   int rc = 0;
   char pathbuf[PATH_MAX+1];
   struct udev* udev_client = NULL;
   struct udev_monitor* monitor = NULL;
   int monitor_fd = 0;
   struct udev_device* dev = NULL;
   struct pollfd pfd[1];
   int num_events = INT_MAX;
   int num_forks = 0;
   
   // usage: $0 [num events to process [num times to fork]]
   if( argc > 1 ) {
      char* tmp = NULL;
      num_events = (int)strtol( argv[1], &tmp, 10 );
      if( tmp == argv[1] || *tmp != '\0' ) {
         fprintf(stderr, "Usage: %s [number of events to process [number of times to fork]]\n", argv[0] );
         exit(1);
      }
      
      if( argc > 2 ) {
         
         num_forks = (int)strtol( argv[2], &tmp, 10 );
         if( tmp == argv[2] || *tmp != '\0' ) {
            fprintf(stderr, "Usage: %s [number of events to process [number of times to fork]]\n", argv[0] );
            exit(1);
         }
      }
   }
   
   // make sure events dir exists 
   log_trace("events directory '%s'", UDEV_FS_EVENTS_DIR);
   
   rc = mkdir( UDEV_FS_EVENTS_DIR, 0700 );
   if( rc != 0 ) {
      
      rc = -errno;
      if( rc != -EEXIST ) {
         log_error("mkdir('%s') rc = %d", UDEV_FS_EVENTS_DIR, rc );
         exit(1);
      }
   }
   
   udev_monitor_fs_events_path( "", pathbuf, 0 );
   
   printf("Watching '%s'\n", pathbuf );
   
   udev_client = udev_new();
   if( udev_client == NULL ) {
      
      // OOM
      exit(2);
   }
   
   monitor = udev_monitor_new_from_netlink( udev_client, "udev" );
   if( monitor == NULL ) {
      
      // OOM or error
      udev_unref( udev_client );
      exit(2);
   }
   
   printf("Press Ctrl-C to quit\n");
   
   monitor_fd = udev_monitor_get_fd( monitor );
   if( monitor_fd < 0 ) {
      
      rc = -errno;
      log_error("udev_monitor_get_fd rc = %d\n", rc );
      exit(3);
   }
   
   pfd[0].fd = monitor_fd;
   pfd[0].events = POLLIN;
   
   while( num_events > 0 ) {
      
      // wait for the next device 
      rc = poll( pfd, 1, -1 );
      if( rc < 0 ) {
      
         log_error("poll(%d) rc = %d\n", monitor_fd, rc );
         break;
      }
      
      // get devices 
      while( num_events > 0 ) {
         
         dev = udev_monitor_receive_device( monitor );
         if( dev == NULL ) {
            break;
         }
         
         int pid = getpid();
         struct udev_list_entry *list_entry = NULL;
         
         printf("[%d] [%d] ACTION:     '%s'\n", pid, num_events, udev_device_get_action( dev ) );
         printf("[%d] [%d] SEQNUM:      %llu\n", pid, num_events, udev_device_get_seqnum( dev ) );
         printf("[%d] [%d] USEC:        %llu\n", pid, num_events, udev_device_get_usec_since_initialized( dev ) );
         printf("[%d] [%d] DEVNODE:    '%s'\n", pid, num_events, udev_device_get_devnode( dev ) );
         printf("[%d] [%d] DEVPATH:    '%s'\n", pid, num_events, udev_device_get_devpath( dev ) );
         printf("[%d] [%d] SYSNAME:    '%s'\n", pid, num_events, udev_device_get_sysname( dev ) );
         printf("[%d] [%d] SYSPATH:    '%s'\n", pid, num_events, udev_device_get_syspath( dev ) );
         printf("[%d] [%d] SUBSYSTEM:  '%s'\n", pid, num_events, udev_device_get_subsystem( dev ) );
         printf("[%d] [%d] DEVTYPE:    '%s'\n", pid, num_events, udev_device_get_devtype( dev ) );
         printf("[%d] [%d] SYSNUM:     '%s'\n", pid, num_events, udev_device_get_sysnum( dev ) );
         printf("[%d] [%d] DRIVER:     '%s'\n", pid, num_events, udev_device_get_driver( dev ) );
         printf("[%d] [%d] DEVNUM:      %d:%d\n", pid, num_events, major( udev_device_get_devnum( dev ) ), minor( udev_device_get_devnum( dev ) ) );
         printf("[%d] [%d] IFINDEX:    '%s'\n", pid, num_events, udev_device_get_property_value( dev, "IFINDEX" ) );
         printf("[%d] [%d] DEVMODE:    '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVMODE" ) );
         printf("[%d] [%d] DEVUID:     '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVUID" ) );
         printf("[%d] [%d] DEVGID:     '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVGID" ) );         
         
         list_entry = udev_device_get_devlinks_list_entry( dev );
         udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
          
            printf("[%d] [%d] devlink:    '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ) );
         }
         
         list_entry = udev_device_get_properties_list_entry( dev );
         udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
            
            printf("[%d] [%d] property:   '%s' = '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ), udev_list_entry_get_value( list_entry ) );
         }
         
         list_entry = udev_device_get_tags_list_entry( dev );
         udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
            
            printf("[%d] [%d] tag:        '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ) );
         }