summaryrefslogtreecommitdiff
path: root/include/usb_sm.h
blob: e57cd0b873b78557f0d6da2e13ac189f045d51e7 (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
140
141
142
143
144
145
146
147
148
149
/* 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, run, exit) \
			DECLARE_SM_FUNC_##run(prefix, name); \
			DECLARE_SM_FUNC_##exit(prefix, name)

#define DECLARE_SM_FUNC_WITH_RUN(prefix, name)    static int \
				prefix##_##name##_run(int port)

#define DECLARE_SM_FUNC_WITH_EXIT(prefix, name)   static int \
				prefix##_##name##_exit(int port)

#define DECLARE_SM_FUNC_NOOP(prefix, name)

#define DECLARE_SM_SIG_RUN(prefix, name, run)  DECLARE_SM_##run(prefix, name)
#define DECLARE_SM_WITH_RUN(prefix, name)   prefix##_##name##_run

#define DECLARE_SM_SIG_EXIT(prefix, name, exit)  DECLARE_SM_##exit(prefix, name)
#define DECLARE_SM_WITH_EXIT(prefix, name)   prefix##_##name##_exit

#define DECLARE_SM_NOOP(prefix, name)  sm_do_nothing

/*
 * Helper macro for the declaration of states.
 *
 * @param prefix - prefix of state function name
 * @param name   - name of state
 * @param run    - if WITH_RUN, generates a run state function name
 *                 if NOOP, generates a do nothing function name
 * @param exit   - if WITH_EXIT, generates an exit state function name
 *                 if NOOP, generates a do nothing function name
 *
 * EXAMPLE:
 *
 * DECLARE_STATE(tc, test, WITH_RUN, WITH_EXIT); generates the following:
 *
 * static unsigned int tc_test(int port, enum sm_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,
 *	sm_get_super_state };
 *
 * DECLARE_STATE(tc, test, NOOP, NOOP); generates the following:
 *
 * static unsigned int tc_test(int port, enum sm_signal sig);
 * static unsigned int tc_test_entry(int port);
 * static const state_sig tc_test_sig[] = {
 *      tc_test_entry,
 *      sm_do_nothing,
 *      sm_do_nothing,
 *      sm_get_super_state };
 */
#define DECLARE_STATE(prefix, name, run, exit) \
static int prefix##_##name(int port, enum sm_signal sig); \
static int prefix##_##name##_entry(int port); \
DECLARE_SM_FUNC_(prefix, name, run, exit); \
static const state_sig prefix##_##name##_sig[] = { \
prefix##_##name##_entry, \
DECLARE_SM_SIG_RUN(prefix, name, run), \
DECLARE_SM_SIG_EXIT(prefix, name, exit), \
sm_get_super_state \
}

#define SM_OBJ(smo)    ((struct sm_obj *)&smo)
#define SM_SUPER(r, sig, s)  ((((r) == 0) || ((sig) == SM_ENTRY_SIG) || \
			((sig) == SM_EXIT_SIG)) ? 0 : ((uintptr_t)(s)))
#define SM_RUN_SUPER	1

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

/* State Machine signals */
enum sm_signal {
	SM_ENTRY_SIG = 0,
	SM_RUN_SIG,
	SM_EXIT_SIG,
	SM_SUPER_SIG,
};

typedef int (*state_sig)(int port);
typedef int (*sm_state)(int port, enum sm_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 sm_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 sm_set_state(int port, struct sm_obj *obj, sm_state target);

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

/**
 * Substitute this function for states that do not implement a
 * run or exit state.
 *
 * @param port USB-C port number
 * @return 0
 */
int sm_do_nothing(int port);

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

#endif /* __CROS_EC_USB_SM_H */