| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_DRIVER2_RECORD_CPP_H_ |
| #define LIB_DRIVER2_RECORD_CPP_H_ |
| |
| #include <fidl/fuchsia.driver.framework/cpp/wire.h> |
| #include <lib/driver2/logger.h> |
| #include <lib/driver2/record.h> |
| #include <lib/fdf/cpp/dispatcher.h> |
| |
| namespace driver::internal { |
| |
| // Starts a driver `T` from `msg` and `dispatcher`, and stores the result in |
| // `driver`. |
| // |
| // This function expects `T` to contain: |
| // 1. A static function `T::Name` that returns the name to use for the logger. |
| // 2. A member function `T::Start` with the signature: |
| // zx::status<std::unique_ptr<T>> Start( |
| // fuchsia_driver_framework::wire::DriverStartArgs& start_args, |
| // fdf::UnownedDispatcher dispatcher, |
| // fidl::WireSharedClient<fuchsia_driver_framework::Node> node, |
| // driver::Namespace ns, |
| // driver::Logger logger) |
| template <typename T> |
| zx_status_t Start(EncodedDriverStartArgs encoded_start_args, fdf_dispatcher_t* dispatcher, |
| void** driver) { |
| // Decode the incoming `msg`. |
| // TODO(fxbug.dev/45252): Use FIDL at rest. |
| auto wire_format_metadata = |
| fidl::WireFormatMetadata::FromOpaque(encoded_start_args.wire_format_metadata); |
| fidl::unstable::DecodedMessage<fuchsia_driver_framework::wire::DriverStartArgs> decoded( |
| wire_format_metadata.wire_format_version(), encoded_start_args.msg); |
| if (!decoded.ok()) { |
| return decoded.status(); |
| } |
| auto start_args = decoded.PrimaryObject(); |
| |
| // Bind the node. |
| fidl::WireSharedClient<fuchsia_driver_framework::Node> node( |
| std::move(start_args->node()), fdf_dispatcher_get_async_dispatcher(dispatcher)); |
| |
| // Create the namespace. |
| auto ns = driver::Namespace::Create(start_args->ns()); |
| if (ns.is_error()) { |
| return ns.status_value(); |
| } |
| |
| // Create the logger. |
| auto logger = |
| driver::Logger::Create(*ns, fdf_dispatcher_get_async_dispatcher(dispatcher), T::Name()); |
| if (logger.is_error()) { |
| return logger.status_value(); |
| } |
| |
| // Create the driver. |
| auto self = T::Start(*start_args, fdf::UnownedDispatcher(dispatcher), std::move(node), |
| std::move(*ns), std::move(*logger)); |
| if (self.is_error()) { |
| return self.status_value(); |
| } |
| |
| // Store `driver` pointer. |
| *driver = (*self).release(); |
| return ZX_OK; |
| } |
| |
| // Stops a driver `T` by deleting it. |
| template <typename T> |
| zx_status_t Stop(void* driver) { |
| delete static_cast<T*>(driver); |
| return ZX_OK; |
| } |
| |
| } // namespace driver::internal |
| |
| #define FUCHSIA_DRIVER_RECORD_CPP_V1(T) \ |
| FUCHSIA_DRIVER_RECORD_V1(.start = driver::internal::Start<T>, .stop = driver::internal::Stop<T>) |
| |
| #endif // LIB_DRIVER2_RECORD_CPP_H_ |