blob: d204d8dae5fd16405bbbc8741b6e67b608afcc94 [file] [log] [blame] [edit]
// Copyright 2023 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_DRIVER_COMPONENT_CPP_LIFECYCLE_H_
#define LIB_DRIVER_COMPONENT_CPP_LIFECYCLE_H_
#include <lib/driver/component/cpp/basic_factory.h>
namespace fdf {
// |Lifecycle| implements static |Start| and |Stop| methods which will be used by the framework.
//
// By default, it will utilize |BasicFactory| to construct your primary driver class, |Driver|,
// and invoke it's |Start| method.
//
// |Driver| must inherit from |DriverBase|. If provided, |Factory| must implement a
// public |CreateDriver| function with the following signature:
// ```
// static void CreateDriver(
// DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
// ```
//
// This illustrates how to use a |Lifecycle| with the default |BasicFactory|:
// ```
// FUCHSIA_DRIVER_LIFECYCLE_CPP_V3(fdf::Lifecycle<MyDriver>);
// ```
//
// This illustrates how to use a |Lifecycle| with a custom factory:
// ```
// class CustomFactory {
// public:
// static void CreateDriver(
// DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
// ...construct and start driver...
// };
// // We must define the lifecycle before passing into the macro, otherwise the macro expansion
// // will think the comma is to pass a second macro argument.
// using lifecycle = fdf::Lifecycle<MyDriver, CustomFactory>;
// FUCHSIA_DRIVER_LIFECYCLE_CPP_V3(lifecycle);
// ```
template <typename Driver, typename Factory = BasicFactory<Driver>>
class Lifecycle {
static_assert(std::is_base_of_v<DriverBase, Driver>, "Driver has to inherit from DriverBase");
DECLARE_HAS_MEMBER_FN(has_create_driver, CreateDriver);
static_assert(has_create_driver_v<Factory>,
"Factory must implement a public static CreateDriver function.");
static_assert(
std::is_same_v<decltype(&Factory::CreateDriver),
void (*)(DriverStartArgs, fdf::UnownedSynchronizedDispatcher,
fdf::StartCompleter)>,
"CreateDriver must be a public static function with signature "
"'void (fdf::DriverStartArgs start_args, "
"fdf::UnownedSynchronizedDispatcher driver_dispatcher, fdf::StartCompleter completer)'.");
public:
static void Start(EncodedDriverStartArgs encoded_start_args, fdf_dispatcher_t* dispatcher,
StartCompleteCallback* complete, void* complete_cookie) {
// Decode the incoming `msg`.
auto wire_format_metadata =
fidl::WireFormatMetadata::FromOpaque(encoded_start_args.wire_format_metadata);
fdf::AdoptEncodedFidlMessage encoded{encoded_start_args.msg};
fit::result start_args = fidl::StandaloneDecode<fuchsia_driver_framework::DriverStartArgs>(
encoded.TakeMessage(), wire_format_metadata);
ZX_ASSERT_MSG(start_args.is_ok(), "Failed to decode start_args: %s",
start_args.error_value().FormatDescription().c_str());
StartCompleter completer(complete, complete_cookie);
Factory::CreateDriver(std::move(*start_args), fdf::UnownedSynchronizedDispatcher(dispatcher),
std::move(completer));
}
static void PrepareStop(void* driver, PrepareStopCompleteCallback* complete,
void* complete_cookie) {
PrepareStopCompleter completer(complete, complete_cookie);
static_cast<DriverBase*>(driver)->PrepareStop(std::move(completer));
}
static zx_status_t Stop(void* driver) {
// Make a unique_ptr take ownership of the driver. Once it goes out of scope at the end of this
// function, the driver is deleted automatically.
auto driver_ptr = std::unique_ptr<DriverBase>(static_cast<DriverBase*>(driver));
driver_ptr->Stop();
return ZX_OK;
}
};
#define FUCHSIA_DRIVER_LIFECYCLE_CPP_V2(lifecycle) \
FUCHSIA_DRIVER_LIFECYCLE_V3(.start = lifecycle::Start, .prepare_stop = nullptr, \
.stop = lifecycle::Stop)
#define FUCHSIA_DRIVER_LIFECYCLE_CPP_V3(lifecycle) \
FUCHSIA_DRIVER_LIFECYCLE_V3(.start = lifecycle::Start, .prepare_stop = lifecycle::PrepareStop, \
.stop = lifecycle::Stop)
} // namespace fdf
#endif // LIB_DRIVER_COMPONENT_CPP_LIFECYCLE_H_