summaryrefslogtreecommitdiff
path: root/include/usb_sm.h
blob: 1fd6688a1f37cced4ff84e90296b4bed319e1e5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
 * 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

#define DECLARE_SM_FUNC_(prefix, name, exit) \
				DECLARE_SM_FUNC_##exit(prefix, name)
#define DECLARE_SM_FUNC_WITH_EXIT(prefix, name)   static unsigned int \
				prefix##_##name##_exit(int port)
#define DECLARE_SM_FUNC_NOOP_EXIT(prefix, name)

#define DECLARE_SM_SIG_(prefix, name, exit)  DECLARE_SM_##exit(prefix, name)
#define DECLARE_SM_WITH_EXIT(prefix, name)   prefix##_##name##_exit
#define DECLARE_SM_NOOP_EXIT(prefix, name)  do_nothing_exit


/*
 * Helper macro for the declaration of states.
 *
 * @param prefix - prefix of state function name
 * @param name   - name of state
 * @param exit   - if WITH_EXIT, generates an exit state function name
 *                 if NOOP_EXIT, generates do_nothing_exit function name
 *
 * EXAMPLE:
 *
 * DECLARE_STATE(tc, test, WITH_EXIT); generates the following:
 *
 * static unsigned int tc_test(int port, enum signal sig);
 * static unsigned int tc_test_entry(int port);
 * static unsigned int tc_test_run(int port);
 * static unsigned int tc_test_exit(int port);
 * static const state_sig tc_test_sig[] = {
 *	tc_test_entry,
 *	tc_test_run,
 *	tc_test_exit,
 *	get_super_state };
 *
 * DECLARE_STATE(tc, test, NOOP_EXIT); generates the following:
 *
 * static unsigned int tc_test(int port, enum signal sig);
 * static unsigned int tc_test_entry(int port);
 * static unsigned int tc_test_run(int port);
 * static const state_sig tc_test_sig[] = {
 *      tc_test_entry,
 *      tc_test_run,
 *      do_nothing_exit,
 *      get_super_state };
 */
#define DECLARE_STATE(prefix, name, exit) \
static unsigned int prefix##_##name(int port, enum signal sig); \
static unsigned int prefix##_##name##_entry(int port); \
static unsigned int prefix##_##name##_run(int port); \
DECLARE_SM_FUNC_(prefix, name, exit); \
static const state_sig prefix##_##name##_sig[] = { \
prefix##_##name##_entry, \
prefix##_##name##_run, \
DECLARE_SM_SIG_(prefix, name, exit), \
get_super_state \
}

#define SM_OBJ(smo)    ((struct sm_obj *)&smo)
#define SUPER(r, sig, s)  ((((r) == 0) || ((sig) == ENTRY_SIG) || \
			((sig) == EXIT_SIG)) ? 0 : ((uintptr_t)(s)))
#define RUN_SUPER	1

/* Local state machine states */
enum sm_local_state {
	SM_INIT,
	SM_RUN,
	SM_PAUSED
};

/* State Machine signals */
enum signal {
	ENTRY_SIG = 0,
	RUN_SIG,
	EXIT_SIG,
	SUPER_SIG,
};

typedef unsigned int (*state_sig)(int port);
typedef unsigned int (*sm_state)(int port, enum signal sig);

struct sm_obj {
	sm_state task_state;
	sm_state last_state;
};

/**
 * Initialize a State Machine
 *
 * @param port   USB-C port number
 * @param obj    State machine object
 * @param target Initial state of state machine
 */
void init_state(int port, struct sm_obj *obj, sm_state target);

/**
 * Changes a state machines state
 *
 * @param port   USB-C port number
 * @param obj    State machine object
 * @param target State to transition to
 * @return 0
 */
int set_state(int port, struct sm_obj *obj, sm_state target);

/**
 * Executes a state machine
 *
 * @param port USB-C port number
 * @param obj  State machine object
 * @param sig  State machine signal
 */
void exe_state(int port, struct sm_obj *obj, enum signal sig);

/**
 * Substitute this function for states that do not implement an exit state.
 *
 * @param port USB-C port number
 * @return 0
 */
unsigned int do_nothing_exit(int port);

/**
 * Called by the state machine framework to execute a states super state.
 *
 * @param port USB-C port number
 * @return RUN_SUPER
 */
unsigned int get_super_state(int port);

#endif /* __CROS_EC_USB_SM_H */