fuchsia_driver_dev/
lib.rs1use anyhow::{Context, Result, anyhow, format_err};
6use {fidl_fuchsia_driver_development as fdd, fidl_fuchsia_driver_framework as fdf};
7
8#[derive(Debug)]
9pub struct Device(pub fdd::NodeInfo);
10
11impl Device {
12 pub fn get_moniker(&self) -> Result<&str> {
14 let moniker = self.0.moniker.as_ref();
15 Ok(moniker.ok_or_else(|| format_err!("Missing moniker"))?)
16 }
17
18 pub fn get_full_name(&self) -> Result<&str> {
20 self.get_moniker()
21 }
22
23 pub fn extract_name(&self) -> Result<&str> {
27 let moniker = self.get_moniker()?;
28 let (_, name) = moniker.rsplit_once('.').unwrap_or(("", &moniker));
29 Ok(name)
30 }
31}
32
33impl std::convert::From<fdd::NodeInfo> for Device {
34 fn from(device_info: fdd::NodeInfo) -> Device {
35 Device(device_info)
36 }
37}
38
39pub async fn get_device_info(
41 service: &fdd::ManagerProxy,
42 device_filter: &[String],
43 exact_match: bool,
44) -> Result<Vec<fdd::NodeInfo>> {
45 let (iterator, iterator_server) =
46 fidl::endpoints::create_proxy::<fdd::NodeInfoIteratorMarker>();
47
48 service
49 .get_node_info(device_filter, iterator_server, exact_match)
50 .context("FIDL call to get device info failed")?;
51
52 let mut info_result = Vec::new();
53
54 'outer: loop {
55 let device_info_futures = vec![
57 iterator.get_next(),
58 iterator.get_next(),
59 iterator.get_next(),
60 iterator.get_next(),
61 iterator.get_next(),
62 iterator.get_next(),
63 iterator.get_next(),
64 iterator.get_next(),
65 iterator.get_next(),
66 iterator.get_next(),
67 iterator.get_next(),
68 iterator.get_next(),
69 ];
70 let device_info_result = futures::future::join_all(device_info_futures).await;
71 for result in device_info_result {
72 let mut device_info = result.context("FIDL call to get device info failed")?;
73 if device_info.len() == 0 {
74 break 'outer;
75 }
76 info_result.append(&mut device_info)
77 }
78 }
79 Ok(info_result)
80}
81
82pub async fn get_driver_info(
84 service: &fdd::ManagerProxy,
85 driver_filter: &[String],
86) -> Result<Vec<fdf::DriverInfo>> {
87 let (iterator, iterator_server) =
88 fidl::endpoints::create_proxy::<fdd::DriverInfoIteratorMarker>();
89
90 service
91 .get_driver_info(driver_filter, iterator_server)
92 .context("FIDL call to get driver info failed")?;
93
94 let mut info_result = Vec::new();
95 'outer: loop {
96 let driver_info_futures = vec![
98 iterator.get_next(),
99 iterator.get_next(),
100 iterator.get_next(),
101 iterator.get_next(),
102 iterator.get_next(),
103 iterator.get_next(),
104 iterator.get_next(),
105 iterator.get_next(),
106 ];
107 let driver_info_result = futures::future::join_all(driver_info_futures).await;
108 for result in driver_info_result {
109 let mut driver_info = result.context("FIDL call to get driver info failed")?;
110 if driver_info.len() == 0 {
111 break 'outer;
112 }
113 info_result.append(&mut driver_info)
114 }
115 }
116 Ok(info_result)
117}
118
119pub async fn get_composite_node_specs(
121 service: &fdd::ManagerProxy,
122 name_filter: Option<String>,
123) -> Result<Vec<fdf::CompositeInfo>> {
124 let (iterator, iterator_server) =
125 fidl::endpoints::create_proxy::<fdd::CompositeNodeSpecIteratorMarker>();
126
127 service
128 .get_composite_node_specs(name_filter.as_deref(), iterator_server)
129 .context("FIDL call to get node groups failed")?;
130
131 let mut info_result = Vec::new();
132 loop {
133 let mut node_groups =
134 iterator.get_next().await.context("FIDL call to get node groups failed")?;
135 if node_groups.is_empty() {
136 break;
137 }
138 info_result.append(&mut node_groups)
139 }
140 Ok(info_result)
141}
142
143pub async fn get_driver_by_filter(
151 driver_filter: &String,
152 driver_development_proxy: &fdd::ManagerProxy,
153) -> Result<fdf::DriverInfo> {
154 let filter_list: [String; 1] = [driver_filter.to_string()];
155 let driver_list = get_driver_info(&driver_development_proxy, &filter_list).await?;
156 if driver_list.len() != 1 {
157 return Err(anyhow!(
158 "There should be exactly one match for '{}'. Found {}.",
159 driver_filter,
160 driver_list.len()
161 ));
162 }
163 let mut driver_info: Option<fdf::DriverInfo> = None;
164
165 let driver = &driver_list[0];
167 if let Some(ref url) = driver.url {
168 if url == driver_filter {
169 driver_info = Some(driver.clone());
170 }
171 }
172 match driver_info {
173 Some(driver) => Ok(driver),
174 _ => Err(anyhow!("Did not find matching driver for: {}", driver_filter)),
175 }
176}
177
178pub async fn get_driver_by_device(
186 device_topo_path: &String,
187 driver_development_proxy: &fdd::ManagerProxy,
188) -> Result<fdf::DriverInfo> {
189 let device_filter: [String; 1] = [device_topo_path.to_string()];
190 let mut device_list =
191 get_device_info(&driver_development_proxy, &device_filter, true).await?;
192 if device_list.len() != 1 {
193 let fuzzy_device_list = get_device_info(
194 &driver_development_proxy,
195 &device_filter,
196 false,
197 )
198 .await?;
199 if fuzzy_device_list.len() == 0 {
200 return Err(anyhow!("No devices matched the query: {}", device_topo_path));
201 } else if fuzzy_device_list.len() > 1 {
202 let mut builder = "Found multiple matches. Did you mean one of these?\n\n".to_string();
203 for item in fuzzy_device_list {
204 let device: Device = item.into();
205 builder = format!("{}{}\n", builder, device.get_full_name()?);
207 }
208 return Err(anyhow!(builder));
209 }
210 device_list = fuzzy_device_list;
211 }
212
213 let found_device = device_list.remove(0);
214 match found_device.bound_driver_url {
215 Some(ref driver_filter) => {
216 get_driver_by_filter(&driver_filter, &driver_development_proxy).await
217 }
218 _ => Err(anyhow!("Did not find driver for device {}", &device_topo_path)),
219 }
220}
221
222pub async fn get_devices_by_driver(
230 driver_filter: &String,
231 driver_development_proxy: &fdd::ManagerProxy,
232) -> Result<Vec<Device>> {
233 let driver_info = get_driver_by_filter(driver_filter, &driver_development_proxy);
234 let empty: [String; 0] = [];
235 let device_list =
236 get_device_info(&driver_development_proxy, &empty, false);
237
238 let (driver_info, device_list) = futures::join!(driver_info, device_list);
239 let (driver_info, device_list) = (driver_info?, device_list?);
240
241 let mut matches: Vec<Device> = Vec::new();
242 for device_item in device_list.into_iter() {
243 let device: Device = device_item.into();
244 if let (Some(bound_driver_url), Some(url)) = (&device.0.bound_driver_url, &driver_info.url)
245 {
246 if &url == &bound_driver_url {
247 matches.push(device);
248 }
249 }
250 }
251 Ok(matches)
252}