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_driver_host_info(service: &fdd::ManagerProxy) -> Result<Vec<fdd::DriverHostInfo>> {
121 let (iterator, iterator_server) =
122 fidl::endpoints::create_proxy::<fdd::DriverHostInfoIteratorMarker>();
123
124 service
125 .get_driver_host_info(iterator_server)
126 .context("FIDL call to get driver host info failed")?;
127
128 let mut info_result = Vec::new();
129 loop {
130 let mut info =
131 iterator.get_next().await.context("FIDL call to get driver host info failed")?;
132 if info.is_empty() {
133 break;
134 }
135 info_result.append(&mut info)
136 }
137 Ok(info_result)
138}
139
140pub async fn get_composite_node_specs(
142 service: &fdd::ManagerProxy,
143 name_filter: Option<String>,
144) -> Result<Vec<fdf::CompositeInfo>> {
145 let (iterator, iterator_server) =
146 fidl::endpoints::create_proxy::<fdd::CompositeNodeSpecIteratorMarker>();
147
148 service
149 .get_composite_node_specs(name_filter.as_deref(), iterator_server)
150 .context("FIDL call to get node groups failed")?;
151
152 let mut info_result = Vec::new();
153 loop {
154 let mut node_groups =
155 iterator.get_next().await.context("FIDL call to get node groups failed")?;
156 if node_groups.is_empty() {
157 break;
158 }
159 info_result.append(&mut node_groups)
160 }
161 Ok(info_result)
162}
163
164pub async fn get_driver_by_filter(
172 driver_filter: &String,
173 driver_development_proxy: &fdd::ManagerProxy,
174) -> Result<fdf::DriverInfo> {
175 let filter_list: [String; 1] = [driver_filter.to_string()];
176 let driver_list = get_driver_info(&driver_development_proxy, &filter_list).await?;
177 if driver_list.len() != 1 {
178 return Err(anyhow!(
179 "There should be exactly one match for '{}'. Found {}.",
180 driver_filter,
181 driver_list.len()
182 ));
183 }
184 let mut driver_info: Option<fdf::DriverInfo> = None;
185
186 let driver = &driver_list[0];
188 if let Some(ref url) = driver.url {
189 if url == driver_filter {
190 driver_info = Some(driver.clone());
191 }
192 }
193 match driver_info {
194 Some(driver) => Ok(driver),
195 _ => Err(anyhow!("Did not find matching driver for: {}", driver_filter)),
196 }
197}
198
199pub async fn get_driver_by_device(
207 device_topo_path: &String,
208 driver_development_proxy: &fdd::ManagerProxy,
209) -> Result<fdf::DriverInfo> {
210 let device_filter: [String; 1] = [device_topo_path.to_string()];
211 let mut device_list =
212 get_device_info(&driver_development_proxy, &device_filter, true).await?;
213 if device_list.len() != 1 {
214 let fuzzy_device_list = get_device_info(
215 &driver_development_proxy,
216 &device_filter,
217 false,
218 )
219 .await?;
220 if fuzzy_device_list.len() == 0 {
221 return Err(anyhow!("No devices matched the query: {}", device_topo_path));
222 } else if fuzzy_device_list.len() > 1 {
223 let mut builder = "Found multiple matches. Did you mean one of these?\n\n".to_string();
224 for item in fuzzy_device_list {
225 let device: Device = item.into();
226 builder = format!("{}{}\n", builder, device.get_full_name()?);
228 }
229 return Err(anyhow!(builder));
230 }
231 device_list = fuzzy_device_list;
232 }
233
234 let found_device = device_list.remove(0);
235 match found_device.bound_driver_url {
236 Some(ref driver_filter) => {
237 get_driver_by_filter(&driver_filter, &driver_development_proxy).await
238 }
239 _ => Err(anyhow!("Did not find driver for device {}", &device_topo_path)),
240 }
241}
242
243pub async fn get_devices_by_driver(
251 driver_filter: &String,
252 driver_development_proxy: &fdd::ManagerProxy,
253) -> Result<Vec<Device>> {
254 let driver_info = get_driver_by_filter(driver_filter, &driver_development_proxy);
255 let empty: [String; 0] = [];
256 let device_list =
257 get_device_info(&driver_development_proxy, &empty, false);
258
259 let (driver_info, device_list) = futures::join!(driver_info, device_list);
260 let (driver_info, device_list) = (driver_info?, device_list?);
261
262 let mut matches: Vec<Device> = Vec::new();
263 for device_item in device_list.into_iter() {
264 let device: Device = device_item.into();
265 if let (Some(bound_driver_url), Some(url)) = (&device.0.bound_driver_url, &driver_info.url)
266 {
267 if &url == &bound_driver_url {
268 matches.push(device);
269 }
270 }
271 }
272 Ok(matches)
273}