⎇ d6b8f18b43c9bd9bf7268e48b61392a2d62bb229
crates/ente-zero/src/graph/devices.rs
Historia
Quién tocó qué
crudo
Pausa: 11 crates del fractal Ente #0 con cerebro completo
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}