driver_tools/subcommands/list_devices/
mod.rs1pub mod args;
6
7use crate::common::{node_property_key_to_string, node_property_value_to_string};
8use anyhow::{Result, anyhow};
9use args::ListDevicesCommand;
10use fuchsia_driver_dev::Device;
11use itertools::Itertools;
12use {
13 fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_driver_development as fdd,
14 fidl_fuchsia_driver_framework as fdf,
15};
16
17trait DevicePrinter {
18 fn print(&self) -> Result<()>;
19 fn print_verbose(&self) -> Result<()>;
20}
21
22impl DevicePrinter for Device {
23 fn print(&self) -> Result<()> {
24 println!("{}", self.get_moniker()?);
25 Ok(())
26 }
27
28 fn print_verbose(&self) -> Result<()> {
29 let moniker = self.get_moniker().expect("Node does not have a moniker");
30 let (_, name) = moniker.rsplit_once('.').unwrap_or(("", &moniker));
31 println!("{0: <9}: {1}", "Name", name);
32 println!("{0: <9}: {1}", "Moniker", moniker);
33
34 if self.0.quarantined == Some(true)
35 && self.0.bound_driver_url != Some("unbound".to_string())
36 {
37 println!(
38 "{0: <9}: {1} (quarantined)",
39 "Driver",
40 self.0.bound_driver_url.as_deref().unwrap_or("None")
41 );
42 } else {
43 println!(
44 "{0: <9}: {1}",
45 "Driver",
46 self.0.bound_driver_url.as_deref().unwrap_or("None")
47 );
48 }
49
50 if let Some(ref bus_topology) = self.0.bus_topology {
51 if !bus_topology.is_empty() {
52 println!("\n{0: <9} {1: <9} {2}", "Bus Type", "Stability", "Address",);
53 }
54 for segment in bus_topology {
55 let address = match &segment.address {
56 Some(fdf::DeviceAddress::IntValue(val)) => format!("{val:02X}"),
57 Some(fdf::DeviceAddress::ArrayIntValue(val)) => {
58 val.iter().map(|v| format!("{v:02X}")).join(":")
59 }
60 Some(fdf::DeviceAddress::CharIntValue(val)) => val.to_string(),
61 Some(fdf::DeviceAddress::ArrayCharIntValue(val)) => {
62 val.iter().map(|v| v.to_string()).join(":")
63 }
64 Some(fdf::DeviceAddress::StringValue(val)) => val.to_string(),
65 None => "None".to_string(),
66 _ => "Unknown".to_string(),
67 };
68 println!(
69 "{0: <9} {1: <9} {2}",
70 segment
71 .bus
72 .map(|s| format!("{s:?}").to_uppercase())
73 .unwrap_or_else(|| "Unknown".to_string()),
74 segment
75 .address_stability
76 .map(|s| format!("{s:?}"))
77 .unwrap_or_else(|| "Unknown".to_string()),
78 address,
79 );
80 }
81 if !bus_topology.is_empty() {
82 println!("");
83 }
84 }
85
86 if let Some(ref node_property_list) = self.0.node_property_list {
87 println!("{} Properties", node_property_list.len());
88 for i in 0..node_property_list.len() {
89 let node_property = &node_property_list[i];
90 println!(
91 "[{:>2}/ {:>2}] : Key {:30} Value {}",
92 i + 1,
93 node_property_list.len(),
94 node_property_key_to_string(&node_property.key),
95 node_property_value_to_string(&node_property.value),
96 );
97 }
98 } else {
99 println!("0 Properties");
100 }
101
102 if let Some(ref offer_list) = self.0.offer_list {
103 println!("{} Offers", offer_list.len());
104 for i in 0..offer_list.len() {
105 #[allow(clippy::or_fun_call)] if let fdecl::Offer::Service(service) = &offer_list[i] {
107 println!(
108 "Service: {}",
109 service.target_name.as_ref().unwrap_or(&"<unknown>".to_string())
110 );
111 if let Some(fdecl::Ref::Child(source)) = service.source.as_ref() {
112 println!(" Source: {}", source.name);
113 }
114 if let Some(filter) = &service.source_instance_filter {
115 println!(" Instances: {}", filter.join(" "));
116 }
117 }
118 }
119 } else {
120 println!("0 Offers");
121 }
122 println!("");
123 Ok(())
124 }
125}
126
127pub async fn list_devices(
128 cmd: ListDevicesCommand,
129 driver_development_proxy: fdd::ManagerProxy,
130) -> Result<()> {
131 let devices: Vec<Device> = match cmd.device {
132 Some(device) => {
133 fuchsia_driver_dev::get_device_info(&driver_development_proxy, &[device], cmd.exact)
134 .await?
135 }
136 None => {
137 fuchsia_driver_dev::get_device_info(&driver_development_proxy, &[], cmd.exact).await?
138 }
139 }
140 .into_iter()
141 .filter(|d| !cmd.unbound || d.bound_driver_url == Some("unbound".to_string()))
142 .map(|device_info| Device::from(device_info))
143 .collect();
144
145 if devices.len() > 0 {
146 if cmd.verbose {
147 for device in devices {
148 device.print_verbose()?;
149 }
150 } else {
151 for device in devices {
152 device.print()?;
153 }
154 }
155 } else {
156 if cmd.fail_on_missing {
157 return Err(anyhow!("No devices found."));
158 } else {
159 println!("No devices found.");
160 }
161 }
162
163 Ok(())
164}