|  | /* | 
|  | * Copyright (c) 2019 Peter Bigot Consulting, LLC | 
|  | * Copyright (c) 2020 Nordic Semiconductor ASA | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #ifndef ZEPHYR_INCLUDE_SYS_ONOFF_H_ | 
|  | #define ZEPHYR_INCLUDE_SYS_ONOFF_H_ | 
|  |  | 
|  | #include <kernel.h> | 
|  | #include <zephyr/types.h> | 
|  | #include <sys/notify.h> | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @defgroup resource_mgmt_onoff_apis On-Off Service APIs | 
|  | * @ingroup kernel_apis | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * @brief Flag indicating an error state. | 
|  | * | 
|  | * Error states are cleared using onoff_reset(). | 
|  | */ | 
|  | #define ONOFF_FLAG_ERROR BIT(0) | 
|  |  | 
|  | /** @internal */ | 
|  | #define ONOFF_FLAG_ONOFF BIT(1) | 
|  | /** @internal */ | 
|  | #define ONOFF_FLAG_TRANSITION BIT(2) | 
|  |  | 
|  | /** | 
|  | * @brief Mask used to isolate bits defining the service state. | 
|  | * | 
|  | * Mask a value with this then test for ONOFF_FLAG_ERROR to determine | 
|  | * whether the machine has an unfixed error, or compare against | 
|  | * ONOFF_STATE_ON, ONOFF_STATE_OFF, ONOFF_STATE_TO_ON, | 
|  | * ONOFF_STATE_TO_OFF, or ONOFF_STATE_RESETTING. | 
|  | */ | 
|  | #define ONOFF_STATE_MASK (ONOFF_FLAG_ERROR   \ | 
|  | | ONOFF_FLAG_ONOFF \ | 
|  | | ONOFF_FLAG_TRANSITION) | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when service is off. | 
|  | */ | 
|  | #define ONOFF_STATE_OFF 0U | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when service is on. | 
|  | */ | 
|  | #define ONOFF_STATE_ON ONOFF_FLAG_ONOFF | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when the service is in an | 
|  | * error state (and not in the process of resetting its state). | 
|  | */ | 
|  | #define ONOFF_STATE_ERROR ONOFF_FLAG_ERROR | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when service is | 
|  | * transitioning to on. | 
|  | */ | 
|  | #define ONOFF_STATE_TO_ON (ONOFF_FLAG_TRANSITION | ONOFF_STATE_ON) | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when service is | 
|  | * transitioning to off. | 
|  | */ | 
|  | #define ONOFF_STATE_TO_OFF (ONOFF_FLAG_TRANSITION | ONOFF_STATE_OFF) | 
|  |  | 
|  | /** | 
|  | * @brief Value exposed by ONOFF_STATE_MASK when service is in the | 
|  | * process of resetting. | 
|  | */ | 
|  | #define ONOFF_STATE_RESETTING (ONOFF_FLAG_TRANSITION | ONOFF_STATE_ERROR) | 
|  |  | 
|  | /* Forward declarations */ | 
|  | struct onoff_manager; | 
|  | struct onoff_monitor; | 
|  |  | 
|  | /** | 
|  | * @brief Signature used to notify an on-off manager that a transition | 
|  | * has completed. | 
|  | * | 
|  | * Functions of this type are passed to service-specific transition | 
|  | * functions to be used to report the completion of the operation. | 
|  | * The functions may be invoked from any context. | 
|  | * | 
|  | * @param mgr the manager for which transition was requested. | 
|  | * | 
|  | * @param res the result of the transition.  This shall be | 
|  | * non-negative on success, or a negative error code.  If an error is | 
|  | * indicated the service shall enter an error state. | 
|  | */ | 
|  | typedef void (*onoff_notify_fn)(struct onoff_manager *mgr, | 
|  | int res); | 
|  |  | 
|  | /** | 
|  | * @brief Signature used by service implementations to effect a | 
|  | * transition. | 
|  | * | 
|  | * Service definitions use two required function pointers of this type | 
|  | * to be notified that a transition is required, and a third optional | 
|  | * one to reset the service when it is in an error state. | 
|  | * | 
|  | * The start function will be called only from the off state. | 
|  | * | 
|  | * The stop function will be called only from the on state. | 
|  | * | 
|  | * The reset function (where supported) will be called only when | 
|  | * onoff_has_error() returns true. | 
|  | * | 
|  | * @note All transitions functions must be isr-ok. | 
|  | * | 
|  | * @param mgr the manager for which transition was requested. | 
|  | * | 
|  | * @param notify the function to be invoked when the transition has | 
|  | * completed.  If the transition is synchronous, notify shall be | 
|  | * invoked by the implementation before the transition function | 
|  | * returns.  Otherwise the implementation shall capture this parameter | 
|  | * and invoke it when the transition completes. | 
|  | */ | 
|  | typedef void (*onoff_transition_fn)(struct onoff_manager *mgr, | 
|  | onoff_notify_fn notify); | 
|  |  | 
|  | /** @brief On-off service transition functions. */ | 
|  | struct onoff_transitions { | 
|  | /* Function to invoke to transition the service to on. */ | 
|  | onoff_transition_fn start; | 
|  |  | 
|  | /* Function to invoke to transition the service to off. */ | 
|  | onoff_transition_fn stop; | 
|  |  | 
|  | /* Function to force the service state to reset, where | 
|  | * supported. | 
|  | */ | 
|  | onoff_transition_fn reset; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief State associated with an on-off manager. | 
|  | * | 
|  | * No fields in this structure are intended for use by service | 
|  | * providers or clients.  The state is to be initialized once, using | 
|  | * onoff_manager_init(), when the service provider is initialized.  In | 
|  | * case of error it may be reset through the onoff_reset() API. | 
|  | */ | 
|  | struct onoff_manager { | 
|  | /* List of clients waiting for request or reset completion | 
|  | * notifications. | 
|  | */ | 
|  | sys_slist_t clients; | 
|  |  | 
|  | /* List of monitors to be notified of state changes including | 
|  | * errors and transition completion. | 
|  | */ | 
|  | sys_slist_t monitors; | 
|  |  | 
|  | /* Transition functions. */ | 
|  | const struct onoff_transitions *transitions; | 
|  |  | 
|  | /* Mutex protection for other fields. */ | 
|  | struct k_spinlock lock; | 
|  |  | 
|  | /* The result of the last transition. */ | 
|  | int last_res; | 
|  |  | 
|  | /* Flags identifying the service state. */ | 
|  | uint16_t flags; | 
|  |  | 
|  | /* Number of active clients for the service. */ | 
|  | uint16_t refs; | 
|  | }; | 
|  |  | 
|  | /** @brief Initializer for a onoff_transitions object. | 
|  | * | 
|  | * @param _start a function used to transition from off to on state. | 
|  | * | 
|  | * @param _stop a function used to transition from on to off state. | 
|  | * | 
|  | * @param _reset a function used to clear errors and force the service | 
|  | * to an off state. Can be null. | 
|  | */ | 
|  | #define ONOFF_TRANSITIONS_INITIALIZER(_start, _stop, _reset) { \ | 
|  | .start = _start,			       \ | 
|  | .stop = _stop,				       \ | 
|  | .reset = _reset,			       \ | 
|  | } | 
|  |  | 
|  | /** @internal */ | 
|  | #define ONOFF_MANAGER_INITIALIZER(_transitions) { \ | 
|  | .transitions = _transitions,	  \ | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Initialize an on-off service to off state. | 
|  | * | 
|  | * This function must be invoked exactly once per service instance, by | 
|  | * the infrastructure that provides the service, and before any other | 
|  | * on-off service API is invoked on the service. | 
|  | * | 
|  | * This function should never be invoked by clients of an on-off | 
|  | * service. | 
|  | * | 
|  | * @param mgr the manager definition object to be initialized. | 
|  | * | 
|  | * @param transitions pointer to a structure providing transition | 
|  | * functions.  The referenced object must persist as long as the | 
|  | * manager can be referenced. | 
|  | * | 
|  | * @retval 0 on success | 
|  | * @retval -EINVAL if start, stop, or flags are invalid | 
|  | */ | 
|  | int onoff_manager_init(struct onoff_manager *mgr, | 
|  | const struct onoff_transitions *transitions); | 
|  |  | 
|  | /* Forward declaration */ | 
|  | struct onoff_client; | 
|  |  | 
|  | /** | 
|  | * @brief Signature used to notify an on-off service client of the | 
|  | * completion of an operation. | 
|  | * | 
|  | * These functions may be invoked from any context including | 
|  | * pre-kernel, ISR, or cooperative or pre-emptible threads. | 
|  | * Compatible functions must be isr-ok and not sleep. | 
|  | * | 
|  | * @param mgr the manager for which the operation was initiated.  This may be | 
|  | * null if the on-off service uses synchronous transitions. | 
|  | * | 
|  | * @param cli the client structure passed to the function that | 
|  | * initiated the operation. | 
|  | * | 
|  | * @param state the state of the machine at the time of completion, | 
|  | * restricted by ONOFF_STATE_MASK.  ONOFF_FLAG_ERROR must be checked | 
|  | * independently of whether res is negative as a machine error may | 
|  | * indicate that all future operations except onoff_reset() will fail. | 
|  | * | 
|  | * @param res the result of the operation.  Expected values are | 
|  | * service-specific, but the value shall be non-negative if the | 
|  | * operation succeeded, and negative if the operation failed.  If res | 
|  | * is negative ONOFF_FLAG_ERROR will be set in state, but if res is | 
|  | * non-negative ONOFF_FLAG_ERROR may still be set in state. | 
|  | */ | 
|  | typedef void (*onoff_client_callback)(struct onoff_manager *mgr, | 
|  | struct onoff_client *cli, | 
|  | uint32_t state, | 
|  | int res); | 
|  |  | 
|  | /** | 
|  | * @brief State associated with a client of an on-off service. | 
|  | * | 
|  | * Objects of this type are allocated by a client, which is | 
|  | * responsible for zero-initializing the node field and invoking the | 
|  | * approprite sys_notify init function to configure notification. | 
|  | * | 
|  | * Control of the object content transfers to the service provider | 
|  | * when a pointer to the object is passed to any on-off manager | 
|  | * function.  While the service provider controls the object the | 
|  | * client must not change any object fields.  Control reverts to the | 
|  | * client concurrent with release of the owned sys_notify structure, | 
|  | * or when indicated by an onoff_cancel() return value. | 
|  | * | 
|  | * After control has reverted to the client the notify field must be | 
|  | * reinitialized for the next operation. | 
|  | */ | 
|  | struct onoff_client { | 
|  | /** @internal | 
|  | * | 
|  | * Links the client into the set of waiting service users. | 
|  | * Applications must ensure this field is zero-initialized | 
|  | * before use. | 
|  | */ | 
|  | sys_snode_t node; | 
|  |  | 
|  | /** @brief Notification configuration. */ | 
|  | struct sys_notify notify; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Identify region of sys_notify flags available for | 
|  | * containing services. | 
|  | * | 
|  | * Bits of the flags field of the sys_notify structure contained | 
|  | * within the queued_operation structure at and above this position | 
|  | * may be used by extensions to the onoff_client structure. | 
|  | * | 
|  | * These bits are intended for use by containing service | 
|  | * implementations to record client-specific information and are | 
|  | * subject to other conditions of use specified on the sys_notify API. | 
|  | */ | 
|  | #define ONOFF_CLIENT_EXTENSION_POS SYS_NOTIFY_EXTENSION_POS | 
|  |  | 
|  | /** | 
|  | * @brief Test whether an on-off service has recorded an error. | 
|  | * | 
|  | * This function can be used to determine whether the service has | 
|  | * recorded an error.  Errors may be cleared by invoking | 
|  | * onoff_reset(). | 
|  | * | 
|  | * This is an unlocked convenience function suitable for use only when | 
|  | * it is known that no other process might invoke an operation that | 
|  | * transitions the service between an error and non-error state. | 
|  | * | 
|  | * @return true if and only if the service has an uncleared error. | 
|  | */ | 
|  | static inline bool onoff_has_error(const struct onoff_manager *mgr) | 
|  | { | 
|  | return (mgr->flags & ONOFF_FLAG_ERROR) != 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Request a reservation to use an on-off service. | 
|  | * | 
|  | * The return value indicates the success or failure of an attempt to | 
|  | * initiate an operation to request the resource be made available. | 
|  | * If initiation of the operation succeeds the result of the request | 
|  | * operation is provided through the configured client notification | 
|  | * method, possibly before this call returns. | 
|  | * | 
|  | * Note that the call to this function may succeed in a case where the | 
|  | * actual request fails.  Always check the operation completion | 
|  | * result. | 
|  | * | 
|  | * @param mgr the manager that will be used. | 
|  | * | 
|  | * @param cli a non-null pointer to client state providing | 
|  | * instructions on synchronous expectations and how to notify the | 
|  | * client when the request completes.  Behavior is undefined if client | 
|  | * passes a pointer object associated with an incomplete service | 
|  | * operation. | 
|  | * | 
|  | * @retval non-negative the observed state of the machine at the time | 
|  | * the request was processed, if successful. | 
|  | * @retval -EIO if service has recorded an an error. | 
|  | * @retval -EINVAL if the parameters are invalid. | 
|  | * @retval -EAGAIN if the reference count would overflow. | 
|  | */ | 
|  | int onoff_request(struct onoff_manager *mgr, | 
|  | struct onoff_client *cli); | 
|  |  | 
|  | /** | 
|  | * @brief Release a reserved use of an on-off service. | 
|  | * | 
|  | * This synchronously releases the caller's previous request.  If the | 
|  | * last request is released the manager will initiate a transition to | 
|  | * off, which can be observed by registering an onoff_monitor. | 
|  | * | 
|  | * @note Behavior is undefined if this is not paired with a preceding | 
|  | * onoff_request() call that completed successfully. | 
|  | * | 
|  | * @param mgr the manager for which a request was successful. | 
|  | * | 
|  | * @retval non-negative the observed state (ONOFF_STATE_ON) of the | 
|  | * machine at the time of the release, if the release succeeds. | 
|  | * @retval -EIO if service has recorded an an error. | 
|  | * @retval -ENOTSUP if the machine is not in a state that permits | 
|  | * release. | 
|  | */ | 
|  | int onoff_release(struct onoff_manager *mgr); | 
|  |  | 
|  | /** | 
|  | * @brief Attempt to cancel an in-progress client operation. | 
|  | * | 
|  | * It may be that a client has initiated an operation but needs to | 
|  | * shut down before the operation has completed.  For example, when a | 
|  | * request was made and the need is no longer present. | 
|  | * | 
|  | * Cancelling is supported only for onoff_request() and onoff_reset() | 
|  | * operations, and is a synchronous operation.  Be aware that any | 
|  | * transition that was initiated on behalf of the client will continue | 
|  | * to progress to completion: it is only notification of transition | 
|  | * completion that may be eliminated.  If there are no active requests | 
|  | * when a transition to on completes the manager will initiate a | 
|  | * transition to off. | 
|  | * | 
|  | * Client notification does not occur for cancelled operations. | 
|  | * | 
|  | * @param mgr the manager for which an operation is to be cancelled. | 
|  | * | 
|  | * @param cli a pointer to the same client state that was provided | 
|  | * when the operation to be cancelled was issued. | 
|  | * | 
|  | * @retval non-negative the observed state of the machine at the time | 
|  | * of the cancellation, if the cancellation succeeds.  On successful | 
|  | * cancellation ownership of @c *cli reverts to the client. | 
|  | * @retval -EINVAL if the parameters are invalid. | 
|  | * @retval -EALREADY if cli was not a record of an uncompleted | 
|  | * notification at the time the cancellation was processed.  This | 
|  | * likely indicates that the operation and client notification had | 
|  | * already completed. | 
|  | */ | 
|  | int onoff_cancel(struct onoff_manager *mgr, | 
|  | struct onoff_client *cli); | 
|  |  | 
|  | /** | 
|  | * @brief Helper function to safely cancel a request. | 
|  | * | 
|  | * Some applications may want to issue requests on an asynchronous | 
|  | * event (such as connection to a USB bus) and to release on a paired | 
|  | * event (such as loss of connection to a USB bus).  Applications | 
|  | * cannot precisely determine that an in-progress request is still | 
|  | * pending without using onoff_monitor and carefully avoiding race | 
|  | * conditions. | 
|  | * | 
|  | * This function is a helper that attempts to cancel the operation and | 
|  | * issues a release if cancellation fails because the request was | 
|  | * completed.  This synchronously ensures that ownership of the client | 
|  | * data reverts to the client so is available for a future request. | 
|  | * | 
|  | * @param mgr the manager for which an operation is to be cancelled. | 
|  | * | 
|  | * @param cli a pointer to the same client state that was provided | 
|  | * when onoff_request() was invoked.  Behavior is undefined if this is | 
|  | * a pointer to client data associated with an onoff_reset() request. | 
|  | * | 
|  | * @retval ONOFF_STATE_TO_ON if the cancellation occurred before the | 
|  | * transition completed. | 
|  | * | 
|  | * @retval ONOFF_STATE_ON if the cancellation occurred after the | 
|  | * transition completed. | 
|  | * | 
|  | * @retval -EINVAL if the parameters are invalid. | 
|  | * | 
|  | * @retval negative other errors produced by onoff_release(). | 
|  | */ | 
|  | static inline int onoff_cancel_or_release(struct onoff_manager *mgr, | 
|  | struct onoff_client *cli) | 
|  | { | 
|  | int rv = onoff_cancel(mgr, cli); | 
|  |  | 
|  | if (rv == -EALREADY) { | 
|  | rv = onoff_release(mgr); | 
|  | } | 
|  | return rv; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Clear errors on an on-off service and reset it to its off | 
|  | * state. | 
|  | * | 
|  | * A service can only be reset when it is in an error state as | 
|  | * indicated by onoff_has_error(). | 
|  | * | 
|  | * The return value indicates the success or failure of an attempt to | 
|  | * initiate an operation to reset the resource.  If initiation of the | 
|  | * operation succeeds the result of the reset operation itself is | 
|  | * provided through the configured client notification method, | 
|  | * possibly before this call returns.  Multiple clients may request a | 
|  | * reset; all are notified when it is complete. | 
|  | * | 
|  | * Note that the call to this function may succeed in a case where the | 
|  | * actual reset fails.  Always check the operation completion result. | 
|  | * | 
|  | * @note Due to the conditions on state transition all incomplete | 
|  | * asynchronous operations will have been informed of the error when | 
|  | * it occurred.  There need be no concern about dangling requests left | 
|  | * after a reset completes. | 
|  | * | 
|  | * @param mgr the manager to be reset. | 
|  | * | 
|  | * @param cli pointer to client state, including instructions on how | 
|  | * to notify the client when reset completes.  Behavior is undefined | 
|  | * if cli references an object associated with an incomplete service | 
|  | * operation. | 
|  | * | 
|  | * @retval non-negative the observed state of the machine at the time | 
|  | * of the reset, if the reset succeeds. | 
|  | * @retval -ENOTSUP if reset is not supported by the service. | 
|  | * @retval -EINVAL if the parameters are invalid. | 
|  | * @retval -EALREADY if the service does not have a recorded error. | 
|  | */ | 
|  | int onoff_reset(struct onoff_manager *mgr, | 
|  | struct onoff_client *cli); | 
|  |  | 
|  | /** | 
|  | * @brief Signature used to notify a monitor of an onoff service of | 
|  | * errors or completion of a state transition. | 
|  | * | 
|  | * This is similar to onoff_client_callback but provides information | 
|  | * about all transitions, not just ones associated with a specific | 
|  | * client.  Monitor callbacks are invoked before any completion | 
|  | * notifications associated with the state change are made. | 
|  | * | 
|  | * These functions may be invoked from any context including | 
|  | * pre-kernel, ISR, or cooperative or pre-emptible threads. | 
|  | * Compatible functions must be isr-ok and not sleep. | 
|  | * | 
|  | * The callback is permitted to unregister itself from the manager, | 
|  | * but must not register or unregister any other monitors. | 
|  | * | 
|  | * @param mgr the manager for which a transition has completed. | 
|  | * | 
|  | * @param mon the monitor instance through which this notification | 
|  | * arrived. | 
|  | * | 
|  | * @param state the state of the machine at the time of completion, | 
|  | * restricted by ONOFF_STATE_MASK.  All valid states may be observed. | 
|  | * | 
|  | * @param res the result of the operation.  Expected values are | 
|  | * service- and state-specific, but the value shall be non-negative if | 
|  | * the operation succeeded, and negative if the operation failed. | 
|  | */ | 
|  | typedef void (*onoff_monitor_callback)(struct onoff_manager *mgr, | 
|  | struct onoff_monitor *mon, | 
|  | uint32_t state, | 
|  | int res); | 
|  |  | 
|  | /** | 
|  | * @brief Registration state for notifications of onoff service | 
|  | * transitions. | 
|  | * | 
|  | * Any given onoff_monitor structure can be associated with at most | 
|  | * one onoff_manager instance. | 
|  | */ | 
|  | struct onoff_monitor { | 
|  | /* Links the client into the set of waiting service users. | 
|  | * | 
|  | * This must be zero-initialized. | 
|  | */ | 
|  | sys_snode_t node; | 
|  |  | 
|  | /** @brief Callback to be invoked on state change. | 
|  | * | 
|  | * This must not be null. | 
|  | */ | 
|  | onoff_monitor_callback callback; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Add a monitor of state changes for a manager. | 
|  | * | 
|  | * @param mgr the manager for which a state changes are to be monitored. | 
|  | * | 
|  | * @param mon a linkable node providing a non-null callback to be | 
|  | * invoked on state changes. | 
|  | * | 
|  | * @return non-negative on successful addition, or a negative error | 
|  | * code. | 
|  | */ | 
|  | int onoff_monitor_register(struct onoff_manager *mgr, | 
|  | struct onoff_monitor *mon); | 
|  |  | 
|  | /** | 
|  | * @brief Remove a monitor of state changes from a manager. | 
|  | * | 
|  | * @param mgr the manager for which a state changes are to be monitored. | 
|  | * | 
|  | * @param mon a linkable node providing the callback to be invoked on | 
|  | * state changes. | 
|  | * | 
|  | * @return non-negative on successful removal, or a negative error | 
|  | * code. | 
|  | */ | 
|  | int onoff_monitor_unregister(struct onoff_manager *mgr, | 
|  | struct onoff_monitor *mon); | 
|  |  | 
|  | /** | 
|  | * @brief State used when a driver uses the on-off service API for synchronous | 
|  | * operations. | 
|  | * | 
|  | * This is useful when a subsystem API uses the on-off API to support | 
|  | * asynchronous operations but the transitions required by a | 
|  | * particular driver are isr-ok and not sleep.  It serves as a | 
|  | * substitute for #onoff_manager, with locking and persisted state | 
|  | * updates supported by onoff_sync_lock() and onoff_sync_finalize(). | 
|  | */ | 
|  | struct onoff_sync_service { | 
|  | /* Mutex protection for other fields. */ | 
|  | struct k_spinlock lock; | 
|  |  | 
|  | /* Negative is error, non-negative is reference count. */ | 
|  | int32_t count; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Lock a synchronous onoff service and provide its state. | 
|  | * | 
|  | * @note If an error state is returned it is the caller's responsibility to | 
|  | * decide whether to preserve it (finalize with the same error state) or clear | 
|  | * the error (finalize with a non-error result). | 
|  | * | 
|  | * @param srv pointer to the synchronous service state. | 
|  | * | 
|  | * @param keyp pointer to where the lock key should be stored | 
|  | * | 
|  | * @return negative if the service is in an error state, otherwise the | 
|  | * number of active requests at the time the lock was taken.  The lock | 
|  | * is held on return regardless of whether a negative state is | 
|  | * returned. | 
|  | */ | 
|  | int onoff_sync_lock(struct onoff_sync_service *srv, | 
|  | k_spinlock_key_t *keyp); | 
|  |  | 
|  | /** | 
|  | * @brief Process the completion of a transition in a synchronous | 
|  | * service and release lock. | 
|  | * | 
|  | * This function updates the service state on the @p res and @p on parameters | 
|  | * then releases the lock.  If @p cli is not null it finalizes the client | 
|  | * notification using @p res. | 
|  | * | 
|  | * If the service was in an error state when locked, and @p res is non-negative | 
|  | * when finalized, the count is reset to zero before completing finalization. | 
|  | * | 
|  | * @param srv pointer to the synchronous service state | 
|  | * | 
|  | * @param key the key returned by the preceding invocation of onoff_sync_lock(). | 
|  | * | 
|  | * @param cli pointer to the onoff client through which completion | 
|  | * information is returned.  If a null pointer is passed only the | 
|  | * state of the service is updated.  For compatibility with the | 
|  | * behavior of callbacks used with the manager API @p cli must be null | 
|  | * when @p on is false (the manager does not support callbacks when | 
|  | * turning off devices). | 
|  | * | 
|  | * @param res the result of the transition.  A negative value places the service | 
|  | * into an error state.  A non-negative value increments or decrements the | 
|  | * reference count as specified by @p on. | 
|  | * | 
|  | * @param on Only when @p res is non-negative, the service reference count will | 
|  | * be incremented if@p on is @c true, and decremented if @p on is @c false. | 
|  | * | 
|  | * @return negative if the service is left or put into an error state, otherwise | 
|  | * the number of active requests at the time the lock was released. | 
|  | */ | 
|  | int onoff_sync_finalize(struct onoff_sync_service *srv, | 
|  | k_spinlock_key_t key, | 
|  | struct onoff_client *cli, | 
|  | int res, | 
|  | bool on); | 
|  |  | 
|  | /** @} */ | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #endif /* ZEPHYR_INCLUDE_SYS_ONOFF_H_ */ |