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