1// Copyright 2024 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.
45use fdf_component::{
6 driver_register, Driver, DriverContext, Node, NodeBuilder, ZirconServiceOffer,
7};
8use fidl_fuchsia_hardware_i2c as i2c;
9use fuchsia_component::server::ServiceFs;
10use futures::{StreamExt, TryStreamExt};
11use log::info;
12use zx::Status;
1314/// The implementation of our driver will live in this object, which implements [`Driver`].
15#[allow(unused)]
16struct ZirconParentDriver {
17/// The [`NodeProxy`] is our handle to the node we bound to. We need to keep this handle
18 /// open to keep the node around.
19node: Node,
20}
2122// This creates the exported driver registration structures that allow the driver host to
23// find and run the start and stop methods on our `ZirconParentDriver`.
24driver_register!(ZirconParentDriver);
2526async fn i2c_server(mut service: i2c::DeviceRequestStream) {
27use i2c::DeviceRequest::*;
28while let Some(req) = service.try_next().await.unwrap() {
29match req {
30 Transfer { responder, .. } => responder.send(Ok(&[vec![0x1u8, 0x2, 0x3]])),
31 GetName { responder } => responder.send(Ok("rust i2c server")),
32 }
33 .unwrap();
34 }
35}
3637impl Driver for ZirconParentDriver {
38const NAME: &str = "zircon_parent_rust_driver";
3940async fn start(mut context: DriverContext) -> Result<Self, Status> {
41info!("Binding node client. Every driver needs to do this for the driver to be considered loaded.");
42let node = context.take_node()?;
4344info!("Offering an i2c service in the outgoing directory");
45let mut outgoing = ServiceFs::new();
46let offer = ZirconServiceOffer::new()
47 .add_default_named(&mut outgoing, "default", |i| {
48// Since we're only acting on one kind of service here, we just unwrap it and that's
49 // the type of our handler. If you were handling more services, you would usually
50 // wrap it in an enum containing one discriminant per protocol handled.
51let i2c::ServiceRequest::Device(service) = i;
52 service
53 })
54 .build();
5556info!("Creating child node with a service offer");
57let child_node = NodeBuilder::new("zircon_transport_rust_child").add_offer(offer).build();
58 node.add_child(child_node).await?;
5960 context.serve_outgoing(&mut outgoing)?;
6162 fuchsia_async::Task::spawn(async move {
63 outgoing.for_each_concurrent(None, i2c_server).await;
64 })
65 .detach();
6667Ok(Self { node })
68 }
6970async fn stop(&self) {
71info!(
72"ZirconParentDriver::stop() was invoked. Use this function to do any cleanup needed."
73);
74 }
75}