Skip to main content

driver_tools/subcommands/list_composites/
mod.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5pub mod args;
6
7use anyhow::{Context, Result};
8use args::ListCompositesCommand;
9use flex_client::ProxyHasDomain;
10use std::io::Write;
11use {flex_fuchsia_driver_development as fdd, flex_fuchsia_driver_framework as fdf};
12
13pub async fn list_composites(
14    cmd: ListCompositesCommand,
15    writer: &mut dyn Write,
16    proxy: fdd::ManagerProxy,
17) -> Result<()> {
18    writeln!(
19        writer,
20        "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
21    )?;
22
23    let (iterator, iterator_server) =
24        proxy.domain().create_proxy::<fdd::CompositeInfoIteratorMarker>();
25    proxy.get_composite_info(iterator_server).context("GetCompositeInfo() failed")?;
26
27    loop {
28        let composite_list =
29            iterator.get_next().await.context("CompositeInfoIterator GetNext() failed")?;
30
31        if composite_list.is_empty() {
32            break;
33        }
34
35        for composite_node in composite_list {
36            match composite_node.composite {
37                Some(fdd::CompositeInfo::Composite(info)) => {
38                    write_composite(
39                        writer,
40                        info,
41                        composite_node.parent_topological_paths.unwrap(),
42                        composite_node.topological_path,
43                        cmd.verbose,
44                    )?;
45                }
46                _ => {}
47            }
48        }
49    }
50
51    Ok(())
52}
53
54fn write_composite(
55    writer: &mut dyn Write,
56    composite: fdf::CompositeInfo,
57    parent_topological_paths: Vec<Option<String>>,
58    topological_path: Option<String>,
59    verbose: bool,
60) -> Result<()> {
61    let spec = composite.spec.unwrap_or_default();
62    let driver_match = composite.matched_driver.unwrap_or_default();
63    if !verbose {
64        writeln!(writer, "{}", spec.name.unwrap_or_else(|| "".to_string()))?;
65        return Ok(());
66    }
67
68    writeln!(writer, "{0: <9}: {1}", "Name", spec.name.unwrap_or_else(|| "".to_string()))?;
69    writeln!(
70        writer,
71        "{0: <9}: {1}",
72        "Driver",
73        driver_match
74            .composite_driver
75            .and_then(|composite_driver| composite_driver.driver_info)
76            .and_then(|driver_info| driver_info.url)
77            .unwrap_or_else(|| "N/A".to_string())
78    )?;
79    writeln!(
80        writer,
81        "{0: <9}: {1}",
82        "Device",
83        topological_path.unwrap_or_else(|| "N/A".to_string())
84    )?;
85
86    write_parent_nodes_info(
87        writer,
88        driver_match.primary_parent_index,
89        driver_match.parent_names.unwrap_or_default(),
90        parent_topological_paths,
91    )?;
92
93    writeln!(writer)?;
94    Ok(())
95}
96
97fn write_parent_nodes_info(
98    writer: &mut dyn Write,
99    primary_index: Option<u32>,
100    parent_names: Vec<String>,
101    parent_paths: Vec<Option<String>>,
102) -> Result<()> {
103    writeln!(writer, "{0: <9}: {1}", "Parents", parent_names.len())?;
104    for (i, parent_name) in parent_names.into_iter().enumerate() {
105        let primary_tag = if primary_index == Some(i as u32) { "(Primary)" } else { "" };
106        writeln!(writer, "{0: <1} {1} : {2} {3}", "Parent", i, parent_name, primary_tag)?;
107
108        writeln!(
109            writer,
110            "   {0: <1} : {1}",
111            "Device",
112            parent_paths[i].clone().unwrap_or_else(|| "Unbound".to_string())
113        )?;
114    }
115    Ok(())
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use fuchsia_async as fasync;
122    use std::io::Error;
123
124    pub struct TestWriteBuffer {
125        pub content: String,
126    }
127
128    impl Write for TestWriteBuffer {
129        fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
130            self.content.push_str(std::str::from_utf8(buf).unwrap());
131            Ok(buf.len())
132        }
133
134        fn flush(&mut self) -> Result<(), Error> {
135            Ok(())
136        }
137    }
138
139    #[fasync::run_singlethreaded(test)]
140    async fn test_composite_verbose() {
141        let test_composite = fdf::CompositeInfo {
142            spec: Some(fdf::CompositeNodeSpec {
143                name: Some("composite_dev".to_string()),
144                ..Default::default()
145            }),
146            matched_driver: Some(fdf::CompositeDriverMatch {
147                composite_driver: Some(fdf::CompositeDriverInfo {
148                    driver_info: Some(fdf::DriverInfo {
149                        url: Some("fuchsia-boot:///#meta/waxwing.cm".to_string()),
150                        ..Default::default()
151                    }),
152                    ..Default::default()
153                }),
154                parent_names: Some(vec!["sysmem".to_string(), "acpi".to_string()]),
155                primary_parent_index: Some(1),
156                ..Default::default()
157            }),
158            ..Default::default()
159        };
160
161        let mut test_write_buffer = TestWriteBuffer { content: "".to_string() };
162        writeln!(
163            &mut test_write_buffer,
164            "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
165        )
166        .unwrap();
167        write_composite(
168            &mut test_write_buffer,
169            test_composite,
170            vec![Some("path/sysmem_dev".to_string()), Some("path/acpi_dev".to_string())],
171            Some("dev/sys/composite_dev".to_string()),
172            true,
173        )
174        .unwrap();
175        assert_eq!(
176            format!(
177                "WARNING: This command is deprecated. Use `ffx driver composite list` instead.\n{}",
178                include_str!("../../../tests/golden/list_composites_verbose")
179            ),
180            test_write_buffer.content
181        );
182    }
183
184    #[fasync::run_singlethreaded(test)]
185    async fn test_composite_verbose_empty_fields() {
186        let test_composite = fdf::CompositeInfo {
187            spec: Some(fdf::CompositeNodeSpec {
188                name: Some("composite_dev".to_string()),
189                ..Default::default()
190            }),
191            matched_driver: Some(fdf::CompositeDriverMatch {
192                composite_driver: Some(fdf::CompositeDriverInfo {
193                    composite_name: Some("composite_name".to_string()),
194                    driver_info: Some(fdf::DriverInfo {
195                        url: Some("fuchsia-boot:///#meta/waxwing.cm".to_string()),
196                        ..Default::default()
197                    }),
198                    ..Default::default()
199                }),
200                parent_names: Some(vec!["sysmem".to_string(), "acpi".to_string()]),
201                primary_parent_index: Some(1),
202                ..Default::default()
203            }),
204            ..Default::default()
205        };
206
207        let mut test_write_buffer = TestWriteBuffer { content: "".to_string() };
208        writeln!(
209            &mut test_write_buffer,
210            "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
211        )
212        .unwrap();
213        write_composite(
214            &mut test_write_buffer,
215            test_composite,
216            vec![None, None],
217            Some("dev/sys/composite_dev".to_string()),
218            true,
219        )
220        .unwrap();
221        println!("{}", test_write_buffer.content);
222
223        assert_eq!(
224            format!(
225                "WARNING: This command is deprecated. Use `ffx driver composite list` instead.\n{}",
226                include_str!("../../../tests/golden/list_composites_verbose_empty_fields")
227            ),
228            test_write_buffer.content
229        );
230    }
231}