From 4564f76627f40d94ac35869fda25e25e6f246231 Mon Sep 17 00:00:00 2001 From: Sriman Achanta Date: Fri, 23 Jan 2026 11:59:47 -0500 Subject: [PATCH 1/5] Add wireless status fields and enum to card structure with proper cleanup --- spa/plugins/alsa/alsa-udev.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index 7d1ae9a3a..b05bd7d06 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -39,6 +39,14 @@ enum action { /* Used for unavailable devices in the card structure. */ #define ID_DEVICE_NOT_SUPPORTED 0 +#define MAX_PARENT_TRAVERSAL_DEPTH 5 + +enum wireless_status { + WIRELESS_STATUS_UNKNOWN = 0, + WIRELESS_STATUS_CONNECTED, + WIRELESS_STATUS_DISCONNECTED, +}; + /* This represents an ALSA card. * One card can have up to 1 PCM and 1 Compress-Offload device. */ struct card { @@ -48,6 +56,7 @@ struct card { unsigned int accessible:1; unsigned int ignored:1; unsigned int emitted:1; + unsigned int wireless_disconnected:1; /* Local SPA object IDs. (Global IDs are produced by PipeWire * out of this using its registry.) Compress-Offload or PCM @@ -59,6 +68,8 @@ struct card { * is used because 0 is a valid ALSA card number. */ uint32_t pcm_device_id; uint32_t compress_offload_device_id; + + char *wireless_status_path; }; static uint32_t calc_pcm_device_id(struct card *card) @@ -144,14 +155,19 @@ static struct card *find_card(struct impl *this, unsigned int card_nr) static void remove_card(struct impl *this, struct card *card) { udev_device_unref(card->udev_device); - *card = this->cards[--this->n_cards]; + free(card->wireless_status_path); + this->n_cards--; + if (card != &this->cards[this->n_cards]) + *card = this->cards[this->n_cards]; } static void clear_cards(struct impl *this) { unsigned int i; - for (i = 0; i < this->n_cards; i++) + for (i = 0; i < this->n_cards; i++) { udev_device_unref(this->cards[i].udev_device); + free(this->cards[i].wireless_status_path); + } this->n_cards = 0; } From 9bde703969c1533e9650de7541ea4af065531cb3 Mon Sep 17 00:00:00 2001 From: Sriman Achanta Date: Fri, 23 Jan 2026 12:02:17 -0500 Subject: [PATCH 2/5] Add wireless status detection and monitoring functions --- spa/plugins/alsa/alsa-udev.c | 179 +++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index b05bd7d06..c66e4e2c0 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -276,6 +276,168 @@ static void unescape(const char *src, char *dst) *d = 0; } +static enum wireless_status read_wireless_status(const char *sysfs_path) +{ + char buf[16]; + ssize_t sz; + int fd; + + fd = open(sysfs_path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return WIRELESS_STATUS_UNKNOWN; + + sz = read(fd, buf, sizeof(buf) - 1); + close(fd); + + if (sz <= 0) + return WIRELESS_STATUS_UNKNOWN; + + buf[sz] = '\0'; + if (buf[sz - 1] == '\n') + buf[sz - 1] = '\0'; + + if (spa_streq(buf, "connected")) + return WIRELESS_STATUS_CONNECTED; + if (spa_streq(buf, "disconnected")) + return WIRELESS_STATUS_DISCONNECTED; + + return WIRELESS_STATUS_UNKNOWN; +} + +static bool is_usb_interface_dir(const char *name) +{ + const char *colon = strchr(name, ':'); + if (!colon || !strchr(name, '-')) + return false; + + for (const char *p = colon + 1; *p; p++) + if (*p != '.' && !(*p >= '0' && *p <= '9')) + return false; + + return true; +} + +static char *check_wireless_status_at_path(struct impl *this, const char *path) +{ + char wireless_path[PATH_MAX]; + char *result; + int res; + + res = spa_scnprintf(wireless_path, sizeof(wireless_path), + "%s/wireless_status", path); + if (res < 0 || (size_t)res >= sizeof(wireless_path)) + return NULL; + + if (access(wireless_path, R_OK) < 0) + return NULL; + + result = strdup(wireless_path); + if (!result) + spa_log_error(this->log, "failed to allocate wireless_status path"); + return result; +} + +static char *search_siblings_for_wireless_status(struct impl *this, const char *parent_path) +{ + struct dirent *entry; + char *result = NULL; + int count = 0; + + spa_autoptr(DIR) parent_dir = opendir(parent_path); + if (!parent_dir) + return NULL; + + while ((entry = readdir(parent_dir)) != NULL) { + char sibling_path[PATH_MAX]; + char *path; + int res; + + if (entry->d_name[0] == '.') + continue; + + if (!is_usb_interface_dir(entry->d_name)) + continue; + + if (entry->d_type != DT_UNKNOWN && entry->d_type != DT_DIR) + continue; + + res = spa_scnprintf(sibling_path, sizeof(sibling_path), + "%s/%s", parent_path, entry->d_name); + if (res < 0 || (size_t)res >= sizeof(sibling_path)) + continue; + + path = check_wireless_status_at_path(this, sibling_path); + if (path) { + count++; + if (!result) + result = path; + else + free(path); + } + } + + if (count > 1) + spa_log_info(this->log, "found %d wireless_status files, using first one", count); + + return result; +} + +static char *find_wireless_status_path(struct impl *this, const char *card_syspath) +{ + char usb_device_path[PATH_MAX]; + char *last_slash, *result; + int i, res; + + res = spa_scnprintf(usb_device_path, sizeof(usb_device_path), "%s", card_syspath); + if (res < 0 || (size_t)res >= sizeof(usb_device_path)) + return NULL; + + result = check_wireless_status_at_path(this, usb_device_path); + if (result) + return result; + + for (i = 0; i < MAX_PARENT_TRAVERSAL_DEPTH; i++) { + last_slash = strrchr(usb_device_path, '/'); + if (!last_slash || last_slash == usb_device_path) + break; + + *last_slash = '\0'; + + result = search_siblings_for_wireless_status(this, usb_device_path); + if (result) + return result; + } + + return NULL; +} + +static void update_wireless_status(struct impl *this, struct card *card) +{ + enum wireless_status status; + bool disconnected; + + if (!card->wireless_status_path) + return; + + status = read_wireless_status(card->wireless_status_path); + + if (status == WIRELESS_STATUS_UNKNOWN) { + spa_log_info(this->log, "card %u wireless_status unreadable, removing monitor", + card->card_nr); + free(card->wireless_status_path); + card->wireless_status_path = NULL; + card->wireless_disconnected = false; + return; + } + + disconnected = (status == WIRELESS_STATUS_DISCONNECTED); + if (disconnected != card->wireless_disconnected) { + spa_log_info(this->log, "card %u wireless device %s", + card->card_nr, disconnected ? "disconnected" : "connected"); + card->wireless_disconnected = disconnected; + } +} + static int check_device_pcm_class(const char *devname) { char path[PATH_MAX]; @@ -906,6 +1068,23 @@ static int start_inotify(struct impl *this) return 0; } +static struct card *find_card_by_wireless_status_path(struct impl *this, const char *syspath) +{ + char wireless_path[PATH_MAX]; + int res; + + res = spa_scnprintf(wireless_path, sizeof(wireless_path), "%s/wireless_status", syspath); + if (res < 0 || (size_t)res >= sizeof(wireless_path)) + return NULL; + + for (unsigned int i = 0; i < this->n_cards; i++) { + if (this->cards[i].wireless_status_path && + spa_streq(this->cards[i].wireless_status_path, wireless_path)) + return &this->cards[i]; + } + return NULL; +} + static void impl_on_fd_events(struct spa_source *source) { struct impl *this = source->data; From aac3c14d4337e102238ad2c3484c18370269c60e Mon Sep 17 00:00:00 2001 From: Sriman Achanta Date: Fri, 23 Jan 2026 12:02:37 -0500 Subject: [PATCH 3/5] Use wireless status to block disconnected devices and monitor HID/USB changes --- spa/plugins/alsa/alsa-udev.c | 48 +++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index c66e4e2c0..2957f304d 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -663,6 +663,20 @@ static int emit_added_object_info(struct impl *this, struct card *card) snprintf(path, sizeof(path), "hw:%u", card->card_nr); + if (!card->wireless_status_path) { + const char *syspath = udev_device_get_syspath(udev_device); + if (syspath) + card->wireless_status_path = find_wireless_status_path(this, syspath); + } + + if (card->wireless_status_path) { + enum wireless_status status = read_wireless_status(card->wireless_status_path); + if (status == WIRELESS_STATUS_DISCONNECTED) { + card->wireless_disconnected = true; + return -ENODEV; + } + } + if ((res = check_pcm_device_availability(this, card, &num_pcm_devices)) < 0) return res; if ((res = check_compress_offload_device_availability(this, card, &num_compress_offload_devices)) < 0) @@ -908,8 +922,9 @@ static void process_card(struct impl *this, enum action action, struct card *car switch (action) { case ACTION_CHANGE: { + update_wireless_status(this, card); check_access(this, card); - if (card->accessible && !card->emitted) { + if (card->accessible && !card->wireless_disconnected && !card->emitted) { int res = emit_added_object_info(this, card); if (res < 0) { if (card->ignored) @@ -928,7 +943,7 @@ static void process_card(struct impl *this, enum action action, struct card *car card->card_nr); card->unavailable = false; } - } else if (!card->accessible && card->emitted) { + } else if ((!card->accessible || card->wireless_disconnected) && card->emitted) { card->emitted = false; if (card->pcm_device_id != ID_DEVICE_NOT_SUPPORTED) @@ -1089,24 +1104,35 @@ static void impl_on_fd_events(struct spa_source *source) { struct impl *this = source->data; struct udev_device *udev_device; - const char *action; + const char *action, *subsystem, *syspath; + struct card *card; udev_device = udev_monitor_receive_device(this->umonitor); if (udev_device == NULL) return; - if ((action = udev_device_get_action(udev_device)) == NULL) + action = udev_device_get_action(udev_device); + if (action == NULL) action = "change"; - spa_log_debug(this->log, "action %s", action); + subsystem = udev_device_get_subsystem(udev_device); start_inotify(this); - if (spa_streq(action, "add") || spa_streq(action, "change")) { - process_udev_device(this, ACTION_CHANGE, udev_device); - } else if (spa_streq(action, "remove")) { - process_udev_device(this, ACTION_REMOVE, udev_device); + if (spa_streq(subsystem, "sound")) { + if (spa_streq(action, "add") || spa_streq(action, "change")) + process_udev_device(this, ACTION_CHANGE, udev_device); + else if (spa_streq(action, "remove")) + process_udev_device(this, ACTION_REMOVE, udev_device); + } else if (spa_streq(subsystem, "hid") || spa_streq(subsystem, "usb")) { + if (spa_streq(action, "change")) { + syspath = udev_device_get_syspath(udev_device); + card = find_card_by_wireless_status_path(this, syspath); + if (card) + process_card(this, ACTION_CHANGE, card); + } } + udev_device_unref(udev_device); } @@ -1123,6 +1149,10 @@ static int start_monitor(struct impl *this) udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, "sound", NULL); + udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, + "hid", NULL); + udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, + "usb", NULL); udev_monitor_enable_receiving(this->umonitor); this->source.func = impl_on_fd_events; From 8361526317382b8064dc427df8099bc87bf0e37e Mon Sep 17 00:00:00 2001 From: Sriman Achanta Date: Fri, 23 Jan 2026 18:14:31 +0000 Subject: [PATCH 4/5] Apply 3 suggestion(s) to 1 file(s) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Barnabás Pőcze --- spa/plugins/alsa/alsa-udev.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index 2957f304d..e06801c87 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -320,7 +320,6 @@ static bool is_usb_interface_dir(const char *name) static char *check_wireless_status_at_path(struct impl *this, const char *path) { char wireless_path[PATH_MAX]; - char *result; int res; res = spa_scnprintf(wireless_path, sizeof(wireless_path), @@ -331,10 +330,7 @@ static char *check_wireless_status_at_path(struct impl *this, const char *path) if (access(wireless_path, R_OK) < 0) return NULL; - result = strdup(wireless_path); - if (!result) - spa_log_error(this->log, "failed to allocate wireless_status path"); - return result; + return strdup(wireless_path); } static char *search_siblings_for_wireless_status(struct impl *this, const char *parent_path) @@ -424,8 +420,7 @@ static void update_wireless_status(struct impl *this, struct card *card) if (status == WIRELESS_STATUS_UNKNOWN) { spa_log_info(this->log, "card %u wireless_status unreadable, removing monitor", card->card_nr); - free(card->wireless_status_path); - card->wireless_status_path = NULL; + spa_clear_ptr(card->wireless_status_path, free); card->wireless_disconnected = false; return; } @@ -1093,8 +1088,7 @@ static struct card *find_card_by_wireless_status_path(struct impl *this, const c return NULL; for (unsigned int i = 0; i < this->n_cards; i++) { - if (this->cards[i].wireless_status_path && - spa_streq(this->cards[i].wireless_status_path, wireless_path)) + if (spa_streq(this->cards[i].wireless_status_path, wireless_path)) return &this->cards[i]; } return NULL; From e4ab89ecadb5d11eaaced6911470626d4c0f8a01 Mon Sep 17 00:00:00 2001 From: Sriman Achanta Date: Fri, 23 Jan 2026 16:12:25 -0500 Subject: [PATCH 5/5] Refactor wireless status monitoring to use direct sysfs file descriptor polling instead of udev hid/usb subsystem events --- spa/plugins/alsa/alsa-udev.c | 193 +++++++++++++++++++++++------------ 1 file changed, 130 insertions(+), 63 deletions(-) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index e06801c87..348935632 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -47,9 +47,13 @@ enum wireless_status { WIRELESS_STATUS_DISCONNECTED, }; +/* Forward declaration for struct impl */ +struct impl; + /* This represents an ALSA card. * One card can have up to 1 PCM and 1 Compress-Offload device. */ struct card { + struct impl *impl; unsigned int card_nr; struct udev_device *udev_device; unsigned int unavailable:1; @@ -70,6 +74,8 @@ struct card { uint32_t compress_offload_device_id; char *wireless_status_path; + int wireless_status_fd; + struct spa_source wireless_status_source; }; static uint32_t calc_pcm_device_id(struct card *card) @@ -108,6 +114,11 @@ struct impl { int use_ucm; }; +/* Forward declarations */ +static void process_card(struct impl *this, enum action action, struct card *card); +static void stop_wireless_status_monitor(struct impl *this, struct card *card); +static void on_wireless_status_change(struct spa_source *source); + static int impl_udev_open(struct impl *this) { if (this->udev == NULL) { @@ -135,7 +146,9 @@ static struct card *add_card(struct impl *this, unsigned int card_nr, struct ude card = &this->cards[this->n_cards++]; spa_zero(*card); + card->impl = this; card->card_nr = card_nr; + card->wireless_status_fd = -1; udev_device_ref(udev_device); card->udev_device = udev_device; @@ -154,8 +167,8 @@ static struct card *find_card(struct impl *this, unsigned int card_nr) static void remove_card(struct impl *this, struct card *card) { + stop_wireless_status_monitor(this, card); udev_device_unref(card->udev_device); - free(card->wireless_status_path); this->n_cards--; if (card != &this->cards[this->n_cards]) *card = this->cards[this->n_cards]; @@ -165,8 +178,8 @@ static void clear_cards(struct impl *this) { unsigned int i; for (i = 0; i < this->n_cards; i++) { + stop_wireless_status_monitor(this, &this->cards[i]); udev_device_unref(this->cards[i].udev_device); - free(this->cards[i].wireless_status_path); } this->n_cards = 0; } @@ -276,6 +289,15 @@ static void unescape(const char *src, char *dst) *d = 0; } +static enum wireless_status parse_wireless_status(const char *buf) +{ + if (spa_streq(buf, "connected")) + return WIRELESS_STATUS_CONNECTED; + if (spa_streq(buf, "disconnected")) + return WIRELESS_STATUS_DISCONNECTED; + return WIRELESS_STATUS_UNKNOWN; +} + static enum wireless_status read_wireless_status(const char *sysfs_path) { char buf[16]; @@ -296,12 +318,7 @@ static enum wireless_status read_wireless_status(const char *sysfs_path) if (buf[sz - 1] == '\n') buf[sz - 1] = '\0'; - if (spa_streq(buf, "connected")) - return WIRELESS_STATUS_CONNECTED; - if (spa_streq(buf, "disconnected")) - return WIRELESS_STATUS_DISCONNECTED; - - return WIRELESS_STATUS_UNKNOWN; + return parse_wireless_status(buf); } static bool is_usb_interface_dir(const char *name) @@ -407,21 +424,93 @@ static char *find_wireless_status_path(struct impl *this, const char *card_syspa return NULL; } -static void update_wireless_status(struct impl *this, struct card *card) +static void stop_wireless_status_monitor(struct impl *this, struct card *card) { + if (card->wireless_status_fd >= 0) { + spa_loop_remove_source(this->main_loop, &card->wireless_status_source); + close(card->wireless_status_fd); + card->wireless_status_fd = -1; + } + if (card->wireless_status_path) { + free(card->wireless_status_path); + card->wireless_status_path = NULL; + } +} + +static int start_wireless_status_monitor(struct impl *this, struct card *card, const char *path) +{ + char buf[16]; + ssize_t sz; + int fd; + + fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + spa_log_debug(this->log, "card %u: failed to open wireless_status: %s", + card->card_nr, spa_strerror(-errno)); + return -errno; + } + + sz = read(fd, buf, sizeof(buf) - 1); + if (sz <= 0) { + spa_log_debug(this->log, "card %u: failed to read wireless_status: %s", + card->card_nr, spa_strerror(sz < 0 ? -errno : -EIO)); + close(fd); + return sz < 0 ? -errno : -EIO; + } + + lseek(fd, 0, SEEK_SET); + + card->wireless_status_path = strdup(path); + if (!card->wireless_status_path) { + close(fd); + return -ENOMEM; + } + + card->wireless_status_fd = fd; + card->wireless_status_source.func = on_wireless_status_change; + card->wireless_status_source.data = card; + card->wireless_status_source.fd = fd; + card->wireless_status_source.mask = SPA_IO_ERR; + + spa_loop_add_source(this->main_loop, &card->wireless_status_source); + + spa_log_info(this->log, "card %u: monitoring wireless_status at %s", + card->card_nr, path); + + return 0; +} + +static void on_wireless_status_change(struct spa_source *source) +{ + struct card *card = source->data; + struct impl *this = card->impl; enum wireless_status status; bool disconnected; + char buf[16]; + ssize_t sz; - if (!card->wireless_status_path) - return; - - status = read_wireless_status(card->wireless_status_path); - - if (status == WIRELESS_STATUS_UNKNOWN) { + lseek(card->wireless_status_fd, 0, SEEK_SET); + sz = read(card->wireless_status_fd, buf, sizeof(buf) - 1); + if (sz <= 0) { spa_log_info(this->log, "card %u wireless_status unreadable, removing monitor", card->card_nr); - spa_clear_ptr(card->wireless_status_path, free); + stop_wireless_status_monitor(this, card); card->wireless_disconnected = false; + process_card(this, ACTION_CHANGE, card); + return; + } + + buf[sz] = '\0'; + if (buf[sz - 1] == '\n') + buf[sz - 1] = '\0'; + + status = parse_wireless_status(buf); + if (status == WIRELESS_STATUS_UNKNOWN) { + spa_log_info(this->log, "card %u wireless_status unknown, removing monitor", + card->card_nr); + stop_wireless_status_monitor(this, card); + card->wireless_disconnected = false; + process_card(this, ACTION_CHANGE, card); return; } @@ -430,6 +519,7 @@ static void update_wireless_status(struct impl *this, struct card *card) spa_log_info(this->log, "card %u wireless device %s", card->card_nr, disconnected ? "disconnected" : "connected"); card->wireless_disconnected = disconnected; + process_card(this, ACTION_CHANGE, card); } } @@ -658,17 +748,27 @@ static int emit_added_object_info(struct impl *this, struct card *card) snprintf(path, sizeof(path), "hw:%u", card->card_nr); - if (!card->wireless_status_path) { + if (card->wireless_status_fd < 0) { const char *syspath = udev_device_get_syspath(udev_device); - if (syspath) - card->wireless_status_path = find_wireless_status_path(this, syspath); - } + char *wireless_path; - if (card->wireless_status_path) { - enum wireless_status status = read_wireless_status(card->wireless_status_path); - if (status == WIRELESS_STATUS_DISCONNECTED) { - card->wireless_disconnected = true; - return -ENODEV; + if (syspath && (wireless_path = find_wireless_status_path(this, syspath))) { + enum wireless_status status = read_wireless_status(wireless_path); + + if (status == WIRELESS_STATUS_DISCONNECTED) { + spa_log_info(this->log, "card %u: wireless device disconnected, not emitting", + card->card_nr); + free(wireless_path); + card->wireless_disconnected = true; + return -ENODEV; + } + + if (status == WIRELESS_STATUS_CONNECTED) { + if (start_wireless_status_monitor(this, card, wireless_path) < 0) + free(wireless_path); + } else { + free(wireless_path); + } } } @@ -917,7 +1017,6 @@ static void process_card(struct impl *this, enum action action, struct card *car switch (action) { case ACTION_CHANGE: { - update_wireless_status(this, card); check_access(this, card); if (card->accessible && !card->wireless_disconnected && !card->emitted) { int res = emit_added_object_info(this, card); @@ -1078,28 +1177,11 @@ static int start_inotify(struct impl *this) return 0; } -static struct card *find_card_by_wireless_status_path(struct impl *this, const char *syspath) -{ - char wireless_path[PATH_MAX]; - int res; - - res = spa_scnprintf(wireless_path, sizeof(wireless_path), "%s/wireless_status", syspath); - if (res < 0 || (size_t)res >= sizeof(wireless_path)) - return NULL; - - for (unsigned int i = 0; i < this->n_cards; i++) { - if (spa_streq(this->cards[i].wireless_status_path, wireless_path)) - return &this->cards[i]; - } - return NULL; -} - static void impl_on_fd_events(struct spa_source *source) { struct impl *this = source->data; struct udev_device *udev_device; - const char *action, *subsystem, *syspath; - struct card *card; + const char *action; udev_device = udev_monitor_receive_device(this->umonitor); if (udev_device == NULL) @@ -1109,23 +1191,12 @@ static void impl_on_fd_events(struct spa_source *source) if (action == NULL) action = "change"; - subsystem = udev_device_get_subsystem(udev_device); - start_inotify(this); - if (spa_streq(subsystem, "sound")) { - if (spa_streq(action, "add") || spa_streq(action, "change")) - process_udev_device(this, ACTION_CHANGE, udev_device); - else if (spa_streq(action, "remove")) - process_udev_device(this, ACTION_REMOVE, udev_device); - } else if (spa_streq(subsystem, "hid") || spa_streq(subsystem, "usb")) { - if (spa_streq(action, "change")) { - syspath = udev_device_get_syspath(udev_device); - card = find_card_by_wireless_status_path(this, syspath); - if (card) - process_card(this, ACTION_CHANGE, card); - } - } + if (spa_streq(action, "add") || spa_streq(action, "change")) + process_udev_device(this, ACTION_CHANGE, udev_device); + else if (spa_streq(action, "remove")) + process_udev_device(this, ACTION_REMOVE, udev_device); udev_device_unref(udev_device); } @@ -1143,10 +1214,6 @@ static int start_monitor(struct impl *this) udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, "sound", NULL); - udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, - "hid", NULL); - udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, - "usb", NULL); udev_monitor_enable_receiving(this->umonitor); this->source.func = impl_on_fd_events;