sys: onoff: Move transition functions out of service struct
Extracted transition functions from onoff structure to external one which allows to keep them in flash. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
7e1b1213d7
commit
e2ca46c329
3 changed files with 120 additions and 90 deletions
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
*/
|
||||
enum onoff_service_flags {
|
||||
/**
|
||||
* @brief Flag passed to onoff_service_init().
|
||||
* @brief Flag used in struct onoff_service_transitions.
|
||||
*
|
||||
* When provided this indicates the start transition function
|
||||
* may cause the calling thread to wait. This blocks attempts
|
||||
|
@ -34,7 +34,7 @@ enum onoff_service_flags {
|
|||
ONOFF_SERVICE_START_SLEEPS = BIT(0),
|
||||
|
||||
/**
|
||||
* @brief Flag passed to onoff_service_init().
|
||||
* @brief Flag used in struct onoff_service_transitions.
|
||||
*
|
||||
* As with @ref ONOFF_SERVICE_START_SLEEPS but describing the
|
||||
* stop transition function.
|
||||
|
@ -42,7 +42,7 @@ enum onoff_service_flags {
|
|||
ONOFF_SERVICE_STOP_SLEEPS = BIT(1),
|
||||
|
||||
/**
|
||||
* @brief Flag passed to onoff_service_init().
|
||||
* @brief Flag used in struct onoff_service_transitions.
|
||||
*
|
||||
* As with @ref ONOFF_SERVICE_START_SLEEPS but describing the
|
||||
* reset transition function.
|
||||
|
@ -102,6 +102,21 @@ typedef void (*onoff_service_notify_fn)(struct onoff_service *srv,
|
|||
typedef void (*onoff_service_transition_fn)(struct onoff_service *srv,
|
||||
onoff_service_notify_fn notify);
|
||||
|
||||
/** @brief On-off service transition functions. */
|
||||
struct onoff_service_transitions {
|
||||
/* Function to invoke to transition the service to on. */
|
||||
onoff_service_transition_fn start;
|
||||
|
||||
/* Function to invoke to transition the service to off. */
|
||||
onoff_service_transition_fn stop;
|
||||
|
||||
/* Function to force the service state to reset, where supported. */
|
||||
onoff_service_transition_fn reset;
|
||||
|
||||
/* Flags identifying transition function capabilities. */
|
||||
u8_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief State associated with an on-off service.
|
||||
*
|
||||
|
@ -117,16 +132,8 @@ struct onoff_service {
|
|||
*/
|
||||
sys_slist_t clients;
|
||||
|
||||
/* Function to invoke to transition the service to on. */
|
||||
onoff_service_transition_fn start;
|
||||
|
||||
/* Function to invoke to transition the service to off. */
|
||||
onoff_service_transition_fn stop;
|
||||
|
||||
/* Function to force the service state to reset, where
|
||||
* supported.
|
||||
*/
|
||||
onoff_service_transition_fn reset;
|
||||
/* Transition functions. */
|
||||
const struct onoff_service_transitions *transitions;
|
||||
|
||||
/* Mutex protection for flags, clients, releaser, and refs. */
|
||||
struct k_spinlock lock;
|
||||
|
@ -141,12 +148,28 @@ struct onoff_service {
|
|||
u16_t refs;
|
||||
};
|
||||
|
||||
/** @brief Initializer of transitions structure.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param _flags any or all of the flags from enum onoff_service_flags.
|
||||
*/
|
||||
#define ONOFF_SERVICE_TRANSITIONS_INITIALIZER(_start, _stop, _reset, _flags) { \
|
||||
.start = _start, \
|
||||
.stop = _stop, \
|
||||
.reset = _reset, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
#define ONOFF_SERVICE_INITIALIZER(_start, _stop, _reset, _flags) { \
|
||||
.start = _start, \
|
||||
.stop = _stop, \
|
||||
.reset = _reset, \
|
||||
.flags = _flags, \
|
||||
#define ONOFF_SERVICE_INITIALIZER(_transitions) { \
|
||||
.transitions = _transitions, \
|
||||
.flags = (_transitions)->flags, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,32 +183,14 @@ struct onoff_service {
|
|||
*
|
||||
* @param srv the service definition object to be initialized.
|
||||
*
|
||||
* @param start the function used to (initiate a) transition from off
|
||||
* to on. This must not be null. Include @ref ONOFF_SERVICE_START_SLEEPS as
|
||||
* appropriate in flags.
|
||||
*
|
||||
* @param stop the function used to (initiate a) transition from on to
|
||||
* off. This must not be null. Include @ref ONOFF_SERVICE_STOP_SLEEPS
|
||||
* as appropriate in flags.
|
||||
*
|
||||
* @param reset the function used to clear errors and force the
|
||||
* service to an off state. Pass null if the service cannot or need
|
||||
* not be reset. (Services where a transition operation can complete
|
||||
* with an error notification should support the reset operation.)
|
||||
* Include @ref ONOFF_SERVICE_RESET_SLEEPS as appropriate in flags.
|
||||
*
|
||||
* @param flags any or all of the flags mentioned above,
|
||||
* e.g. @ref ONOFF_SERVICE_START_SLEEPS. Use of other flags produces an
|
||||
* error.
|
||||
* @param transitions A structure with transition functions. Structure must be
|
||||
* persistent as it is used by the service.
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL if start, stop, or flags are invalid
|
||||
*/
|
||||
int onoff_service_init(struct onoff_service *srv,
|
||||
onoff_service_transition_fn start,
|
||||
onoff_service_transition_fn stop,
|
||||
onoff_service_transition_fn reset,
|
||||
u32_t flags);
|
||||
const struct onoff_service_transitions *transitions);
|
||||
|
||||
/** @internal
|
||||
*
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define CLIENT_NOTIFY_METHOD_MASK 0x03
|
||||
#define CLIENT_VALID_FLAGS_MASK 0x07
|
||||
|
||||
|
||||
#define SERVICE_CONFIG_FLAGS \
|
||||
(ONOFF_SERVICE_START_SLEEPS \
|
||||
| ONOFF_SERVICE_STOP_SLEEPS \
|
||||
|
@ -76,21 +77,17 @@ static int validate_args(const struct onoff_service *srv,
|
|||
}
|
||||
|
||||
int onoff_service_init(struct onoff_service *srv,
|
||||
onoff_service_transition_fn start,
|
||||
onoff_service_transition_fn stop,
|
||||
onoff_service_transition_fn reset,
|
||||
u32_t flags)
|
||||
const struct onoff_service_transitions *transitions)
|
||||
{
|
||||
if ((flags & SERVICE_CONFIG_FLAGS) != flags) {
|
||||
if (transitions->flags & ~SERVICE_CONFIG_FLAGS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((start == NULL) || (stop == NULL)) {
|
||||
if ((transitions->start == NULL) || (transitions->stop == NULL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*srv = (struct onoff_service)ONOFF_SERVICE_INITIALIZER(start, stop,
|
||||
reset, flags);
|
||||
*srv = (struct onoff_service)ONOFF_SERVICE_INITIALIZER(transitions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -261,8 +258,8 @@ out:
|
|||
k_spin_unlock(&srv->lock, key);
|
||||
|
||||
if (start) {
|
||||
__ASSERT_NO_MSG(srv->start != NULL);
|
||||
srv->start(srv, onoff_start_notify);
|
||||
__ASSERT_NO_MSG(srv->transitions->start != NULL);
|
||||
srv->transitions->start(srv, onoff_start_notify);
|
||||
} else if (notify) {
|
||||
notify_one(srv, cli, 0);
|
||||
}
|
||||
|
@ -328,7 +325,7 @@ static void onoff_stop_notify(struct onoff_service *srv,
|
|||
if (notify_clients) {
|
||||
notify_all(srv, &clients, client_res);
|
||||
} else if (start) {
|
||||
srv->start(srv, onoff_start_notify);
|
||||
srv->transitions->start(srv, onoff_start_notify);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,8 +393,8 @@ out:
|
|||
k_spin_unlock(&srv->lock, key);
|
||||
|
||||
if (stop) {
|
||||
__ASSERT_NO_MSG(srv->stop != NULL);
|
||||
srv->stop(srv, onoff_stop_notify);
|
||||
__ASSERT_NO_MSG(srv->transitions->stop != NULL);
|
||||
srv->transitions->stop(srv, onoff_stop_notify);
|
||||
} else if (notify) {
|
||||
notify_one(srv, cli, 0);
|
||||
}
|
||||
|
@ -435,7 +432,7 @@ static void onoff_reset_notify(struct onoff_service *srv,
|
|||
int onoff_service_reset(struct onoff_service *srv,
|
||||
struct onoff_client *cli)
|
||||
{
|
||||
if (srv->reset == NULL) {
|
||||
if (srv->transitions->reset == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -472,7 +469,7 @@ out:
|
|||
k_spin_unlock(&srv->lock, key);
|
||||
|
||||
if (reset) {
|
||||
srv->reset(srv, onoff_reset_notify);
|
||||
srv->transitions->reset(srv, onoff_reset_notify);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -167,44 +167,53 @@ static void test_service_init_validation(void)
|
|||
{
|
||||
int rc;
|
||||
struct onoff_service srv;
|
||||
const struct onoff_service_transitions null_transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(NULL, NULL, NULL, 0);
|
||||
const struct onoff_service_transitions start_transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, NULL, NULL, 0);
|
||||
const struct onoff_service_transitions stop_transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(NULL, stop, NULL, 0);
|
||||
struct onoff_service_transitions start_stop_transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||
const struct onoff_service_transitions all_transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset,
|
||||
ONOFF_SERVICE_START_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
|
||||
rc = onoff_service_init(NULL, NULL, NULL, NULL, 0);
|
||||
rc = onoff_service_init(NULL, &null_transitions);
|
||||
zassert_equal(rc, -EINVAL,
|
||||
"init null srv %d", rc);
|
||||
|
||||
rc = onoff_service_init(&srv, NULL, NULL, NULL, 0);
|
||||
rc = onoff_service_init(&srv, &null_transitions);
|
||||
zassert_equal(rc, -EINVAL,
|
||||
"init null transit %d", rc);
|
||||
|
||||
rc = onoff_service_init(&srv, start, NULL, NULL, 0);
|
||||
rc = onoff_service_init(&srv, &start_transitions);
|
||||
zassert_equal(rc, -EINVAL,
|
||||
"init null stop %d", rc);
|
||||
|
||||
rc = onoff_service_init(&srv, NULL, stop, NULL, 0);
|
||||
rc = onoff_service_init(&srv, &stop_transitions);
|
||||
zassert_equal(rc, -EINVAL,
|
||||
"init null start %d", rc);
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_INTERNAL_BASE);
|
||||
start_stop_transitions.flags |= ONOFF_SERVICE_INTERNAL_BASE;
|
||||
rc = onoff_service_init(&srv, &start_stop_transitions);
|
||||
zassert_equal(rc, -EINVAL,
|
||||
"init bad flags %d", rc);
|
||||
|
||||
u32_t flags = ONOFF_SERVICE_START_SLEEPS;
|
||||
|
||||
memset(&srv, 0xA5, sizeof(srv));
|
||||
zassert_false(sys_slist_is_empty(&srv.clients),
|
||||
"slist empty");
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset, flags);
|
||||
rc = onoff_service_init(&srv, &all_transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"init good %d", rc);
|
||||
zassert_equal(srv.start, start,
|
||||
zassert_equal(srv.transitions->start, start,
|
||||
"init start mismatch");
|
||||
zassert_equal(srv.stop, stop,
|
||||
zassert_equal(srv.transitions->stop, stop,
|
||||
"init stop mismatch");
|
||||
zassert_equal(srv.reset, reset,
|
||||
zassert_equal(srv.transitions->reset, reset,
|
||||
"init reset mismatch");
|
||||
zassert_equal(srv.flags, ONOFF_SERVICE_START_SLEEPS,
|
||||
"init flags mismatch");
|
||||
|
@ -256,6 +265,8 @@ static void test_validate_args(void)
|
|||
struct onoff_service srv;
|
||||
struct k_poll_signal sig;
|
||||
struct onoff_client cli;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||
|
||||
clear_transit();
|
||||
|
||||
|
@ -263,7 +274,7 @@ static void test_validate_args(void)
|
|||
* release, and reset; test it through the request API.
|
||||
*/
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL, 0);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -334,17 +345,21 @@ static void test_reset(void)
|
|||
struct onoff_client cli;
|
||||
unsigned int signalled = 0;
|
||||
int result = 0;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||
struct onoff_service_transitions transitions_with_reset =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||
|
||||
clear_transit();
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL, 0);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
rc = onoff_service_reset(&srv, &cli);
|
||||
zassert_equal(rc, -ENOTSUP,
|
||||
"reset: %d", rc);
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset, 0);
|
||||
rc = onoff_service_init(&srv, &transitions_with_reset);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -423,8 +438,8 @@ static void test_reset(void)
|
|||
zassert_false(onoff_service_has_error(&srv),
|
||||
"has error");
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset,
|
||||
ONOFF_SERVICE_RESET_SLEEPS);
|
||||
transitions_with_reset.flags |= ONOFF_SERVICE_RESET_SLEEPS;
|
||||
rc = onoff_service_init(&srv, &transitions_with_reset);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
start_state.retval = -23;
|
||||
|
@ -460,10 +475,12 @@ static void test_request(void)
|
|||
{
|
||||
int rc;
|
||||
struct onoff_service srv;
|
||||
struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||
|
||||
clear_transit();
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset, 0);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -546,8 +563,8 @@ static void test_request(void)
|
|||
"has error");
|
||||
|
||||
/* Diagnose a no-wait delayed start */
|
||||
rc = onoff_service_init(&srv, start, stop, reset,
|
||||
ONOFF_SERVICE_START_SLEEPS);
|
||||
transitions.flags |= ONOFF_SERVICE_START_SLEEPS;
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
start_state.async = true;
|
||||
|
@ -578,10 +595,12 @@ static void test_sync(void)
|
|||
{
|
||||
int rc;
|
||||
struct onoff_service srv;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||
|
||||
clear_transit();
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset, 0);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -628,6 +647,9 @@ static void test_async(void)
|
|||
struct onoff_client cli[2];
|
||||
unsigned int signalled = 0;
|
||||
int result = 0;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset,
|
||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.async = true;
|
||||
|
@ -635,9 +657,7 @@ static void test_async(void)
|
|||
stop_state.async = true;
|
||||
stop_state.retval = 17;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, reset,
|
||||
ONOFF_SERVICE_START_SLEEPS
|
||||
| ONOFF_SERVICE_STOP_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -820,14 +840,16 @@ static void test_half_sync(void)
|
|||
struct onoff_service srv;
|
||||
struct k_poll_signal sig;
|
||||
struct onoff_client cli;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||
ONOFF_SERVICE_STOP_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.retval = 23;
|
||||
stop_state.async = true;
|
||||
stop_state.retval = 17;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_STOP_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -876,6 +898,9 @@ static void test_cancel_request_waits(void)
|
|||
struct onoff_service srv;
|
||||
struct k_poll_signal sig;
|
||||
struct onoff_client cli;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.async = true;
|
||||
|
@ -883,9 +908,7 @@ static void test_cancel_request_waits(void)
|
|||
stop_state.async = true;
|
||||
stop_state.retval = 31;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS
|
||||
| ONOFF_SERVICE_STOP_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -972,14 +995,16 @@ static void test_cancel_request_ok(void)
|
|||
struct onoff_service srv;
|
||||
struct k_poll_signal sig;
|
||||
struct onoff_client cli;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.async = true;
|
||||
start_state.retval = 14;
|
||||
stop_state.retval = 31;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -1027,6 +1052,9 @@ static void test_blocked_restart(void)
|
|||
int result;
|
||||
struct k_poll_signal sig[2];
|
||||
struct onoff_client cli[2];
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.async = true;
|
||||
|
@ -1034,9 +1062,7 @@ static void test_blocked_restart(void)
|
|||
stop_state.async = true;
|
||||
stop_state.retval = 31;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_START_SLEEPS
|
||||
| ONOFF_SERVICE_STOP_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
@ -1103,14 +1129,16 @@ static void test_cancel_release(void)
|
|||
{
|
||||
int rc;
|
||||
struct onoff_service srv;
|
||||
const struct onoff_service_transitions transitions =
|
||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||
ONOFF_SERVICE_STOP_SLEEPS);
|
||||
|
||||
clear_transit();
|
||||
start_state.retval = 16;
|
||||
stop_state.async = true;
|
||||
stop_state.retval = 94;
|
||||
|
||||
rc = onoff_service_init(&srv, start, stop, NULL,
|
||||
ONOFF_SERVICE_STOP_SLEEPS);
|
||||
rc = onoff_service_init(&srv, &transitions);
|
||||
zassert_equal(rc, 0,
|
||||
"service init");
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue