driver_manager_composite/
spec.rs1use crate::parent_set_collector::ParentSetCollector;
6use driver_manager_node::{Node, NodeManager, NodeProperty, NodePropertyValue};
7use fidl_fuchsia_driver_development as fdd;
8use fidl_fuchsia_driver_framework as fdf;
9use flyweights::FlyStr;
10use futures::channel::oneshot;
11use std::rc::{Rc, Weak};
12
13#[derive(Copy, Clone)]
14pub enum Condition {
15 Unknown = 0,
16 Accept = 1,
17 Reject = 2,
18}
19
20impl std::convert::From<fdf::Condition> for Condition {
21 fn from(source: fdf::Condition) -> Self {
22 match source {
23 fdf::Condition::Unknown => Self::Unknown,
24 fdf::Condition::Accept => Self::Accept,
25 fdf::Condition::Reject => Self::Reject,
26 }
27 }
28}
29
30impl std::convert::From<Condition> for fdf::Condition {
31 fn from(source: Condition) -> fdf::Condition {
32 match source {
33 Condition::Unknown => fdf::Condition::Unknown,
34 Condition::Accept => fdf::Condition::Accept,
35 Condition::Reject => fdf::Condition::Reject,
36 }
37 }
38}
39
40#[derive(Clone)]
41pub struct BindRule {
42 pub key: FlyStr,
43 pub condition: Condition,
44 pub values: Vec<NodePropertyValue>,
45}
46
47impl std::convert::From<fdf::BindRule2> for BindRule {
48 fn from(source: fdf::BindRule2) -> Self {
49 Self {
50 key: FlyStr::new(source.key),
51 condition: source.condition.into(),
52 values: source.values.into_iter().map(|v| v.into()).collect(),
53 }
54 }
55}
56
57impl std::convert::From<BindRule> for fdf::BindRule2 {
58 fn from(source: BindRule) -> fdf::BindRule2 {
59 fdf::BindRule2 {
60 key: source.key.to_string(),
61 condition: source.condition.into(),
62 values: source.values.into_iter().map(|v| v.into()).collect(),
63 }
64 }
65}
66
67#[derive(Clone)]
68pub struct ParentSpec {
69 pub bind_rules: Vec<BindRule>,
70 pub properties: Vec<NodeProperty>,
71}
72
73impl std::convert::From<fdf::ParentSpec2> for ParentSpec {
74 fn from(source: fdf::ParentSpec2) -> Self {
75 Self {
76 bind_rules: source.bind_rules.into_iter().map(|b| b.into()).collect(),
77 properties: source.properties.into_iter().map(|p| p.into()).collect(),
78 }
79 }
80}
81
82impl std::convert::From<ParentSpec> for fdf::ParentSpec2 {
83 fn from(source: ParentSpec) -> fdf::ParentSpec2 {
84 fdf::ParentSpec2 {
85 bind_rules: source.bind_rules.into_iter().map(|b| b.into()).collect(),
86 properties: source.properties.into_iter().map(|p| p.into()).collect(),
87 }
88 }
89}
90
91#[derive(Clone)]
92pub struct NodeSpec {
93 pub name: String,
94 pub parents: Vec<ParentSpec>,
95 pub driver_host: Option<String>,
96}
97
98impl std::convert::From<fdf::CompositeNodeSpec> for NodeSpec {
99 fn from(source: fdf::CompositeNodeSpec) -> Self {
100 Self {
101 name: source.name.unwrap(),
102 parents: source.parents2.unwrap().into_iter().map(|p| p.into()).collect(),
103 driver_host: source.driver_host,
104 }
105 }
106}
107
108#[derive(Clone)]
109pub struct DriverInfo {
110 pub url: String,
111 pub name: Option<String>,
112 pub colocate: bool,
113 pub package_type: fdf::DriverPackageType,
114 pub is_fallback: bool,
115 pub device_categories: Vec<fdf::DeviceCategory>,
116 pub bind_rules_bytecode: Vec<u8>,
117 pub driver_framework_version: u8,
118 pub is_disabled: bool,
119}
120
121impl std::convert::From<fdf::DriverInfo> for DriverInfo {
122 fn from(source: fdf::DriverInfo) -> Self {
123 Self {
124 url: source.url.unwrap(),
125 name: source.name,
126 colocate: source.colocate.unwrap(),
127 package_type: source.package_type.unwrap(),
128 is_fallback: source.is_fallback.unwrap(),
129 device_categories: source.device_categories.unwrap(),
130 bind_rules_bytecode: source.bind_rules_bytecode.unwrap_or_default(),
131 driver_framework_version: source.driver_framework_version.unwrap(),
132 is_disabled: source.is_disabled.unwrap(),
133 }
134 }
135}
136
137impl std::convert::From<DriverInfo> for fdf::DriverInfo {
138 fn from(source: DriverInfo) -> fdf::DriverInfo {
139 fdf::DriverInfo {
140 url: Some(source.url),
141 name: source.name,
142 colocate: Some(source.colocate),
143 package_type: Some(source.package_type),
144 is_fallback: Some(source.is_fallback),
145 device_categories: Some(source.device_categories),
146 bind_rules_bytecode: Some(source.bind_rules_bytecode),
147 driver_framework_version: Some(source.driver_framework_version),
148 is_disabled: Some(source.is_disabled),
149 ..Default::default()
150 }
151 }
152}
153
154#[derive(Clone)]
155pub struct CompositeDriverInfo {
156 pub composite_name: String,
157 pub driver_info: DriverInfo,
158}
159
160impl std::convert::From<fdf::CompositeDriverInfo> for CompositeDriverInfo {
161 fn from(source: fdf::CompositeDriverInfo) -> Self {
162 Self {
163 composite_name: source.composite_name.unwrap(),
164 driver_info: source.driver_info.unwrap().into(),
165 }
166 }
167}
168
169#[derive(Clone)]
170pub struct CompositeDriverMatch {
171 pub composite_driver: CompositeDriverInfo,
172 pub parent_names: Vec<String>,
173 pub primary_parent_index: u32,
174}
175
176impl std::convert::From<fdf::CompositeDriverMatch> for CompositeDriverMatch {
177 fn from(source: fdf::CompositeDriverMatch) -> Self {
178 Self {
179 composite_driver: source.composite_driver.unwrap().into(),
180 parent_names: source.parent_names.unwrap(),
181 primary_parent_index: source.primary_parent_index.unwrap_or(0),
182 }
183 }
184}
185
186#[derive(Clone)]
187pub struct CompositeInfo {
188 pub spec: NodeSpec,
189 pub matched_driver: CompositeDriverMatch,
190}
191
192impl std::convert::From<fdf::CompositeInfo> for CompositeInfo {
193 fn from(source: fdf::CompositeInfo) -> Self {
194 Self {
195 spec: source.spec.unwrap().into(),
196 matched_driver: source.matched_driver.unwrap().into(),
197 }
198 }
199}
200
201pub struct CompositeNodeSpec {
202 #[allow(unused)]
203 name: String,
204 parent_specs: Vec<ParentSpec>,
205 parent_nodes: Vec<Option<Weak<Node>>>,
206 parent_set_collector: Option<ParentSetCollector>,
207 driver_url: String,
208 node_manager: Box<dyn NodeManager>,
209 composite_info: Option<CompositeInfo>,
210 driver_host_name_for_colocation: String,
211}
212
213impl CompositeNodeSpec {
214 pub fn new(
215 name: String,
216 parent_specs: Vec<fdf::ParentSpec2>,
217 node_manager: Box<dyn NodeManager>,
218 driver_host_name_for_colocation: String,
219 ) -> Self {
220 let parent_nodes = vec![None; parent_specs.len()];
221 Self {
222 name,
223 parent_specs: parent_specs.into_iter().map(|p| p.into()).collect(),
224 parent_nodes,
225 parent_set_collector: None,
226 driver_url: String::new(),
227 node_manager,
228 composite_info: None,
229 driver_host_name_for_colocation,
230 }
231 }
232
233 fn bind_parent_impl(
234 &mut self,
235 composite_parent: fdf::CompositeParent,
236 node_ptr: Weak<Node>,
237 ) -> Result<Option<Weak<Node>>, zx::Status> {
238 if self.composite_info.is_none() {
239 self.composite_info = composite_parent.composite.map(|c| c.into());
240 }
241
242 let composite_info = self.composite_info.as_ref().unwrap();
243 let spec = &composite_info.spec;
244 let matched_driver = &composite_info.matched_driver;
245 let spec_name = &spec.name;
246 let composite_driver = &matched_driver.composite_driver;
247 let driver_info = &composite_driver.driver_info;
248 let parent_names = &matched_driver.parent_names;
249 let primary_index = matched_driver.primary_parent_index;
250 let url = &driver_info.url;
251
252 if self.parent_set_collector.is_none() {
253 self.parent_set_collector = Some(ParentSetCollector::new(
254 spec_name.clone(),
255 parent_names.clone(),
256 primary_index,
257 self.driver_host_name_for_colocation.clone(),
258 ));
259 self.driver_url = url.clone();
260 }
261
262 let collector = self.parent_set_collector.as_mut().unwrap();
263 let index = composite_parent.index.unwrap();
264 let properties = self.parent_specs[index as usize].properties.clone();
265 collector.add_node(index, properties, node_ptr)?;
266
267 match collector.try_to_assemble(self.node_manager.clone_box()) {
268 Ok(node) => Ok(Some(Rc::downgrade(&node))),
269 Err(zx::Status::SHOULD_WAIT) => Ok(None),
270 Err(e) => Err(e),
271 }
272 }
273
274 pub fn bind_parent(
275 &mut self,
276 composite_parent: fdf::CompositeParent,
277 node_ptr: Weak<Node>,
278 ) -> Result<Option<Weak<Node>>, zx::Status> {
279 let node_index = composite_parent.index.unwrap() as usize;
280 if node_index >= self.parent_nodes.len() {
281 return Err(zx::Status::OUT_OF_RANGE);
282 }
283
284 if let Some(current_at_index) = &self.parent_nodes[node_index]
285 && current_at_index.upgrade().is_some()
286 {
287 return Err(zx::Status::ALREADY_BOUND);
288 }
289
290 let result = self.bind_parent_impl(composite_parent, node_ptr.clone());
291 if result.is_ok() {
292 self.parent_nodes[node_index] = Some(node_ptr);
293 }
294 result
295 }
296
297 pub fn get_composite_info(&self) -> fdd::CompositeNodeInfo {
298 let mut info = fdd::CompositeNodeInfo::default();
299
300 let (spec, matched_driver) = if let Some(composite_info) = &self.composite_info {
301 let spec = Some(fdf::CompositeNodeSpec {
302 name: Some(composite_info.spec.name.clone()),
303 parents2: Some(
304 composite_info.spec.parents.clone().into_iter().map(|p| p.into()).collect(),
305 ),
306 ..Default::default()
307 });
308
309 let md = &composite_info.matched_driver;
310 let matched_driver = Some(fdf::CompositeDriverMatch {
311 composite_driver: Some({
312 fdf::CompositeDriverInfo {
313 composite_name: Some(md.composite_driver.composite_name.clone()),
314 driver_info: Some(md.composite_driver.driver_info.clone().into()),
315 ..Default::default()
316 }
317 }),
318 parent_names: Some(md.parent_names.clone()),
319 primary_parent_index: Some(md.primary_parent_index),
320 ..Default::default()
321 });
322 (spec, matched_driver)
323 } else {
324 let spec = Some(fdf::CompositeNodeSpec {
325 name: Some(self.name.clone()),
326 parents2: Some(self.parent_specs.clone().into_iter().map(|p| p.into()).collect()),
327 ..Default::default()
328 });
329 (spec, None)
330 };
331
332 info.composite = Some(fdd::CompositeInfo::Composite(fdf::CompositeInfo {
333 spec,
334 matched_driver,
335 ..Default::default()
336 }));
337
338 if self.parent_set_collector.is_none() {
339 info.parent_topological_paths = Some(vec![None; self.parent_nodes.len()]);
340 info.parent_monikers = Some(vec![None; self.parent_nodes.len()]);
341 return info;
342 }
343
344 let collector = self.parent_set_collector.as_ref().unwrap();
345 info.parent_topological_paths = Some(collector.get_parent_topological_paths());
346 info.parent_monikers = Some(collector.get_parent_monikers());
347
348 if let Some(node_weak) = collector.completed_composite_node()
349 && let Some(node) = node_weak.upgrade()
350 {
351 info.topological_path = Some(node.make_topological_path(false));
352 info.moniker = Some(node.make_component_moniker());
353 }
354 info
355 }
356
357 pub fn remove(&mut self, callback: oneshot::Sender<Result<(), zx::Status>>) {
358 self.parent_nodes = vec![None; self.parent_specs.len()];
359 if self.parent_set_collector.is_none() {
360 let _ = callback.send(Ok(()));
361 return;
362 }
363
364 let collector = self.parent_set_collector.as_mut().unwrap();
365 collector.release_nodes();
366
367 if let Some(node_weak) = collector.completed_composite_node()
368 && let Some(node) = node_weak.upgrade()
369 {
370 node.remove_composite_node_for_rebind(callback);
371 self.parent_set_collector = None;
372 self.driver_url.clear();
373 self.composite_info = None;
374 return;
375 }
376
377 self.parent_set_collector = None;
378 self.driver_url.clear();
379 self.composite_info = None;
380 let _ = callback.send(Ok(()));
381 }
382}