tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definitions

⎇ f9e42c846b2260232ff3f9be13396d120f60f18b recipes/libudev-zero-scan-class.patch 96 lines · 5.1 KB History raw

🔊 audio FUNCIONANDO — el muro era libudev-zero, y ensancharlo de más rompía el vídeo 7f2fdd5a4 · sergio ·

1libudev-zero: enumerar devices de CLASE para una lista ACOTADA de subsistemas.
2
3EL HUECO, medido en las fuentes de los dos lados. `udev_enumerate_scan_devices` recorre
4**exclusivamente** `/sys/dev/block` y `/sys/dev/char` (udev_enumerate.c:281), o sea sólo devices que
5tienen `major:minor` y por tanto nodo en /dev. El udev real recorre `/sys/class` entero. La diferencia
6es invisible para casi todos los consumidores y letal para los que piden un device de CLASE.
7
8CÓMO SE DESTAPÓ: el audio. `spa/plugins/alsa/alsa-udev.c:178-183` de PipeWire pide el device **card**
9—`/sys/devices/.../sound/card0`—, que es de clase: sin major:minor, sin nodo. Con ALSA encendido en el
10kernel, `/dev/snd/controlC0` presente y `/sys/class/sound` listando `card0`, `wpctl status` daba
11`Devices:` vacío **porque card0 nunca entraba en la enumeración**. No era una propiedad que faltara:
12faltaba la mitad del espacio de búsqueda.
13
14⚠ POR QUÉ UNA LISTA Y NO `/sys/class` ENTERO — se probó global y ROMPIÓ EL VÍDEO
15La primera versión de este parche recorría todo `/sys/class`. El audio pasó a funcionar
16(`48. HDA Intel [alsa]`, sink y source reales en vez de `auto_null`) **y la pantalla se puso negra**:
17
18    libmutter-WARNING: Failed to use linear monitor configuration:
19                       No available CRTC for monitor 'RHT QEMU Monitor' not found
20    libmutter-WARNING: Page flip failed: drmModeAtomicCommit: Invalid argument   (en bucle)
21
22`/sys/class/drm` no contiene sólo las tarjetas: contiene los CONECTORES (`card0-Virtual-1`,
23`card1-eDP-1`…) y un fichero `version`, ninguno con nodo. Al aparecer en la enumeración, mutter los
24toma como candidatos y no encuentra CRTC. **El udev real también los enumera** — pero además les
25adjunta las propiedades por las que mutter los descarta, y ésas libudev-zero no las sintetiza (su
26tabla es fija y está orientada a input: `ID_INPUT*`, `EV`, `KEY`, `ABS`, `REL`).
27
28La lección, que vale para cualquier reimplementación parcial de una API: **ensanchar la enumeración
29expone los huecos de PROPIEDADES a más consumidores.** Los dos lados del contrato tienen que crecer
30juntos.
31
32Así que se agrega subsistema por subsistema, con un caso de uso medido detrás de cada uno. Hoy:
33`sound`. Agregar otro es una línea en `class_subsystems[]` **y una prueba de que el consumidor lo
34necesita y no se rompe**.
35
36POR QUÉ ESTO Y NO eudev, y acá el repo ya tenía la respuesta escrita: empaquetar eudev se probó en otro
37frente y **rompió el input** — su `libudev.so.1` pisa el de libudev-zero y, SIN udevd corriendo, eudev
38no expone `ID_INPUT`, así que libinput ignora TODOS los dispositivos EN SILENCIO (`udev_assign_seat`
39devuelve OK con 0 devices). Se resolvió restaurando libudev-zero, con verificación A/B en QEMU: eudev =
400 «New device», libudev-zero = 5. Ver [[mirada-usb-nvidia]]. eudev sin udevd es PEOR, y correr udevd
41contradice la arquitectura (arje-zero es PID1, sin udevd en el camino).
42
43⚠ COSTO: `yupana radio libudev-zero` = **51 artefactos sellados cayendo a deuda** en las cinco
44imágenes (9 en el cierre GNOME). Una variante NO era opción: dos `libudev.so.1` en el mismo rootfs es
45exactamente el choque del episodio de eudev.
46
47diff -Naur a/udev_enumerate.c b/udev_enumerate.c
48--- a/udev_enumerate.c
49+++ b/udev_enumerate.c
50@@ -276,6 +276,37 @@
51     return 1;
52 }
53 
54+/* Enumera devices de CLASE (los que no tienen major:minor y por tanto no aparecen bajo
55+ * /sys/dev/{block,char}) para una LISTA ACOTADA de subsistemas.
56+ *
57+ * Por que una lista y no /sys/class entero: se probo global y ROMPIO EL VIDEO. /sys/class/drm no
58+ * contiene solo las tarjetas: contiene los CONECTORES (card0-Virtual-1, card1-eDP-1...) y un fichero
59+ * `version`, ninguno con nodo. Al aparecer en la enumeracion, mutter los trata como candidatos y
60+ * termina en `No available CRTC for monitor` + `Page flip failed: drmModeAtomicCommit: Invalid
61+ * argument` en bucle: pantalla negra con el compositor vivo. El udev real tambien los enumera, pero
62+ * ademas les adjunta las propiedades por las que mutter los descarta, y esas propiedades libudev-zero
63+ * no las sintetiza. O sea: ensanchar la enumeracion expone los huecos de PROPIEDADES a mas
64+ * consumidores.
65+ *
66+ * Asi que se agrega subsistema por subsistema, con un caso de uso medido detras de cada uno:
67+ *   sound  -> PipeWire pide el device `card` de la tarjeta (alsa-udev.c:178-183), que no tiene nodo.
68+ *             Sin esto `wpctl status` da `Devices:` vacio con ALSA funcionando y /dev/snd poblado.
69+ */
70+static const char *const class_subsystems[] = { "sound", NULL };
71+
72+static int scan_class(struct udev_enumerate *udev_enumerate)
73+{
74+    char subsystem_path[PATH_MAX];
75+    int i;
76+
77+    for (i = 0; class_subsystems[i]; i++) {
78+        snprintf(subsystem_path, sizeof(subsystem_path), "/sys/class/%s", class_subsystems[i]);
79+        scan_devices(udev_enumerate, subsystem_path);
80+    }
81+
82+    return 1;
83+}
84+
85 int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
86 {
87     const char *path[] = { "/sys/dev/block", "/sys/dev/char", NULL };
88@@ -291,6 +322,8 @@
89         }
90     }
91 
92+    scan_class(udev_enumerate);
93+
94     return 0;
95 }
96