fuchsia_driver_dev/
lib.rs
1use anyhow::{anyhow, format_err, Context, Result};
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 loop {
54 let mut device_info =
55 iterator.get_next().await.context("FIDL call to get device info failed")?;
56 if device_info.len() == 0 {
57 break;
58 }
59 info_result.append(&mut device_info)
60 }
61 Ok(info_result)
62}
63
64pub async fn get_driver_info(
66 service: &fdd::ManagerProxy,
67 driver_filter: &[String],
68) -> Result<Vec<fdf::DriverInfo>> {
69 let (iterator, iterator_server) =
70 fidl::endpoints::create_proxy::<fdd::DriverInfoIteratorMarker>();
71
72 service
73 .get_driver_info(driver_filter, iterator_server)
74 .context("FIDL call to get driver info failed")?;
75
76 let mut info_result = Vec::new();
77 loop {
78 let mut driver_info =
79 iterator.get_next().await.context("FIDL call to get driver info failed")?;
80 if driver_info.len() == 0 {
81 break;
82 }
83 info_result.append(&mut driver_info)
84 }
85 Ok(info_result)
86}
87
88pub async fn get_composite_node_specs(
90 service: &fdd::ManagerProxy,
91 name_filter: Option<String>,
92) -> Result<Vec<fdf::CompositeInfo>> {
93 let (iterator, iterator_server) =
94 fidl::endpoints::create_proxy::<fdd::CompositeNodeSpecIteratorMarker>();
95
96 service
97 .get_composite_node_specs(name_filter.as_deref(), iterator_server)
98 .context("FIDL call to get node groups failed")?;
99
100 let mut info_result = Vec::new();
101 loop {
102 let mut node_groups =
103 iterator.get_next().await.context("FIDL call to get node groups failed")?;
104 if node_groups.is_empty() {
105 break;
106 }
107 info_result.append(&mut node_groups)
108 }
109 Ok(info_result)
110}
111
112pub async fn get_driver_by_filter(
120 driver_filter: &String,
121 driver_development_proxy: &fdd::ManagerProxy,
122) -> Result<fdf::DriverInfo> {
123 let filter_list: [String; 1] = [driver_filter.to_string()];
124 let driver_list = get_driver_info(&driver_development_proxy, &filter_list).await?;
125 if driver_list.len() != 1 {
126 return Err(anyhow!(
127 "There should be exactly one match for '{}'. Found {}.",
128 driver_filter,
129 driver_list.len()
130 ));
131 }
132 let mut driver_info: Option<fdf::DriverInfo> = None;
133
134 let driver = &driver_list[0];
136 if let Some(ref url) = driver.url {
137 if url == driver_filter {
138 driver_info = Some(driver.clone());
139 }
140 }
141 match driver_info {
142 Some(driver) => Ok(driver),
143 _ => Err(anyhow!("Did not find matching driver for: {}", driver_filter)),
144 }
145}
146
147pub async fn get_driver_by_device(
155 device_topo_path: &String,
156 driver_development_proxy: &fdd::ManagerProxy,
157) -> Result<fdf::DriverInfo> {
158 let device_filter: [String; 1] = [device_topo_path.to_string()];
159 let mut device_list =
160 get_device_info(&driver_development_proxy, &device_filter, true).await?;
161 if device_list.len() != 1 {
162 let fuzzy_device_list = get_device_info(
163 &driver_development_proxy,
164 &device_filter,
165 false,
166 )
167 .await?;
168 if fuzzy_device_list.len() == 0 {
169 return Err(anyhow!("No devices matched the query: {}", device_topo_path.to_string()));
170 } else if fuzzy_device_list.len() > 1 {
171 let mut builder = "Found multiple matches. Did you mean one of these?\n\n".to_string();
172 for item in fuzzy_device_list {
173 let device: Device = item.into();
174 builder = format!("{}{}\n", builder, device.get_full_name()?);
176 }
177 return Err(anyhow!(builder));
178 }
179 device_list = fuzzy_device_list;
180 }
181
182 let found_device = device_list.remove(0);
183 match found_device.bound_driver_url {
184 Some(ref driver_filter) => {
185 get_driver_by_filter(&driver_filter, &driver_development_proxy).await
186 }
187 _ => Err(anyhow!("Did not find driver for device {}", &device_topo_path)),
188 }
189}
190
191pub async fn get_devices_by_driver(
199 driver_filter: &String,
200 driver_development_proxy: &fdd::ManagerProxy,
201) -> Result<Vec<Device>> {
202 let driver_info = get_driver_by_filter(driver_filter, &driver_development_proxy);
203 let empty: [String; 0] = [];
204 let device_list =
205 get_device_info(&driver_development_proxy, &empty, false);
206
207 let (driver_info, device_list) = futures::join!(driver_info, device_list);
208 let (driver_info, device_list) = (driver_info?, device_list?);
209
210 let mut matches: Vec<Device> = Vec::new();
211 for device_item in device_list.into_iter() {
212 let device: Device = device_item.into();
213 if let (Some(bound_driver_url), Some(url)) = (&device.0.bound_driver_url, &driver_info.url)
214 {
215 if &url == &bound_driver_url {
216 matches.push(device);
217 }
218 }
219 }
220 Ok(matches)
221}