driver_manager_composite/
composite_node_spec_manager.rs1use crate::{CompositeManagerBridge, CompositeNodeSpec};
6use driver_manager_bind::{BindSpecResult, CompositeNodeAndDriver};
7use driver_manager_node::Node;
8use fidl_fuchsia_driver_development as fdd;
9use fidl_fuchsia_driver_framework as fdf;
10use fuchsia_async as fasync;
11use futures::channel::oneshot;
12use log::{error, warn};
13use std::cell::RefCell;
14use std::collections::HashMap;
15use std::rc::Weak;
16
17pub struct CompositeNodeSpecManager {
18 bridge: Box<dyn CompositeManagerBridge>,
19 specs: RefCell<HashMap<String, CompositeNodeSpec>>,
20}
21
22impl CompositeNodeSpecManager {
23 pub fn new(bridge: Box<dyn CompositeManagerBridge>) -> Self {
24 Self { bridge, specs: RefCell::new(HashMap::new()) }
25 }
26
27 pub async fn add_spec(
28 &self,
29 fidl_spec: fdf::CompositeNodeSpec,
30 spec: CompositeNodeSpec,
31 ) -> Result<(), fdf::CompositeNodeSpecError> {
32 let name = fidl_spec.name.as_ref().unwrap().clone();
33 if self.specs.borrow().contains_key(&name) {
34 error!("Duplicate composite node spec {}", name);
35 return Err(fdf::CompositeNodeSpecError::AlreadyExists);
36 }
37
38 if let Err(e) = self.bridge.add_spec_to_driver_index(fidl_spec).await {
39 error!("Failed to add composite node spec to driver index: {}", e);
40 return Err(fdf::CompositeNodeSpecError::DriverIndexFailure);
41 }
42
43 self.specs.borrow_mut().insert(name, spec);
44 let bridge = self.bridge.box_clone();
45 fasync::Task::local(async move {
46 bridge.bind_nodes_for_composite_node_spec().await;
47 })
48 .detach();
49 Ok(())
50 }
51
52 pub fn bind_parent_spec(
53 &self,
54 composite_parents: &[fdf::CompositeParent],
55 node_ptr: Weak<Node>,
56 enable_multibind: bool,
57 ) -> Result<BindSpecResult, zx::Status> {
58 if composite_parents.is_empty() {
59 error!("composite_parents needs to contain at least one composite parent.");
60 return Err(zx::Status::INVALID_ARGS);
61 }
62
63 let mut bound_composite_parents = Vec::new();
64 let mut node_and_drivers = Vec::new();
65
66 for composite_parent in composite_parents {
67 let composite = match &composite_parent.composite {
68 Some(c) => c,
69 None => {
70 warn!("CompositeParent missing composite.");
71 continue;
72 }
73 };
74
75 let index = match composite_parent.index {
76 Some(i) => i,
77 None => {
78 warn!("CompositeParent missing index.");
79 continue;
80 }
81 };
82
83 let matched_driver = match &composite.matched_driver {
84 Some(md) => md,
85 None => continue,
86 };
87
88 if matched_driver.composite_driver.is_none() || matched_driver.parent_names.is_none() {
89 warn!("CompositeDriverMatch does not have all needed fields.");
90 continue;
91 }
92
93 let spec_info = match &composite.spec {
94 Some(s) => s,
95 None => {
96 warn!("CompositeInfo missing spec.");
97 continue;
98 }
99 };
100
101 let (name, parents) = match (&spec_info.name, &spec_info.parents2) {
102 (Some(name), Some(parents)) => (name, parents.len()),
103 _ => {
104 warn!("CompositeNodeSpec missing name or parents2.");
105 continue;
106 }
107 };
108
109 if index as usize >= parents
110 || matched_driver.parent_names.as_ref().unwrap().len() != parents
111 {
112 warn!(
113 "Parent names count does not match the spec parent count or index is out of bounds."
114 );
115 continue;
116 }
117
118 let mut specs = self.specs.borrow_mut();
119 let spec = match specs.get_mut(name) {
120 Some(s) => s,
121 None => {
122 error!("Missing composite node spec {}", name);
123 continue;
124 }
125 };
126
127 match spec.bind_parent(composite_parent.clone(), node_ptr.clone()) {
128 Ok(Some(composite_node)) => {
129 bound_composite_parents.push(composite_parent.clone());
130 if let Some(driver) = &matched_driver.composite_driver {
131 node_and_drivers.push(CompositeNodeAndDriver {
132 driver: driver.clone(),
133 node: composite_node,
134 });
135 }
136 }
137 Ok(None) => {
138 bound_composite_parents.push(composite_parent.clone());
139 }
140 Err(zx::Status::ALREADY_BOUND) => {
141 continue;
142 }
143 Err(e) => {
144 error!("Failed to bind node: {}", e);
145 continue;
146 }
147 }
148
149 if !enable_multibind {
150 break;
151 }
152 }
153
154 if !bound_composite_parents.is_empty() {
155 Ok(BindSpecResult {
156 bound_composite_parents,
157 completed_node_and_drivers: node_and_drivers,
158 })
159 } else {
160 Err(zx::Status::NOT_FOUND)
161 }
162 }
163
164 pub async fn rebind(
165 &self,
166 spec_name: String,
167 restart_driver_url_suffix: Option<String>,
168 ) -> Result<(), zx::Status> {
169 if !self.specs.borrow().contains_key(&spec_name) {
170 warn!("Spec {} is not available for rebind", spec_name);
171 return Err(zx::Status::NOT_FOUND);
172 }
173
174 self.bridge
175 .request_rebind_from_driver_index(spec_name.clone(), restart_driver_url_suffix)
176 .await?;
177
178 self.on_request_rebind_complete(spec_name).await
179 }
180
181 async fn on_request_rebind_complete(&self, spec_name: String) -> Result<(), zx::Status> {
182 let rx = {
183 let mut specs = self.specs.borrow_mut();
184 let spec = specs.get_mut(&spec_name).unwrap();
185
186 let (tx, rx) = oneshot::channel();
187 spec.remove(tx);
188 rx
189 };
190 rx.await.map_err(|_| zx::Status::INTERNAL)??;
191
192 log::debug!("Rebinding composite node spec {}", spec_name);
193 self.bridge.bind_nodes_for_composite_node_spec().await;
194 Ok(())
195 }
196
197 pub fn get_composite_info(&self) -> Vec<fdd::CompositeNodeInfo> {
198 self.specs.borrow().values().map(|spec| spec.get_composite_info()).collect()
199 }
200}