smithay_drm_extras/drm_scanner/
connector_scanner.rs1use std::{
2 collections::HashMap,
3 iter::{Chain, Map},
4};
5
6use drm::control::{connector, Device as ControlDevice};
7
8#[derive(Debug, Default)]
25pub struct ConnectorScanner {
26 connectors: HashMap<connector::Handle, connector::Info>,
27}
28
29impl ConnectorScanner {
30 pub fn new() -> Self {
32 Default::default()
33 }
34
35 pub fn scan(&mut self, drm: &impl ControlDevice) -> std::io::Result<ConnectorScanResult> {
37 let res_handles = drm.resource_handles()?;
38 let connector_handles = res_handles.connectors();
39
40 let mut added = Vec::new();
41 let mut removed = Vec::new();
42
43 for conn in connector_handles
44 .iter()
45 .filter_map(|conn| drm.get_connector(*conn, true).ok())
46 {
47 let curr_state = conn.state();
48
49 use connector::State;
50 if let Some(old) = self.connectors.insert(conn.handle(), conn.clone()) {
51 match (old.state(), curr_state) {
52 (State::Connected, State::Disconnected) => removed.push(conn),
53 (State::Disconnected | State::Unknown, State::Connected) => added.push(conn),
54 (State::Connected, State::Connected) => {}
56 (State::Disconnected, State::Disconnected) => {}
57 (State::Unknown, _) => {}
59 (_, State::Unknown) => {}
60 }
61 } else if curr_state == State::Connected {
62 added.push(conn)
63 }
64 }
65
66 Ok(ConnectorScanResult {
67 connected: added,
68 disconnected: removed,
69 })
70 }
71
72 pub fn connectors(&self) -> &HashMap<connector::Handle, connector::Info> {
74 &self.connectors
75 }
76}
77
78#[derive(Debug, Default, Clone)]
84pub struct ConnectorScanResult {
85 pub connected: Vec<connector::Info>,
87 pub disconnected: Vec<connector::Info>,
89}
90
91#[derive(Debug, Clone)]
93pub enum ConnectorScanEvent {
94 Connected(connector::Info),
96 Disconnected(connector::Info),
98}
99
100impl ConnectorScanResult {
101 pub fn iter(&self) -> impl Iterator<Item = ConnectorScanEvent> {
105 self.clone().into_iter()
106 }
107}
108
109type ConnectorScanItemToEvent = fn(connector::Info) -> ConnectorScanEvent;
110
111impl IntoIterator for ConnectorScanResult {
112 type Item = ConnectorScanEvent;
113 type IntoIter = Chain<
114 Map<std::vec::IntoIter<connector::Info>, ConnectorScanItemToEvent>,
115 Map<std::vec::IntoIter<connector::Info>, ConnectorScanItemToEvent>,
116 >;
117
118 fn into_iter(self) -> Self::IntoIter {
119 self.disconnected
120 .into_iter()
121 .map(ConnectorScanEvent::Disconnected as ConnectorScanItemToEvent)
122 .chain(
123 self.connected
124 .into_iter()
125 .map(ConnectorScanEvent::Connected as ConnectorScanItemToEvent),
126 )
127 }
128}