swm_version: 1 base: distro_version: dev pins: {} mutations: - type: source_patch tarball: https://github.com/illiliti/libudev-zero/archive/refs/tags/1.0.4.tar.gz sha256: 10148cfd6047d387bf71eca72cd19c177084224d96434a118d8def6e0a3d6316 patches: - "libudev-zero: enumerar devices de CLASE para una lista ACOTADA de subsistemas.\n\nEL HUECO, medido en las fuentes de los dos lados. `udev_enumerate_scan_devices` recorre\n**exclusivamente** `/sys/dev/block` y `/sys/dev/char` (udev_enumerate.c:281), o sea sólo devices que\ntienen `major:minor` y por tanto nodo en /dev. El udev real recorre `/sys/class` entero. La diferencia\nes invisible para casi todos los consumidores y letal para los que piden un device de CLASE.\n\nCÓMO SE DESTAPÓ: el audio. `spa/plugins/alsa/alsa-udev.c:178-183` de PipeWire pide el device **card**\n—`/sys/devices/.../sound/card0`—, que es de clase: sin major:minor, sin nodo. Con ALSA encendido en el\nkernel, `/dev/snd/controlC0` presente y `/sys/class/sound` listando `card0`, `wpctl status` daba\n`Devices:` vacío **porque card0 nunca entraba en la enumeración**. No era una propiedad que faltara:\nfaltaba la mitad del espacio de búsqueda.\n\n⚠ POR QUÉ UNA LISTA Y NO `/sys/class` ENTERO — se probó global y ROMPIÓ EL VÍDEO\nLa primera versión de este parche recorría todo `/sys/class`. El audio pasó a funcionar\n(`48. HDA Intel [alsa]`, sink y source reales en vez de `auto_null`) **y la pantalla se puso negra**:\n\n libmutter-WARNING: Failed to use linear monitor configuration:\n No available CRTC for monitor 'RHT QEMU Monitor' not found\n libmutter-WARNING: Page flip failed: drmModeAtomicCommit: Invalid argument (en bucle)\n\n`/sys/class/drm` no contiene sólo las tarjetas: contiene los CONECTORES (`card0-Virtual-1`,\n`card1-eDP-1`…) y un fichero `version`, ninguno con nodo. Al aparecer en la enumeración, mutter los\ntoma como candidatos y no encuentra CRTC. **El udev real también los enumera** — pero además les\nadjunta las propiedades por las que mutter los descarta, y ésas libudev-zero no las sintetiza (su\ntabla es fija y está orientada a input: `ID_INPUT*`, `EV`, `KEY`, `ABS`, `REL`).\n\nLa lección, que vale para cualquier reimplementación parcial de una API: **ensanchar la enumeración\nexpone los huecos de PROPIEDADES a más consumidores.** Los dos lados del contrato tienen que crecer\njuntos.\n\nAsí que se agrega subsistema por subsistema, con un caso de uso medido detrás de cada uno. Hoy:\n`sound`. Agregar otro es una línea en `class_subsystems[]` **y una prueba de que el consumidor lo\nnecesita y no se rompe**.\n\nPOR QUÉ ESTO Y NO eudev, y acá el repo ya tenía la respuesta escrita: empaquetar eudev se probó en otro\nfrente y **rompió el input** — su `libudev.so.1` pisa el de libudev-zero y, SIN udevd corriendo, eudev\nno expone `ID_INPUT`, así que libinput ignora TODOS los dispositivos EN SILENCIO (`udev_assign_seat`\ndevuelve OK con 0 devices). Se resolvió restaurando libudev-zero, con verificación A/B en QEMU: eudev =\n0 «New device», libudev-zero = 5. Ver [[mirada-usb-nvidia]]. eudev sin udevd es PEOR, y correr udevd\ncontradice la arquitectura (arje-zero es PID1, sin udevd en el camino).\n\n⚠ COSTO: `yupana radio libudev-zero` = **51 artefactos sellados cayendo a deuda** en las cinco\nimágenes (9 en el cierre GNOME). Una variante NO era opción: dos `libudev.so.1` en el mismo rootfs es\nexactamente el choque del episodio de eudev.\n\ndiff -Naur a/udev_enumerate.c b/udev_enumerate.c\n--- a/udev_enumerate.c\n+++ b/udev_enumerate.c\n@@ -276,6 +276,37 @@\n return 1;\n }\n \n+/* Enumera devices de CLASE (los que no tienen major:minor y por tanto no aparecen bajo\n+ * /sys/dev/{block,char}) para una LISTA ACOTADA de subsistemas.\n+ *\n+ * Por que una lista y no /sys/class entero: se probo global y ROMPIO EL VIDEO. /sys/class/drm no\n+ * contiene solo las tarjetas: contiene los CONECTORES (card0-Virtual-1, card1-eDP-1...) y un fichero\n+ * `version`, ninguno con nodo. Al aparecer en la enumeracion, mutter los trata como candidatos y\n+ * termina en `No available CRTC for monitor` + `Page flip failed: drmModeAtomicCommit: Invalid\n+ * argument` en bucle: pantalla negra con el compositor vivo. El udev real tambien los enumera, pero\n+ * ademas les adjunta las propiedades por las que mutter los descarta, y esas propiedades libudev-zero\n+ * no las sintetiza. O sea: ensanchar la enumeracion expone los huecos de PROPIEDADES a mas\n+ * consumidores.\n+ *\n+ * Asi que se agrega subsistema por subsistema, con un caso de uso medido detras de cada uno:\n+ * sound -> PipeWire pide el device `card` de la tarjeta (alsa-udev.c:178-183), que no tiene nodo.\n+ * Sin esto `wpctl status` da `Devices:` vacio con ALSA funcionando y /dev/snd poblado.\n+ */\n+static const char *const class_subsystems[] = { \"sound\", NULL };\n+\n+static int scan_class(struct udev_enumerate *udev_enumerate)\n+{\n+ char subsystem_path[PATH_MAX];\n+ int i;\n+\n+ for (i = 0; class_subsystems[i]; i++) {\n+ snprintf(subsystem_path, sizeof(subsystem_path), \"/sys/class/%s\", class_subsystems[i]);\n+ scan_devices(udev_enumerate, subsystem_path);\n+ }\n+\n+ return 1;\n+}\n+\n int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)\n {\n const char *path[] = { \"/sys/dev/block\", \"/sys/dev/char\", NULL };\n@@ -291,6 +322,8 @@\n }\n }\n \n+ scan_class(udev_enumerate);\n+\n return 0;\n }\n \n" build: compiler: zig-cc target: x86_64-linux-musl link: dynamic flags: [] phases: compile: make PREFIX=/usr install: make PREFIX=/usr DESTDIR=/out install install-pkgconfig target_bin: /usr/bin/libudev-zero expected_hash: b3:eb42376d716ede0b72381c96158121cf45dd8d5dfeef7dd717970f5ecaf7a39b deps: build: - pkgconf - make runtime: []