int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_device **ret) { _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; struct DeviceMonitorData data = {}; int r; assert(device); assert(subsystem); if (sd_device_get_is_initialized(device) > 0) { if (ret) *ret = sd_device_ref(device); return 0; } assert_se(sd_device_get_sysname(device, &data.sysname) >= 0); /* Wait until the device is initialized, so that we can get access to the ID_PATH property */ r = sd_event_new(&event); if (r < 0) return log_error_errno(r, "Failed to get default event: %m"); r = sd_device_monitor_new(&monitor); if (r < 0) return log_error_errno(r, "Failed to acquire monitor: %m"); r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, NULL); if (r < 0) return log_error_errno(r, "Failed to add %s subsystem match to monitor: %m", subsystem); r = sd_device_monitor_attach_event(monitor, event); if (r < 0) return log_error_errno(r, "Failed to attach event to device monitor: %m"); r = sd_device_monitor_start(monitor, device_monitor_handler, &data); if (r < 0) return log_error_errno(r, "Failed to start device monitor: %m"); /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized * yet. */ if (sd_device_get_is_initialized(device) > 0) { if (ret) *ret = sd_device_ref(device); return 0; } r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Event loop failed: %m"); if (ret) *ret = TAKE_PTR(data.device); return 0; }
return log_error_errno(r, "Failed to attach event: %m"); HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter, i) { r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, devtype); if (r < 0) return log_error_errno(r, "Failed to apply subsystem filter '%s%s%s': %m", subsystem, devtype ? "/" : "", strempty(devtype)); } SET_FOREACH(tag, arg_tag_filter, i) { r = sd_device_monitor_filter_add_match_tag(monitor, tag); if (r < 0) return log_error_errno(r, "Failed to apply tag filter '%s': %m", tag); } r = sd_device_monitor_start(monitor, device_monitor_handler, INT_TO_PTR(sender)); if (r < 0) return log_error_errno(r, "Failed to start device monitor: %m"); (void) sd_event_source_set_description(sd_device_monitor_get_event_source(monitor), sender == MONITOR_GROUP_UDEV ? "device-monitor-udev" : "device-monitor-kernel"); *ret = TAKE_PTR(monitor); return 0; } static int help(void) { printf("%s monitor [OPTIONS]\n\n" "Listen to kernel and udev events.\n\n" " -h --help Show this help\n" " -V --version Show package version\n"