blob: d945ebd0accd597cf7e3606d0e367834950f1830 [file] [log] [blame]
/* Copyright 2019 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* USB State Machine Framework */
#ifndef __CROS_EC_USB_SM_H
#define __CROS_EC_USB_SM_H
#include "compiler.h" /* for typeof() on Zephyr */
/* Function pointer that implements a portion of a usb state */
typedef void (*state_execution)(const int port);
/*
* General usb state that can be used in multiple state machines.
*
* entry - Optional method that will be run when this state is entered
* run - Optional method that will be run repeatedly during state machine loop
* exit - Optional method that will be run when this state exists
* parent- Optional parent usb_state that contains common entry/run/exit
* implementation among various child usb_states.
* entry: Parent function executes BEFORE child function.
* run: Parent function executes AFTER child function.
* exit: Parent function executes AFTER child function.
*
* Note: When transitioning between two child states with a shared parent,
* that parent's exit and entry functions do not execute.
*/
struct usb_state {
const state_execution entry;
const state_execution run;
const state_execution exit;
const struct usb_state *parent;
};
typedef const struct usb_state *usb_state_ptr;
/* Defines the current context of the usb statemachine. */
struct sm_ctx {
usb_state_ptr current;
usb_state_ptr previous;
/* We use intptr_t type to accommodate host tests ptr size variance */
intptr_t internal[2];
};
/* Local state machine states */
enum sm_local_state {
SM_INIT = 0, /* Ensure static variables initialize to SM_INIT */
SM_RUN,
SM_PAUSED,
};
/*
* A state machine can use these debug levels to regulate the amount of debug
* information printed on the EC console
*
* The states currently defined are
* Level 0: disabled
* Level 1: state names
*
* Note that higher log level causes timing changes and thus may affect
* performance.
*/
enum debug_level {
DEBUG_DISABLE,
DEBUG_LEVEL_1,
DEBUG_LEVEL_2,
DEBUG_LEVEL_3,
DEBUG_LEVEL_MAX = DEBUG_LEVEL_3
};
/**
* Changes a state machines state. This handles exiting the previous state and
* entering the target state. A common parent state will not exited nor be
* re-entered.
*
* @param port USB-C port number
* @param ctx State machine context
* @param new_state State to transition to (NULL is valid and exits all states)
*/
void set_state(int port, struct sm_ctx *ctx, usb_state_ptr new_state);
/**
* Runs one iteration of a state machine (including any parent states)
*
* @param port USB-C port number
* @param ctx State machine context
*/
void run_state(int port, struct sm_ctx *ctx);
#ifdef TEST_BUILD
/*
* Struct for test builds that allow unit tests to easily iterate through
* state machines
*/
struct test_sm_data {
/* Base pointer of the state machine array */
const usb_state_ptr base;
/* Size fo the state machine array above */
const int size;
/* The array of names for states, can be NULL */
const char *const *const names;
/* The size of the above names array */
const int names_size;
};
#endif
/* Creates a state machine state that will never link. Useful with IS_ENABLED */
#define GEN_NOT_SUPPORTED(state) extern typeof(state) state##_NOT_SUPPORTED
#endif /* __CROS_EC_USB_SM_H */