gioser
⎇ d6b8f18b43c9bd9bf7268e48b61392a2d62bb229 crates/ente-zero/src/graph/devices.rs Rust · 60 líneas · 2.5 KB Historia Quién tocó qué crudo

Pausa: 11 crates del fractal Ente #0 con cerebro completo d6b8f18b4 · Sergio ·

1//! Device registry: mantiene el índice de dispositivos del kernel presentes,
2//! traduce uevents en cambios de `Capability::Device { class }`.
3
4use super::EnteGraph;
5use crate::events::GraphEvent;
6use ente_card::{Capability, DeviceClass};
7use ente_kernel::{UAction, UEvent};
8use tokio::sync::mpsc;
9use tracing::{debug, info, warn};
10
11impl EnteGraph {
12    pub async fn on_uevent(&mut self, evt: UEvent, _tx: &mpsc::Sender<GraphEvent>) {
13        let class = match &evt.device_class {
14            Some(c) => c.clone(),
15            None => return, // subsystems sin DeviceClass mapeada — ignoramos.
16        };
17        match evt.action {
18            UAction::Add | UAction::Bind | UAction::Online => {
19                let was_first = self.devices_of_class(&class) == 0;
20                self.devices.insert(evt.devpath.clone(), evt.clone());
21                if was_first {
22                    // Primera instancia de la clase → la registramos como
23                    // capacidad disponible. El "proveedor" virtual es el
24                    // Ente #0 (kernel surface).
25                    let cap = Capability::Device { class: class.clone() };
26                    self.providers.entry(cap).or_default().insert(self.seed.id);
27                    info!(?class, devpath = %evt.devpath, "device capability disponible");
28                }
29            }
30            UAction::Remove | UAction::Unbind | UAction::Offline => {
31                self.devices.remove(&evt.devpath);
32                if self.devices_of_class(&class) == 0 {
33                    let cap = Capability::Device { class: class.clone() };
34                    if let Some(set) = self.providers.get_mut(&cap) {
35                        set.remove(&self.seed.id);
36                    }
37                    let revoked: Vec<u64> = self.grants.iter()
38                        .filter(|(_, g)| g.cap == cap)
39                        .map(|(t, _)| *t)
40                        .collect();
41                    for t in revoked {
42                        self.grants.remove(&t);
43                    }
44                    warn!(?class, "última instancia removida — capacidad revocada");
45                }
46            }
47            UAction::Change | UAction::Move => {
48                self.devices.insert(evt.devpath.clone(), evt);
49                debug!(?class, "device modified");
50            }
51            UAction::Unknown => {}
52        }
53    }
54
55    fn devices_of_class(&self, class: &DeviceClass) -> usize {
56        self.devices.values()
57            .filter(|e| e.device_class.as_ref() == Some(class))
58            .count()
59    }
60}