├── efsm
├── .DS_Store
├── lib
│ ├── fsm.a
│ └── .DS_Store
├── src
│ ├── fsm.o
│ ├── .DS_Store
│ ├── Makefile
│ └── fsm.c
├── test
│ ├── d_fsm
│ ├── .DS_Store
│ ├── d_fsm.dSYM
│ │ └── Contents
│ │ │ ├── Resources
│ │ │ └── DWARF
│ │ │ │ └── d_fsm
│ │ │ └── Info.plist
│ ├── demo_fsm.dSYM
│ │ └── Contents
│ │ │ ├── Resources
│ │ │ └── DWARF
│ │ │ │ └── demo_fsm
│ │ │ └── Info.plist
│ ├── Makefile
│ ├── demo_context.h
│ ├── demo_event_handlers.h
│ ├── demo.c
│ ├── demo_session_fsm.h
│ ├── demo_event_handlers.c
│ └── demo_session_fsm.c
├── include
│ ├── .DS_Store
│ └── fsm.h
└── doc
│ ├── fsm_readme.txt
│ └── demo_fsm_output.txt
├── safe_base
├── .DS_Store
├── src
│ ├── .DS_Store
│ ├── runtime_environment.o
│ ├── Makefile
│ └── runtime_environment.c
├── test
│ └── .DS_Store
├── lib
│ └── safe_base.a
└── include
│ ├── .DS_Store
│ ├── runtime_environment.h
│ ├── safe_types.h
│ └── safe_limits.h
└── README.md
/efsm/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/.DS_Store
--------------------------------------------------------------------------------
/efsm/lib/fsm.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/lib/fsm.a
--------------------------------------------------------------------------------
/efsm/src/fsm.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/src/fsm.o
--------------------------------------------------------------------------------
/efsm/test/d_fsm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/test/d_fsm
--------------------------------------------------------------------------------
/efsm/lib/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/lib/.DS_Store
--------------------------------------------------------------------------------
/efsm/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/src/.DS_Store
--------------------------------------------------------------------------------
/efsm/test/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/test/.DS_Store
--------------------------------------------------------------------------------
/safe_base/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/.DS_Store
--------------------------------------------------------------------------------
/efsm/include/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/include/.DS_Store
--------------------------------------------------------------------------------
/safe_base/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/src/.DS_Store
--------------------------------------------------------------------------------
/safe_base/test/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/test/.DS_Store
--------------------------------------------------------------------------------
/safe_base/lib/safe_base.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/lib/safe_base.a
--------------------------------------------------------------------------------
/safe_base/include/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/include/.DS_Store
--------------------------------------------------------------------------------
/safe_base/src/runtime_environment.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/safe_base/src/runtime_environment.o
--------------------------------------------------------------------------------
/efsm/test/d_fsm.dSYM/Contents/Resources/DWARF/d_fsm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/test/d_fsm.dSYM/Contents/Resources/DWARF/d_fsm
--------------------------------------------------------------------------------
/efsm/test/demo_fsm.dSYM/Contents/Resources/DWARF/demo_fsm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l4es/eFSM/HEAD/efsm/test/demo_fsm.dSYM/Contents/Resources/DWARF/demo_fsm
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # eFSM
2 | This is a copy of similar project located on SourceForge: https://sourceforge.net/projects/efsm/.
3 | For documentation, see: http://www.drdobbs.com/embedded-systems/the-embedded-finite-state-machine/217400611.
4 |
--------------------------------------------------------------------------------
/efsm/src/Makefile:
--------------------------------------------------------------------------------
1 |
2 | SRC = fsm.c
3 |
4 | OBJ = $(SRC:.c=.o)
5 |
6 | OUT = ../lib/fsm.a
7 |
8 | INCLUDES = -I. \
9 | -I../include/ \
10 | -I../../safe_base/include
11 |
12 | CCFLAGS = -g
13 | CCC = gcc
14 | LDFLAGS = -g
15 | .SUFFIXES: .c
16 |
17 | .c.o:
18 | $(CCC) $(INCLUDES) $(CCFLAGS) -c $< -o $@
19 |
20 | $(OUT): $(OBJ)
21 | ar rcs $(OUT) $(OBJ)
22 |
23 | clean:
24 | rm -f $(OBJ)
25 |
26 | # DO NOT DELETE
27 |
28 |
29 |
--------------------------------------------------------------------------------
/safe_base/src/Makefile:
--------------------------------------------------------------------------------
1 |
2 |
3 | SRC = runtime_environment.c
4 |
5 | OBJ = $(SRC:.c=.o)
6 |
7 | INCLUDE = -I. \
8 | -I../include/
9 |
10 | LIBS = -L../lib
11 |
12 | OUT = ../lib/safe_base.a
13 |
14 | CCFLAGS = -g
15 | CCC = gcc
16 | LDFLAGS = -g
17 | .SUFFIXES: .c
18 |
19 |
20 | .c.o:
21 | $(CCC) $(INCLUDE) $(CCFLAGS) -c $< -o $@
22 |
23 | $(OUT): $(OBJ)
24 | ar rcs $(OUT) $(OBJ)
25 |
26 | clean:
27 | rm -f $(OBJ) $(OUT)
28 |
29 | # DO NOT DELETE
30 |
31 |
--------------------------------------------------------------------------------
/efsm/test/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | #
3 | #
4 | INCLUDE = -I. -I../include -I../../safe_base/include
5 |
6 | SRC = demo.c \
7 | demo_session_fsm.c \
8 | demo_event_handlers.c
9 |
10 | OBJ = $(SRC:.c=.o)
11 |
12 | LIB = ../lib/fsm.a
13 |
14 | IMAGE = d_fsm
15 |
16 |
17 | CCC = gcc
18 | DEBUG = -g
19 | CFLAGS = -Wall -c $(DEBUG)
20 | LFLAGS = -Wall $(DEBUG)
21 |
22 |
23 | $(IMAGE):
24 | $(CCC) $(INCLUDE) $(LFLAGS) $(SRC) $(LIB) -o $(IMAGE)
25 |
26 | clean:
27 | rm -f $(OBJ) $(IMAGE)
28 |
29 | # DO NOT DELETE
30 |
31 |
32 |
--------------------------------------------------------------------------------
/efsm/test/d_fsm.dSYM/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleIdentifier
8 | com.apple.xcode.dsym.d_fsm
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundlePackageType
12 | dSYM
13 | CFBundleSignature
14 | ????
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleVersion
18 | 1
19 |
20 |
21 |
--------------------------------------------------------------------------------
/efsm/test/demo_fsm.dSYM/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleIdentifier
8 | com.apple.xcode.dsym.demo_fsm
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundlePackageType
12 | dSYM
13 | CFBundleSignature
14 | ????
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleVersion
18 | 1
19 | dSYM_UUID
20 |
21 | i386
22 | A9CED057-D8CD-2715-62E6-7E0DC80D1B2B
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/safe_base/include/runtime_environment.h:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * runtime_environment.h -- Abstractions
3 | *
4 | * Februrary 2002, Bo Berry
5 | *
6 | * Copyright (c) 2002-2011 by Cisco Systems, Inc.
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom the
15 | * Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __RUNTIME_ENVIRONMENT_H__
33 | #define __RUNTIME_ENVIRONMENT_H__
34 |
35 |
36 | #define LOCK_INTERRUPTS()
37 | #define UNLOCK_INTERRUPTS()
38 |
39 |
40 | extern void
41 | lock_interrupts(void *context);
42 |
43 | extern void
44 | lock_uninterrupts(void *context);
45 |
46 |
47 | #endif
48 |
49 |
--------------------------------------------------------------------------------
/efsm/test/demo_context.h:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo_context.h
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | *
8 | * Permission is hereby granted, free of charge, to any person
9 | * obtaining a copy of this software and associated documentation
10 | * files (the "Software"), to deal in the Software without restriction,
11 | * including without limitation the rights to use, copy, modify, merge,
12 | * publish, distribute, sublicense, and/or sell copies of the Software,
13 | * and to permit persons to whom the Software is furnished to do so,
14 | * subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be
17 | * included in all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 | *---------------------------------------------------------------------
27 | */
28 |
29 |
30 | #ifndef __DEMO_CONTEXT_H__
31 | #define __DEMO_CONTEXT_H__
32 |
33 | #define DEMO_TRACE printf
34 | #define DEMO_ERROR printf
35 | #define DEMO_EVENT printf
36 |
37 |
38 | /*
39 | * configuration data
40 | */
41 | typedef struct {
42 | uint32_t count;
43 | uint32_t tmo_threshold;
44 | } demo_config_t;
45 |
46 |
47 | /*
48 | * session context data
49 | */
50 | typedef struct {
51 | uint32_t count;
52 | uint32_t timeout_count;
53 | } demo_context_t;
54 |
55 |
56 | #endif
57 |
58 |
--------------------------------------------------------------------------------
/efsm/test/demo_event_handlers.h:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo_event_handlers.h
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *---------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __DEMO_EVENT_HANDLERS_H__
33 | #define __DEMO_EVENT_HANDLERS_H__
34 |
35 | #include "fsm.h"
36 |
37 |
38 | extern RC_FSM_t event_start_init(void *p2event, void *p2parm);
39 |
40 | extern RC_FSM_t event_init_rcvd(void *p2event, void *p2parm);
41 |
42 | extern RC_FSM_t event_init_ack_rcvd(void *p2event, void *p2parm);
43 |
44 | extern RC_FSM_t event_init_ack_tmo(void *p2event, void *p2parm);
45 |
46 | extern RC_FSM_t event_start_term (void *p2event, void *p2parm);
47 |
48 | extern RC_FSM_t event_term_rcvd(void *p2event, void *p2parm);
49 |
50 | extern RC_FSM_t event_term_ack_rcvd(void *p2event, void *p2parm);
51 |
52 |
53 | #endif
54 |
55 |
--------------------------------------------------------------------------------
/efsm/test/demo.c:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo.c
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *---------------------------------------------------------------------
30 | */
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include "fsm.h"
37 | #include "demo_context.h"
38 |
39 | #include "demo_session_fsm.h"
40 |
41 |
42 |
43 | static demo_config_t config;
44 |
45 | static demo_context_t context;
46 |
47 |
48 |
49 |
50 |
51 | int main (int argc, char **argv)
52 | {
53 |
54 | demo_fsm_create(&config, &context);
55 |
56 | context.timeout_count = 0;
57 | config.tmo_threshold = 3;
58 |
59 | demo_fsm_engine(start_init_e, &config, &context);
60 |
61 | demo_fsm_engine(init_tmo_e, &config, &context);
62 | demo_fsm_engine(init_tmo_e, &config, &context);
63 | demo_fsm_engine(init_ack_e, &config, &context);
64 |
65 | demo_fsm_engine(start_term_e, &config, &context);
66 | demo_fsm_engine(term_ack_e, &config, &context);
67 |
68 | demo_fsm_show_history(&config, &context);
69 |
70 | demo_fsm_show_state_table(&config, &context);
71 |
72 | exit (0);
73 | }
74 |
75 |
76 |
--------------------------------------------------------------------------------
/safe_base/src/runtime_environment.c:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * runtime_environment.c -- Misc functions
3 | *
4 | * Copyright (c) 2008-2011 by Cisco Systems, Inc
5 | * All rights reserved.
6 | *
7 | * Permission is hereby granted, free of charge, to any person
8 | * obtaining a copy of this software and associated documentation
9 | * files (the "Software"), to deal in the Software without
10 | * restriction, including without limitation the rights to use,
11 | * copy, modify, merge, publish, distribute, sublicense, and/or
12 | * sell copies of the Software, and to permit persons to whom the
13 | * Software is furnished to do so, subject to the following
14 | * conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be
17 | * included in all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 | * OTHER DEALINGS IN THE SOFTWARE.
27 | *------------------------------------------------------------------
28 | */
29 |
30 | #include
31 | #include
32 |
33 | #include "safe_types.h"
34 | #include "runtime_environment.h"
35 |
36 |
37 | /* simple stub */
38 | static uint32_t interrupt_sema_count = 0;
39 |
40 |
41 | /**
42 | * NAME
43 | * lock_interrupts
44 | *
45 | * DESCRIPTION
46 | * Abstract the interrupt lock.
47 | *
48 | * INPUT PARAMETERS
49 | * context - a void pointer
50 | *
51 | * OUTPUT PARAMETERS
52 | * none
53 | *
54 | * RETURNS
55 | * none
56 | *
57 | */
58 | void
59 | lock_interrupts (void *context)
60 | {
61 | interrupt_sema_count++;
62 | return;
63 | }
64 |
65 |
66 | /**
67 | * NAME
68 | * unlock_interrupts
69 | *
70 | * DESCRIPTION
71 | * Abstract the interrupt lock.
72 | *
73 | * INPUT PARAMETERS
74 | * context - a void pointer
75 | *
76 | * OUTPUT PARAMETERS
77 | * none
78 | *
79 | * RETURNS
80 | * none
81 | *
82 | */
83 | void
84 | unlock_interrupts(void *context)
85 | {
86 | interrupt_sema_count--;
87 | return;
88 | }
89 |
90 |
91 |
--------------------------------------------------------------------------------
/efsm/doc/fsm_readme.txt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2005-2009 by Cisco Systems, Inc.
3 | *
4 | * Permission is hereby granted, free of charge, to any person
5 | * obtaining a copy of this software and associated documentation
6 | * files (the "Software"), to deal in the Software without restriction,
7 | * including without limitation the rights to use, copy, modify, merge,
8 | * publish, distribute, sublicense, and/or sell copies of the Software,
9 | * and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be
13 | * included in all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | The finite state machine can be used to model the behavior of
25 | systems, systems that exist in one or more states. State transitions
26 | are driven by a set of normalized events derived from one or more
27 | sources.
28 |
29 | The initial state can be any one of the normalized states. This is
30 | defined when the state machie is created. The number of state is
31 | determined by a state table. Each state table entry, state, references
32 | an event table. The normalized event table is maps each event to a
33 | specific event handler. The handler is a user function that handles
34 | the specific event.
35 |
36 |
37 |
38 | The Demo
39 |
40 | The demo is a simple imaginary protocol to demonstrate the state and
41 | event tables to configure a state machine and a few fsm calls to
42 | drive that state machine. Included are calls to display the state
43 | machine history of events and resulting state transitions (useful
44 | for debugging) and a call to display the state-event tables. The
45 | organization of the demo software suggests an organization for your
46 | real application.
47 |
48 |
49 |
50 | References
51 |
52 | [1] http://en.wikipedia.org/wiki/Finite_state_machine
53 |
54 | [2] http://en.wikipedia.org/wiki/Mealy_machine
55 |
56 | [3] http://en.wikipedia.org/wiki/Moore_machine
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/efsm/doc/demo_fsm_output.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | event_start_init-50
5 | event_init_ack_tmo-100
6 | event_init_ack_tmo-116 init time out count=1 threshold=3
7 | event_init_ack_tmo-100
8 | event_init_ack_tmo-116 init time out count=2 threshold=3
9 | event_init_ack_rcvd-82
10 | event_start_term-138
11 | event_term_ack_rcvd-171
12 |
13 | FSM: Demo State Machine History
14 | Current State / Event / New State / rc
15 | ------------------------------------------------
16 | 0-Idle State / 0-Start Session Init / 1-Wait for Init Ack State / 0
17 | 1-Wait for Init Ack State / 2-Session Init ACK TMO / 1-Wait for Init Ack State / 0
18 | 1-Wait for Init Ack State / 2-Session Init ACK TMO / 1-Wait for Init Ack State / 0
19 | 1-Wait for Init Ack State / 3-Session Init ACK / 2-Established State / 0
20 | 2-Established State / 4-Start Session Termination / 3-Wait for Terminate Ack State / 0
21 | 3-Wait for Terminate Ack State / 6-Session Terminate ACK / 0-Idle State / 0
22 |
23 |
24 | FSM: Demo State Machine Counters
25 | Invalid events = 0
26 | Invalid states = 0
27 | Exception states set = 0
28 | Quiet states = 0
29 | Handler error = 0
30 | Ignored events = 0
31 |
32 |
33 | FSM: Demo State Machine
34 | number_states = 4
35 | number_events = 7
36 | curr_state = Idle State
37 |
38 | State: Idle State
39 | Event / Next State
40 | ----------------------------
41 | 0-Start Session Init / Wait for Init Ack State
42 | 1-Session Init / Established State
43 | 2-Session Init ACK TMO / Idle State
44 | 3-Session Init ACK / Idle State
45 | 4-Start Session Termination / Idle State
46 | 5-Session Terminate / Idle State
47 | 6-Session Terminate ACK / Idle State
48 |
49 | State: Wait for Init Ack State
50 | Event / Next State
51 | ----------------------------
52 | 0-Start Session Init / Wait for Init Ack State
53 | 1-Session Init / Wait for Init Ack State
54 | 2-Session Init ACK TMO / Wait for Init Ack State
55 | 3-Session Init ACK / Established State
56 | 4-Start Session Termination / Wait for Init Ack State
57 | 5-Session Terminate / Idle State
58 | 6-Session Terminate ACK / Wait for Init Ack State
59 |
60 | State: Established State
61 | Event / Next State
62 | ----------------------------
63 | 0-Start Session Init / Established State
64 | 1-Session Init / Established State
65 | 2-Session Init ACK TMO / Established State
66 | 3-Session Init ACK / Established State
67 | 4-Start Session Termination / Wait for Terminate Ack State
68 | 5-Session Terminate / Idle State
69 | 6-Session Terminate ACK / Established State
70 |
71 | State: Wait for Terminate Ack State
72 | Event / Next State
73 | ----------------------------
74 | 0-Start Session Init / Wait for Terminate Ack State
75 | 1-Session Init / Wait for Terminate Ack State
76 | 2-Session Init ACK TMO / Wait for Terminate Ack State
77 | 3-Session Init ACK / Wait for Terminate Ack State
78 | 4-Start Session Termination / Wait for Terminate Ack State
79 | 5-Session Terminate / Idle State
80 | 6-Session Terminate ACK / Idle State
81 |
82 |
83 |
--------------------------------------------------------------------------------
/safe_base/include/safe_types.h:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * safe_types.h
3 | *
4 | * March 2007, Bo Berry
5 | *
6 | * Copyright (c) 2007-2011 by Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom the
15 | * Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __SAFE_TYPES__
33 | #define __SAFE_TYPES__
34 |
35 | #include
36 |
37 | #include "safe_limits.h"
38 |
39 |
40 | /*
41 | * Abstract header file for portability.
42 | */
43 |
44 | #ifndef TRUE
45 | #define TRUE ( 1 )
46 | #endif
47 |
48 | #ifndef FALSE
49 | #define FALSE ( 0 )
50 | #endif
51 |
52 | #ifndef NULL
53 | #define NULL ((void *) 0)
54 | #endif
55 |
56 | #ifndef boolean_t
57 | typedef unsigned char boolean_t;
58 | #endif
59 |
60 |
61 |
62 | #ifndef int8_t
63 | typedef signed char int8_t;
64 | #endif
65 |
66 | #ifndef int16_t
67 | typedef short int16_t;
68 | #endif
69 |
70 | #ifndef int32_t
71 | typedef int int32_t;
72 | #endif
73 |
74 | #ifndef uchar_t
75 | typedef unsigned char uchar_t;
76 | #endif
77 |
78 | #ifndef uint8_t
79 | typedef unsigned char uint8_t;
80 | #endif
81 |
82 | #ifndef uint16_t
83 | typedef unsigned short uint16_t;
84 | #endif
85 |
86 | #ifndef uint32_t
87 | typedef unsigned int uint32_t;
88 | #endif
89 |
90 | #ifndef uint64_t
91 | typedef unsigned long long uint64_t;
92 | #endif
93 |
94 | #if 0
95 | #if POINTER_BIT == 64
96 | #ifndef intptr_t;
97 | typedef long long intptr_t;
98 | #endif
99 |
100 | #ifndef uintptr_t;
101 | typedef unsigned long long uintptr_t;
102 | #endif
103 |
104 | #else
105 |
106 | #ifndef intptr_t;
107 | typedef signed int intptr_t;
108 | #endif
109 | #ifndef uintptr_t;
110 | typedef unsigned int uintptr_t;
111 | #endif
112 |
113 | #endif
114 | #endif
115 |
116 |
117 | #ifndef ushort
118 | typedef unsigned short ushort;
119 | #endif
120 |
121 | #ifndef int_t
122 | typedef int int_t;
123 | #endif
124 |
125 | #ifndef uint_t
126 | typedef unsigned int uint_t;
127 | #endif
128 |
129 | #ifndef ulong
130 | typedef unsigned long ulong;
131 | #endif
132 |
133 | #ifndef ulonglong
134 | typedef unsigned long long ullong;
135 | #endif
136 |
137 |
138 | #endif /* __SAFE_TYPES__ */
139 |
140 |
--------------------------------------------------------------------------------
/efsm/test/demo_session_fsm.h:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo_session_fsm.h
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *---------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __DEMO_SESSION_FSM_H__
33 | #define __DEMO_SESSION_FSM_H__
34 |
35 | #include "demo_context.h"
36 |
37 |
38 | /*
39 | * normalized events
40 | */
41 | typedef enum {
42 | /*
43 | * The state machine remains dormant until the start
44 | * event. The start event handler will send an init
45 | * message to the server, and transition to the
46 | * wait for ack state.
47 | */
48 | start_init_e,
49 |
50 | /*
51 | * When the server receives the init, the init rcvd
52 | * event is processed by the state machine.
53 | */
54 | init_rcvd_e,
55 |
56 | /*
57 | * If the client does not receive an acknowledgement
58 | * to the init, a guard timer expires. The guard
59 | * timer expiration is processed as an init ack timeout.
60 | */
61 | init_tmo_e,
62 |
63 | /*
64 | * When the client receives an acknowledgement to the
65 | * init request from the server, the ack event is
66 | * processed by the state machine.
67 | */
68 | init_ack_e,
69 |
70 | /*
71 | * The start terminate event is used to terminate the
72 | * established session. This event will generate a
73 | * terminate message.
74 | */
75 | start_term_e,
76 |
77 | /*
78 | * When the terminate request is received, the terminate
79 | * received event is processed to terminate the session
80 | * and send an acknowledgement.
81 | */
82 | term_rcvd_e,
83 |
84 | /*
85 | * This is an acknowledgement to the terminate request.
86 | */
87 | term_ack_e,
88 | } session_events_e;
89 |
90 |
91 | /*
92 | * normalized states
93 | */
94 | typedef enum {
95 | /*
96 | * The idle state represents a dormant state. The start event
97 | * kicks things off.
98 | */
99 | idle_s = 0,
100 |
101 | /*
102 | * This state expects the acknowledgement to the init request
103 | * of the guard timer expiration.
104 | */
105 | wait_for_init_ack_s,
106 |
107 | /*
108 | * The established state is reached once the init request and
109 | * init ack have been exchanged.
110 | */
111 | established_s,
112 |
113 | /*
114 | * Ths state expects the acknowledgement to the terminate
115 | */
116 | wait_for_term_ack_s,
117 | } demo_states_e;
118 |
119 |
120 |
121 |
122 | extern uint32_t
123 | demo_fsm_get_state(demo_config_t *p2config,
124 | demo_context_t *p2context);
125 |
126 | extern void
127 | demo_fsm_show_counter(demo_config_t *p2config,
128 | demo_context_t *p2context);
129 |
130 | extern void
131 | demo_fsm_show_state_table(demo_config_t *p2config,
132 | demo_context_t *p2context);
133 |
134 | extern void
135 | demo_fsm_show_history(demo_config_t *p2config,
136 | demo_context_t *p2context);
137 |
138 | extern void
139 | demo_fsm_engine(uint32_t normalized_event,
140 | demo_config_t *p2config,
141 | demo_context_t *p2context);
142 |
143 | extern void
144 | demo_fsm_destroy(demo_config_t *p2config,
145 | demo_context_t *p2context);
146 |
147 | extern void
148 | demo_fsm_create(demo_config_t *p2config,
149 | demo_context_t *p2context);
150 |
151 |
152 | #endif
153 |
154 |
--------------------------------------------------------------------------------
/safe_base/include/safe_limits.h:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * safe_limits.h
3 | *
4 | * February 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009-2011 by Cisco Systems
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom the
15 | * Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __SAFE_LIMITS__
33 | #define __SAFE_LIMITS__
34 |
35 | /*
36 | * Abstract header file for portability.
37 | */
38 |
39 |
40 | /*
41 | * ANSI C - number of bits by type
42 | */
43 | #ifndef CHAR_BIT
44 | #define CHAR_BIT ( 8 )
45 | #endif
46 |
47 | #ifndef BYTE_BIT
48 | #define BYTE_BIT ( 8 )
49 | #endif
50 |
51 | #ifndef SHORT_BIT
52 | #define SHORT_BIT ( 16 )
53 | #endif
54 |
55 | #ifndef INT_BIT
56 | #define INT_BIT ( 32 )
57 | #endif
58 |
59 | #ifndef LONG_BIT
60 | // #define LONG_BIT ( 32 )
61 | #define LONG_BIT ( 64 )
62 | #endif
63 |
64 | #ifndef LONG_LONG_BIT
65 | #define LONG_LONG_BIT ( 64 )
66 | #endif
67 |
68 | #ifndef POINTER_BIT
69 | #define POINTER_BIT ( 64 )
70 | #endif
71 |
72 |
73 |
74 | #ifndef BYTE_MAX
75 | #define BYTE_MAX ( 255 )
76 | #endif
77 |
78 | #ifndef SCHAR_MAX
79 | #define SCHAR_MAX ( 127 )
80 | #define SCHAR_MIN ( -SCHAR_MAX - 1 )
81 | #endif
82 |
83 | #ifndef CHAR_MAX
84 | #define CHAR_MAX ( 127 )
85 | #define CHAR_MIN ( -CHAR_MAX - 1 )
86 | #endif
87 |
88 | #ifndef UCHAR_MAX
89 | #define UCHAR_MAX ( 0xff )
90 | #endif
91 |
92 | #ifndef SHRT_MAX
93 | #define SHRT_MAX ( 32767 )
94 | #define SHRT_MIN ( -SHRT_MAX - 1 )
95 | #endif
96 |
97 | #ifndef USHRT_MAX
98 | #define USHRT_MAX ( 0xffff )
99 | #endif
100 |
101 | #ifndef INT_MAX
102 | #define INT_MAX ( 2147483647 )
103 | #define INT_MIN ( -INT_MAX - 1 )
104 | #endif
105 |
106 | #ifndef UINT_MAX
107 | #define UINT_MAX ( 0xffffffff )
108 | #endif
109 |
110 | #ifndef LLONG_MAX
111 | #define LLONG_MAX ( 9223372036854775807 )
112 | #define LLONG_MIN ( -LLONG_MAX - 1 )
113 | #endif
114 |
115 | #ifndef ULLONG_MAX
116 | #define ULLONG_MAX ( 0xffffffffffffffff )
117 | #endif
118 |
119 |
120 | #if LONG_BIT == INT_BIT
121 |
122 | #ifndef LONG_MAX
123 | #define LONG_MAX ( INT_MAX)
124 | #define LONG_MIN ( -LONG_MAX - 1 )
125 | #endif
126 |
127 | #ifndef ULONG_MAX
128 | #define ULONG_MAX ( UINT_MAX )
129 | #endif
130 |
131 | #else
132 |
133 | #ifndef LONG_MAX
134 | #define LONG_MAX ( LLONG_MAX)
135 | #define LONG_MIN ( -LONG_MAX - 1 )
136 | #endif
137 |
138 | #ifndef ULONG_MAX
139 | #define ULONG_MAX ( ULLONG_MAX )
140 | #endif
141 |
142 | #endif
143 |
144 |
145 | #ifndef INT8_MIN
146 | #define INT8_MIN ( SCHAR_MIN )
147 | #endif
148 |
149 | #ifndef INT8_MAX
150 | #define INT8_MAX ( SCHAR_MAX )
151 | #endif
152 |
153 | #ifndef UINT8_MAX
154 | #define UINT8_MAX ( UCHAR_MAX )
155 | #endif
156 |
157 | #ifndef INT16_MIN
158 | #define INT16_MIN ( SHRT_MIN )
159 | #endif
160 |
161 | #ifndef INT16_MAX
162 | #define INT16_MAX ( SHRT_MAX )
163 | #endif
164 |
165 | #ifndef UINT16_MAX
166 | #define UINT16_MAX ( USHRT_MAX )
167 | #endif
168 |
169 | #ifndef INT32_MIN
170 | #define INT32_MIN ( INT_MIN )
171 | #endif
172 |
173 | #ifndef INT32_MAX
174 | #define INT32_MAX ( INT_MAX )
175 | #endif
176 |
177 | #ifndef UINT32_MAX
178 | #define UINT32_MAX ( UINT_MAX )
179 | #endif
180 |
181 | #ifndef INT64_MIN
182 | #define INT64_MIN ( LLONG_MIN )
183 | #endif
184 |
185 | #ifndef INT64_MAX
186 | #define INT64_MAX ( LLONG_MAX )
187 | #endif
188 |
189 | #ifndef UINT64_MAX
190 | #define UINT64_MAX ( ULLONG_MAX )
191 | #endif
192 |
193 |
194 | #endif /* __SAFE_LIMITS__ */
195 |
196 |
--------------------------------------------------------------------------------
/efsm/test/demo_event_handlers.c:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo_event_handlers.c
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *---------------------------------------------------------------------
30 | */
31 |
32 | #include
33 | #include
34 |
35 | #include "fsm.h"
36 | #include "demo_context.h"
37 | #include "demo_session_fsm.h"
38 |
39 |
40 |
41 | /*
42 | * This event is triggered when the start init is rcvd
43 | */
44 | RC_FSM_t event_start_init (void *p2event, void *p2parm)
45 | {
46 | demo_config_t *p2config;
47 | demo_context_t *p2context;
48 |
49 | p2config = p2event;
50 | p2context = p2parm;
51 |
52 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
53 | return (RC_FSM_OK);
54 | }
55 |
56 |
57 | /*
58 | * This event is triggered when an init is rcvd
59 | */
60 | RC_FSM_t event_init_rcvd (void *p2event, void *p2parm)
61 | {
62 | demo_config_t *p2config;
63 | demo_context_t *p2context;
64 |
65 | p2config = p2event;
66 | p2context = p2parm;
67 |
68 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
69 | return (RC_FSM_OK);
70 | }
71 |
72 |
73 | /*
74 | * This event is triggered when an init ack is rcvd
75 | */
76 | RC_FSM_t event_init_ack_rcvd (void *p2event, void *p2parm)
77 | {
78 | demo_config_t *p2config;
79 | demo_context_t *p2context;
80 |
81 | p2config = p2event;
82 | p2context = p2parm;
83 |
84 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
85 | return (RC_FSM_OK);
86 | }
87 |
88 |
89 | /*
90 | * This event is triggered when a timeout for the init ack occurrs
91 | */
92 | RC_FSM_t event_init_ack_tmo (void *p2event, void *p2parm)
93 | {
94 | RC_FSM_t rc;
95 |
96 | demo_config_t *p2config;
97 | demo_context_t *p2context;
98 |
99 | p2config = p2event;
100 | p2context = p2parm;
101 |
102 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
103 |
104 | p2context->timeout_count++;
105 | if (p2context->timeout_count >= p2config->tmo_threshold) {
106 |
107 | DEMO_TRACE("%s-%u Error: init time outs exceeded \n",
108 | __FUNCTION__,
109 | __LINE__);
110 |
111 | rc = RC_FSM_STOP_PROCESSING;
112 | rc = RC_FSM_OK;
113 |
114 | } else {
115 |
116 | DEMO_TRACE("%s-%u init time out count=%u threshold=%u \n",
117 | __FUNCTION__,
118 | __LINE__,
119 | p2context->timeout_count,
120 | p2config->tmo_threshold);
121 |
122 | rc = RC_FSM_OK;
123 | }
124 |
125 | return (rc);
126 | }
127 |
128 |
129 | /*
130 | * This event is triggered when to start the termination
131 | */
132 | RC_FSM_t event_start_term (void *p2event, void *p2parm)
133 | {
134 | demo_config_t *p2config;
135 | demo_context_t *p2context;
136 |
137 | p2config = p2event;
138 | p2context = p2parm;
139 |
140 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
141 | return (RC_FSM_OK);
142 | }
143 |
144 |
145 | /*
146 | * This event is triggered when a terminate is rcvd
147 | */
148 | RC_FSM_t event_term_rcvd (void *p2event, void *p2parm)
149 | {
150 | demo_config_t *p2config;
151 | demo_context_t *p2context;
152 |
153 | p2config = p2event;
154 | p2context = p2parm;
155 |
156 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
157 | return (RC_FSM_OK);
158 | //return (RC_FSM_STOP_PROCESSING);
159 | }
160 |
161 |
162 | /*
163 | * This event is triggered when a terminate ack is rcvd
164 | */
165 | RC_FSM_t event_term_ack_rcvd (void *p2event, void *p2parm)
166 | {
167 | demo_config_t *p2config;
168 | demo_context_t *p2context;
169 |
170 | p2config = p2event;
171 | p2context = p2parm;
172 |
173 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
174 | return (RC_FSM_OK);
175 | //return (RC_FSM_STOP_PROCESSING);
176 | }
177 |
178 |
--------------------------------------------------------------------------------
/efsm/test/demo_session_fsm.c:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------
2 | * demo_session_fsm.c
3 | *
4 | * January 2009, Bo Berry
5 | *
6 | * Copyright (c) 2009 Cisco Systems, Inc
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *---------------------------------------------------------------------
30 | */
31 |
32 | #include
33 |
34 | #include "safe_limits.h"
35 | #include "fsm.h"
36 | #include "demo_context.h"
37 | #include "demo_event_handlers.h"
38 |
39 | #include "demo_session_fsm.h"
40 |
41 |
42 |
43 |
44 | /*
45 | * table of normalized event descriptions
46 | */
47 | static event_description_t normalized_event_table[] =
48 | {{start_init_e, "Start Session Init"},
49 | {init_rcvd_e, "Session Init"},
50 | {init_tmo_e, "Session Init ACK TMO"},
51 | {init_ack_e, "Session Init ACK"},
52 | {start_term_e, "Start Session Termination"},
53 | {term_rcvd_e, "Session Terminate"},
54 | {term_ack_e, "Session Terminate ACK"},
55 | {FSM_NULL_EVENT_ID, NULL} };
56 |
57 |
58 | /*
59 | * table of normalized state descriptions
60 | */
61 | static state_description_t normalized_state_table[] =
62 | {{idle_s, "Idle State"},
63 | {wait_for_init_ack_s, "Wait for Init Ack State"},
64 | {established_s, "Established State"},
65 | {wait_for_term_ack_s, "Wait for Terminate Ack State"},
66 | {FSM_NULL_STATE_ID, NULL} };
67 |
68 |
69 | /* state machine handle */
70 | static fsm_t *fsm_handle;
71 |
72 |
73 | /*
74 | * catch-all ignore event processing
75 | */
76 | static RC_FSM_t event_ignore (void *p2event, void *p2parm)
77 | {
78 | DEMO_TRACE("%s-%u\n", __FUNCTION__, __LINE__);
79 | return (RC_FSM_OK);
80 | }
81 |
82 |
83 |
84 | /*
85 | * State event tables
86 | */
87 | static event_tuple_t state_idle_events[] =
88 | /* The client sending the init */
89 | { { start_init_e, event_start_init, wait_for_init_ack_s},
90 | /* The server rcvd an init */
91 | { init_rcvd_e, event_init_rcvd, established_s},
92 |
93 | { init_tmo_e, event_ignore, idle_s},
94 | { init_ack_e, event_ignore, idle_s},
95 | { start_term_e, event_ignore, idle_s},
96 | { term_rcvd_e, event_ignore, idle_s},
97 | { term_ack_e, event_ignore, idle_s} };
98 |
99 | static event_tuple_t state_wait_for_init_ack_events[] =
100 | { { start_init_e, event_ignore, wait_for_init_ack_s},
101 | { init_rcvd_e, event_ignore, wait_for_init_ack_s},
102 | { init_tmo_e, event_init_ack_tmo, wait_for_init_ack_s},
103 | { init_ack_e, event_init_ack_rcvd, established_s},
104 | { start_term_e, event_term_rcvd, wait_for_init_ack_s},
105 | { term_rcvd_e, event_term_rcvd, idle_s},
106 | { term_ack_e, event_ignore, wait_for_init_ack_s} };
107 |
108 | static event_tuple_t state_established_events[] =
109 | { { start_init_e, event_ignore, established_s},
110 | { init_rcvd_e, event_ignore, established_s},
111 | { init_tmo_e, event_ignore, established_s},
112 | { init_ack_e, event_ignore, established_s},
113 | { start_term_e, event_start_term, wait_for_term_ack_s},
114 | { term_rcvd_e, event_term_rcvd, idle_s},
115 | { term_ack_e, event_ignore, established_s} };
116 |
117 | static event_tuple_t state_wait_for_term_ack_events[] =
118 | /****** Event ID ******* Handler ************* Next State ID *****/
119 | { { start_init_e, event_ignore, wait_for_term_ack_s},
120 | { init_rcvd_e, event_ignore, wait_for_term_ack_s},
121 | { init_tmo_e, event_ignore, wait_for_term_ack_s},
122 | { init_ack_e, event_ignore, wait_for_term_ack_s},
123 | { start_term_e, event_ignore, wait_for_term_ack_s},
124 | { term_rcvd_e, event_ignore, idle_s},
125 | { term_ack_e, event_term_ack_rcvd, idle_s} };
126 |
127 |
128 | /*
129 | * Session State table
130 | */
131 | static state_tuple_t demo_state_table[] =
132 | /*** State ID ****************** Event Table ***/
133 | { {idle_s, state_idle_events},
134 | {wait_for_init_ack_s, state_wait_for_init_ack_events},
135 | {established_s, state_established_events},
136 | {wait_for_term_ack_s, state_wait_for_term_ack_events},
137 | {FSM_NULL_STATE_ID, NULL} };
138 |
139 |
140 | /*
141 | * This function is used to return the current state
142 | */
143 | uint32_t
144 | demo_fsm_get_state (demo_config_t *p2config,
145 | demo_context_t *p2context)
146 | {
147 | uint32_t state;
148 |
149 | state = (-1);
150 |
151 | if (p2context) {
152 | fsm_get_state(fsm_handle, &state);
153 | } else {
154 | /* ignore */
155 | }
156 | return (state);
157 | }
158 |
159 |
160 |
161 | /*
162 | * This function is used to display the state machine sate table
163 | */
164 | void
165 | demo_fsm_show_state_table (demo_config_t *p2config,
166 | demo_context_t *p2context)
167 | {
168 | if (p2context) {
169 | fsm_display_table(fsm_handle);
170 | } else {
171 | /* ignore */
172 | }
173 | return;
174 | }
175 |
176 |
177 | /*
178 | * This function is used to display a state machine's history
179 | */
180 | void
181 | demo_fsm_show_history (demo_config_t *p2config,
182 | demo_context_t *p2context)
183 | {
184 | if (p2context) {
185 | fsm_show_history(fsm_handle);
186 | } else {
187 | /* ignore */
188 | }
189 | return;
190 | }
191 |
192 |
193 | /*
194 | * demo state machine engine
195 | */
196 | void
197 | demo_fsm_engine (uint32_t normalized_event,
198 | demo_config_t *p2config,
199 | demo_context_t *p2context)
200 | {
201 | RC_FSM_t rc;
202 |
203 | if (!p2config) {
204 | DEMO_ERROR("%s-%u Error: Config is null \n",
205 | __FUNCTION__,
206 | __LINE__);
207 | return;
208 | }
209 |
210 | if (!p2context) {
211 | DEMO_ERROR("%s-%u Error: Context is null \n",
212 | __FUNCTION__,
213 | __LINE__);
214 | return;
215 | }
216 |
217 | rc = fsm_engine(fsm_handle,
218 | normalized_event,
219 | p2config,
220 | p2context);
221 | if (rc != RC_FSM_OK) {
222 | DEMO_ERROR("%s-%u Error: demo state machine rc=%u \n",
223 | __FUNCTION__,
224 | __LINE__,
225 | rc);
226 | }
227 | return;
228 | }
229 |
230 |
231 | /*
232 | * This function is used to destroy a demo state machine engine
233 | */
234 | void
235 | demo_fsm_destroy (demo_config_t *p2config,
236 | demo_context_t *p2context)
237 | {
238 | if (!p2config) {
239 | DEMO_ERROR("%s-%u Error: Config is null \n",
240 | __FUNCTION__,
241 | __LINE__);
242 | return;
243 | }
244 |
245 | if (!p2context) {
246 | DEMO_ERROR("%s-%u Error: Context is null \n",
247 | __FUNCTION__,
248 | __LINE__);
249 | return;
250 | }
251 |
252 | fsm_destroy((fsm_t **)&fsm_handle);
253 | return;
254 | }
255 |
256 |
257 | /*
258 | * This function is used to create a demo state machine
259 | * when the session is instaniated.
260 | */
261 | void
262 | demo_fsm_create (demo_config_t *p2config,
263 | demo_context_t *p2context)
264 | {
265 | RC_FSM_t rc;
266 |
267 | if (!p2config) {
268 | DEMO_ERROR("%s-%u Error: Config is null \n",
269 | __FUNCTION__,
270 | __LINE__);
271 | return;
272 | }
273 |
274 | if (!p2context) {
275 | DEMO_ERROR("%s-%u Error: Context is null \n",
276 | __FUNCTION__,
277 | __LINE__);
278 | return;
279 | }
280 |
281 | fsm_handle = NULL;
282 | rc = fsm_create((fsm_t **)&fsm_handle,
283 | "Demo State Machine",
284 | idle_s,
285 | normalized_state_table,
286 | normalized_event_table,
287 | demo_state_table);
288 | if (rc != RC_FSM_OK) {
289 | DEMO_ERROR("%s-%u Error: demo state machine rc=%u \n",
290 | __FUNCTION__,
291 | __LINE__,
292 | rc);
293 | }
294 |
295 | return;
296 | }
297 |
298 |
299 |
--------------------------------------------------------------------------------
/efsm/include/fsm.h:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * fsm.h - Finite State Machine definitions
3 | *
4 | * February 2005, Bo Berry
5 | *
6 | * Copyright (c) 2005-2009 by Cisco Systems, Inc.
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *------------------------------------------------------------------
30 | */
31 |
32 | #ifndef __FSM_H__
33 | #define __FSM_H__
34 |
35 | #include "safe_types.h"
36 |
37 |
38 | /*
39 | * return codes utilized by the fsm APIs and
40 | * user event handlers
41 | */
42 | typedef enum {
43 | /* indicates success - state change */
44 | RC_FSM_OK = 0,
45 |
46 | /* indicates that the fsm handle was NULL */
47 | RC_FSM_NULL,
48 |
49 | /* indicates that the fsm handle pointed to somethinf else! */
50 | RC_FSM_INVALID_HANDLE,
51 |
52 | RC_FSM_INVALID_EVENT_HANDLER,
53 |
54 | /* indicates that an error was found in the state table */
55 | RC_FSM_INVALID_STATE_TABLE,
56 |
57 | /* indicates that the next state was out of bounds */
58 | RC_FSM_INVALID_STATE,
59 |
60 | /* indicates that an error was found in the event table */
61 | RC_FSM_INVALID_EVENT_TABLE,
62 |
63 | /* indicates that the next event was out of bounds */
64 | RC_FSM_INVALID_EVENT,
65 |
66 | /* indicates that there was no memory available */
67 | RC_FSM_NO_RESOURCES,
68 |
69 | /* event handler indicating that the event can be
70 | * ignored, no transition
71 | */
72 | RC_FSM_IGNORE_EVENT,
73 |
74 | /* event handler indicating that the state machine is
75 | * being deallocated and no further access to the fsm
76 | * strucutre should be made - history
77 | */
78 | RC_FSM_STOP_PROCESSING,
79 | } RC_FSM_t;
80 |
81 |
82 |
83 | #define FSM_NULL_STATE_ID ( -1 )
84 | #define FSM_NULL_EVENT_ID ( -1 )
85 |
86 |
87 | /*
88 | * typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm)
89 | *
90 | * DESCRIPTION
91 | * Provides typedef for the event handler functions.
92 | *
93 | * Once the state's normalized event ID and index has been
94 | * determined, the associated event call-back is invoked
95 | * to effect the state processing and transition.
96 | *
97 | * INPUT PARAMETERS
98 | * p2event pointer to the raw event to be processed
99 | * by the event handler.
100 | *
101 | * p2parm pointer parameter that is simply
102 | * passed through from fsm_engine to each
103 | * event handler.
104 | *
105 | * RETURN VALUE
106 | * RC_FSM_OK
107 | * error otherwise
108 | */
109 | typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm);
110 |
111 |
112 | /*
113 | * User provided Normalized Event Description Table.
114 | *
115 | * An Example
116 | * typedef enum {
117 | * start_init_e = 0,
118 | * init_rcvd_e,
119 | * init_tmo_e,
120 | * init_ack_e,
121 | * start_term_e,
122 | * term_rcvd_e,
123 | * term_ack_e,
124 | * } session_events_e;
125 | *
126 | * static event_description_t normalized_event_table[] =
127 | * {{start_init_e, "Start Session Init"},
128 | * {init_rcvd_e, "Session Init"},
129 | * {init_tmo_e, "Session Init ACK TMO"},
130 | * {init_ack_e, "Session Init ACK"},
131 | * {start_term_e, "Start Session Termination"},
132 | * {term_rcvd_e, "Session Terminate"},
133 | * {term_ack_e, "Session Terminate ACK"},
134 | * {FSM_NULL_EVENT_ID, NULL}}; / required to end table /
135 | *
136 | */
137 | typedef struct {
138 | uint32_t event_id;
139 | char *description;
140 | } event_description_t;
141 |
142 |
143 | /*
144 | * User provided Normalized State DESCRIPTION Table.
145 | *
146 | * An example
147 | * typedef enum {
148 | * idle_s = 0,
149 | * wait_for_init_ack_s,
150 | * established_s,
151 | * wait_for_term_ack_s,
152 | * } demo_states_e;
153 | *
154 | * static state_description_t normalized_state_table[] =
155 | * {{start_init_e, "Start Session Init"},
156 | * {idle_s, Idle State"},
157 | * {wait_for_init_ack_s, "Wait for Init Ack State"},
158 | * {established_s, "Established State"},
159 | * {wait_for_term_ack_s, "Wait for Terminate Ack State"},
160 | * {FSM_NULL_STATE_ID, NULL}}; / required to end table /
161 | *
162 | */
163 | typedef struct {
164 | uint32_t state_id;
165 | char *description;
166 | } state_description_t;
167 |
168 |
169 |
170 | /*
171 | * User provided Event Table - one table per state is
172 | * required. The table must have an entry for each
173 | * normalized event, ordered from 0 - n.
174 | *
175 | * event_id is the normalized value.
176 | *
177 | * event_handler is the user provided call-back function that is
178 | * invoked to handle the event and effect the state transition.
179 | * If the event_handler is NULL, no processing is
180 | * associated with the event - no state transition.
181 | *
182 | * next_state is the next state as result of the event. It is
183 | * possible that a state transition associated with an event
184 | * remain in the current state.
185 | *
186 | * An example:
187 | * static event_tuple_t state_wait_for_init_ack_events[] =
188 | * {{start_init_e, event_ignore, wait_for_init_ack_s},
189 | * {init_rcvd_e, event_ignore, wait_for_init_ack_s},
190 | * {init_tmo_e, event_init_ack_tmo, wait_for_init_ack_s},
191 | * {init_ack_e, event_init_ack_rcvd, established_s},
192 | * {start_term_e, event_term_rcvd, wait_for_term_ack_s},
193 | * {term_rcvd_e, event_term_rcvd, idle_s},
194 | * {term_ack_e, event_ignore, wait_for_term_ack_s}};
195 | */
196 | typedef struct {
197 | uint32_t eventID; /* normalized event id */
198 | event_cb_t event_handler; /* if NULL==no transaction processing */
199 | uint32_t next_state; /* normalized next state - can be
200 | * the same state */
201 | } event_tuple_t;
202 |
203 |
204 | /*
205 | * User provided Normalized State Table. This table represents all
206 | * the states and the event table associated with each state.
207 | *
208 | * An example:
209 | * static state_tuple_t demo_state_table[] =
210 | * {{idle_s, state_idle_events},
211 | * {wait_for_init_ack_s, state_wait_for_init_ack_events},
212 | * {established_s, state_established_events},
213 | * {wait_for_term_ack_s, state_wait_for_term_ack_events},
214 | * {FSM_NULL_STATE_ID, NULL}}; / requied to end table /
215 | */
216 | typedef struct {
217 | uint32_t state_id;
218 | event_tuple_t *p2event_tuple;
219 | } state_tuple_t;
220 |
221 |
222 | /*
223 | * Historical record of state changes
224 | */
225 | typedef struct {
226 | uint32_t number;
227 | uint32_t prevStateID;
228 | uint32_t stateID;
229 | uint32_t eventID;
230 | RC_FSM_t handler_rc;
231 | } fsm_history_t;
232 |
233 |
234 | #define FSM_HISTORY ( 64 )
235 |
236 | /*
237 | * Finite State Machine structure
238 | *
239 | */
240 | #define FSM_TAG ( 0xba5eba11 )
241 | #define FSM_NAME_LEN ( 32 )
242 |
243 | typedef struct {
244 | /* for fsm validation */
245 | uint32_t tag;
246 |
247 | uint32_t curr_state;
248 | uint32_t next_state;
249 |
250 | /*
251 | * This is set by an event handle to cover an excpetion
252 | * state transition that is different from the event
253 | * table next state transition.
254 | */
255 | uint32_t exception_state;
256 | boolean_t exception_state_indicator;
257 |
258 | char fsm_name[FSM_NAME_LEN];
259 |
260 | /* number states in table */
261 | uint32_t number_states;
262 |
263 | /* number events in each state-event table */
264 | uint32_t number_events;
265 |
266 | /* debug and trace flags*/
267 | uint32_t flags;
268 |
269 | /* pointer to the state table */
270 | state_tuple_t *state_table;
271 |
272 | /* description of normalized states and events */
273 | state_description_t *state_description_table;
274 | event_description_t *event_description_table;
275 |
276 | /* starts at 0 and wraps */
277 | uint32_t history_index;
278 | /* memory is malloc'ed to record history */
279 | fsm_history_t *history;
280 | } fsm_t;
281 |
282 |
283 | /*
284 | * show state machine table
285 | */
286 | extern void
287 | fsm_display_table(fsm_t *fsm);
288 |
289 |
290 | /*
291 | * shows state machine history
292 | */
293 | extern void
294 | fsm_show_history(fsm_t *fsm);
295 |
296 |
297 | /* get state */
298 | extern RC_FSM_t
299 | fsm_get_state(fsm_t *fsm, uint32_t *p2state);
300 |
301 |
302 | /*
303 | * allows event handler to update the next state based upon
304 | * an unexpected condition when processing the event.
305 | */
306 | extern RC_FSM_t
307 | fsm_set_exception_state(fsm_t *fsm, uint32_t exception_state);
308 |
309 |
310 | /*
311 | * destroy a state machine
312 | */
313 | extern RC_FSM_t
314 | fsm_destroy(fsm_t **fsm);
315 |
316 |
317 | /*
318 | * create and config a state machine
319 | */
320 | extern RC_FSM_t
321 | fsm_create(fsm_t **fsm,
322 | char *fsm_name,
323 | uint32_t initial_state,
324 | state_description_t *state_description_table,
325 | event_description_t *event_description_table,
326 | state_tuple_t *state_table);
327 |
328 |
329 | /*
330 | * API to drive a state machine
331 | */
332 | extern RC_FSM_t
333 | fsm_engine(fsm_t *fsm,
334 | uint32_t normalized_event,
335 | void *p2event_bufer,
336 | void *p2parm);
337 |
338 |
339 | #endif /* __FSM_H__ */
340 |
341 |
--------------------------------------------------------------------------------
/efsm/src/fsm.c:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------
2 | * fsm.c -- Finite State Machine
3 | *
4 | * February 2005, Bo Berry
5 | *
6 | * Copyright (c) 2005-2009 by Cisco Systems, Inc.
7 | * All rights reserved.
8 | *
9 | * Permission is hereby granted, free of charge, to any person
10 | * obtaining a copy of this software and associated documentation
11 | * files (the "Software"), to deal in the Software without
12 | * restriction, including without limitation the rights to use,
13 | * copy, modify, merge, publish, distribute, sublicense, and/or
14 | * sell copies of the Software, and to permit persons to whom
15 | * the Software is furnished to do so, subject to the following
16 | * conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be
19 | * included in all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | * OTHER DEALINGS IN THE SOFTWARE.
29 | *------------------------------------------------------------------
30 | */
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include "fsm.h"
37 |
38 |
39 | /*
40 | * These are the maximum states and events that fsm uses
41 | * for sizing during create.
42 | */
43 | #define FSM_MAX_STATES ( 64 )
44 | #define FSM_MAX_EVENTS ( 64 )
45 |
46 |
47 |
48 | /**
49 | * NAME
50 | * fsm_display_table
51 | *
52 | * SYNOPSIS
53 | * #include "fsm.h"
54 | * void
55 | * fsm_display_table(fsm_t *fsm)
56 | *
57 | * DESCRIPTION
58 | * Displays the designated state machine table to console.
59 | *
60 | * INPUT PARAMETERS
61 | * fsm - handle to fsm
62 | *
63 | * OUTPUT PARAMETERS
64 | * none
65 | *
66 | * RETURN VALUE
67 | * none
68 | *
69 | */
70 | void
71 | fsm_display_table (fsm_t *fsm)
72 | {
73 | uint32_t i;
74 | uint32_t j;
75 | state_tuple_t *state_ptr;
76 | event_tuple_t *event_ptr;
77 |
78 | state_description_t *p2state_description;
79 | event_description_t *p2event_description;
80 |
81 | if (fsm == NULL) {
82 | return;
83 | }
84 |
85 | if (fsm->tag != FSM_TAG) {
86 | return;
87 | }
88 |
89 | p2state_description = fsm->state_description_table;
90 | p2event_description = fsm->event_description_table;
91 |
92 | printf("\nFSM: %s \n", fsm->fsm_name);
93 | printf(" number_states = %d\n", fsm->number_states);
94 | printf(" number_events = %d\n", fsm->number_events);
95 | printf(" curr_state = %s\n",
96 | p2state_description[fsm->curr_state].description );
97 | printf("\n");
98 |
99 | /*
100 | * For the normalized state table, list the normalized
101 | * events and state transitions.
102 | */
103 | for (i=0; inumber_states; i++) {
104 |
105 | state_ptr = &fsm->state_table[i];
106 |
107 | printf(" State: %s \n",
108 | p2state_description[state_ptr->state_id].description);
109 | printf(" Event / Next State \n");
110 | printf("----------------------------\n");
111 |
112 | for (j=0; jnumber_events; j++) {
113 |
114 | event_ptr = &state_ptr->p2event_tuple[j];
115 |
116 | /*
117 | * Display the name of the state associated with the next state.
118 | */
119 | printf(" %u-%s / %s \n",
120 | j,
121 | p2event_description[j].description,
122 | p2state_description[event_ptr->next_state].description);
123 | }
124 | printf("\n");
125 | }
126 | printf("\n");
127 | return;
128 | }
129 |
130 |
131 | /**
132 | * NAME
133 | * fsm_show_history
134 | *
135 | * SYNOPSIS
136 | * #include "fsm.h'
137 | * void
138 | * fsm_show_history(fsm_t *fsm)
139 | *
140 | * DESCRIPTION
141 | * Displays history of the state transitions.
142 | *
143 | * INPUT PARAMETERS
144 | * *fsm - handle of the state machine
145 | *
146 | * OUTPUT PARAMETERS
147 | * none
148 | *
149 | * RETURN VALUE
150 | * none
151 | *
152 | */
153 | void
154 | fsm_show_history (fsm_t *fsm)
155 | {
156 | uint32_t i, j;
157 | fsm_history_t *history_ptr;
158 |
159 | state_description_t *p2state_description;
160 | event_description_t *p2event_description;
161 |
162 | if (fsm == NULL) {
163 | return;
164 | }
165 |
166 | if (fsm->tag != FSM_TAG) {
167 | return;
168 | }
169 |
170 | p2state_description = fsm->state_description_table;
171 | p2event_description = fsm->event_description_table;
172 |
173 | printf("\nFSM: %s History \n", fsm->fsm_name);
174 | printf("Current State / Event / New State / rc \n");
175 | printf("------------------------------------------------\n");
176 |
177 | j = fsm->history_index;
178 | for (i=0; ihistory[i];
184 |
185 | if (history_ptr->stateID == FSM_NULL_STATE_ID) {
186 | continue;
187 | }
188 |
189 | printf(" %u-%s / %u-%s / %u-%s / %u\n",
190 | history_ptr->prevStateID,
191 | p2state_description[history_ptr->prevStateID].description,
192 | history_ptr->eventID,
193 | p2event_description[history_ptr->eventID].description,
194 | history_ptr->stateID,
195 | p2state_description[history_ptr->stateID].description,
196 | history_ptr->handler_rc);
197 |
198 | if (j==0) {
199 | j=FSM_HISTORY;
200 | }
201 | j--;
202 | }
203 |
204 | printf("\n");
205 | return;
206 | }
207 |
208 |
209 | /**
210 | * NAME
211 | * fsm_get_state
212 | *
213 | * SYNOPSIS
214 | * #include "fsm.h"
215 | * RC_FSM_t
216 | * fsm_get_state(fsm_t *fsm, uint32_t*p2state)
217 | *
218 | * DESCRIPTION
219 | * Function to return the current state.
220 | *
221 | * INPUT PARAMETERS
222 | * *fsm - state machine handle
223 | *
224 | * p2state - Pointer to a state variable to be updated.
225 | *
226 | * OUTPUT PARAMETERS
227 | * none
228 | *
229 | * RETURN VALUE
230 | * RC_FSM_OK
231 | * error otherwise
232 | *
233 | */
234 | RC_FSM_t
235 | fsm_get_state (fsm_t *fsm, uint32_t *p2state)
236 | {
237 | if (fsm == NULL) {
238 | return (RC_FSM_NULL);
239 | }
240 |
241 | if (fsm->tag != FSM_TAG) {
242 | return (RC_FSM_INVALID_HANDLE);
243 | }
244 |
245 | *p2state = fsm->curr_state;
246 | return (RC_FSM_OK);
247 | }
248 |
249 |
250 | /**
251 | * NAME
252 | * fsm_set_exception_state
253 | *
254 | * SYNOPSIS
255 | * #include "fsm.h"
256 | * RC_FSM_t
257 | * fsm_set_exception_state(fsm_t *fsm,
258 | * uint32_t exception_state)
259 | *
260 | * DESCRIPTION
261 | * To be called from an event handler to alter
262 | * the next state from the event table when an
263 | * exception has been detected
264 | *
265 | * INPUT PARAMETERS
266 | * *fsm - state machine handle
267 | *
268 | * exception_state - New state to be transitioned
269 | * when the event handler returns.
270 | *
271 | * OUTPUT PARAMETERS
272 | * none
273 | *
274 | * RETURN VALUE
275 | * RC_FSM_OK
276 | * error otherwise
277 | *
278 | */
279 | RC_FSM_t
280 | fsm_set_exception_state (fsm_t *fsm, uint32_t exception_state)
281 | {
282 | if (fsm == NULL) {
283 | return (RC_FSM_NULL);
284 | }
285 |
286 | if (fsm->tag != FSM_TAG) {
287 | return (RC_FSM_INVALID_HANDLE);
288 | }
289 |
290 | /*
291 | * Change the state of this FSM to the requested state.
292 | */
293 | if (exception_state > fsm->number_states-1) {
294 | return (RC_FSM_INVALID_STATE);
295 | }
296 |
297 | fsm->exception_state = exception_state;
298 | fsm->exception_state_indicator = TRUE;
299 | return (RC_FSM_OK);
300 | }
301 |
302 |
303 | /**
304 | * NAME
305 | * fsm_destroy
306 | *
307 | * SYNOPSIS
308 | * #include "fsm.h"
309 | * RC_FSM_t
310 | * fsm_destroy(fsm_t **fsm)
311 | *
312 | * DESCRIPTION
313 | * Destroys the specified state machine.
314 | *
315 | * INPUT PARAMETERS
316 | * fsm - pointer to fsm handle
317 | *
318 | * OUTPUT PARAMETERS
319 | * fsm - is nulled
320 | *
321 | * RETURN VALUE
322 | * RC_FSM_OK
323 | * error otherwise
324 | *
325 | */
326 | RC_FSM_t
327 | fsm_destroy (fsm_t **fsm)
328 | {
329 | fsm_t *p2fsm;
330 |
331 | if (fsm == NULL) {
332 | return (RC_FSM_NULL);
333 | }
334 |
335 | p2fsm = *fsm;
336 | if (p2fsm->tag != FSM_TAG) {
337 | return (RC_FSM_INVALID_HANDLE);
338 | }
339 |
340 | free(p2fsm->history);
341 | *fsm = NULL;
342 | free(p2fsm);
343 | return (RC_FSM_OK);
344 | }
345 |
346 |
347 | /**
348 | * NAME
349 | * fsm_create
350 | *
351 | * SYNOPSIS
352 | * #include "fsm.h"
353 | * RC_FSM_t
354 | * fsm_create(fsm_t **fsm,
355 | * char *name,
356 | * uint32_t initial_state,
357 | * state_description_t *state_description_table,
358 | * event_description_t *event_description_table,
359 | * state_tuple_t *state_table)
360 | *
361 | * DESCRIPTION
362 | * Creates and initializes a state machine. The
363 | * initial state is specified by the user.
364 | *
365 | * INPUT PARAMETERS
366 | * fsm pointer to fsm handle to be returned
367 | * once created
368 | *
369 | * name pointer to fsm name
370 | *
371 | * initial_state Initial start state
372 | *
373 | * state_description_table
374 | * Pointer to the user table which
375 | * provides a description of each state.
376 | * The table is used when displaying
377 | * state info to the console.
378 | *
379 | * event_description_table
380 | * Pointer to the user table which
381 | * provides a description of each event.
382 | * The table is used when displaying
383 | * state info to the console.
384 | *
385 | * state_table Pointer to user defined state
386 | * table. The state table is indexed
387 | * by the normalized state ID, 0, 1, ...
388 | * Each state table tuple must reference
389 | * an event table.
390 | *
391 | * OUTPUT PARAMETERS
392 | * none
393 | *
394 | * RETURN VALUE
395 | * RC_FSM_OK
396 | * error otherwise
397 | *
398 | */
399 | RC_FSM_t
400 | fsm_create (fsm_t **fsm,
401 | char *name,
402 | uint32_t initial_state,
403 | state_description_t *state_description_table,
404 | event_description_t *event_description_table,
405 | state_tuple_t *state_table)
406 | {
407 | fsm_t *temp_fsm;
408 | uint32_t i;
409 | uint32_t j;
410 | state_tuple_t *state_ptr;
411 | event_tuple_t *event_ptr;
412 |
413 |
414 | if (fsm == NULL) {
415 | return (RC_FSM_NULL);
416 | }
417 |
418 | if (state_description_table == NULL) {
419 | return (RC_FSM_INVALID_STATE_TABLE);
420 | }
421 |
422 | if (event_description_table == NULL) {
423 | return (RC_FSM_INVALID_EVENT_TABLE);
424 | }
425 |
426 | if (state_table == NULL) {
427 | return (RC_FSM_INVALID_STATE_TABLE);
428 | }
429 |
430 |
431 | /*
432 | * allocate memory to manage state machine
433 | */
434 | temp_fsm = (fsm_t *)malloc( sizeof(fsm_t) );
435 | if (temp_fsm == NULL) {
436 | return (RC_FSM_NO_RESOURCES);
437 | }
438 |
439 | /*
440 | * default a name if needed
441 | */
442 | if (name) {
443 | strncpy(temp_fsm->fsm_name, name, FSM_NAME_LEN);
444 | } else {
445 | strncpy(temp_fsm->fsm_name, "State Machine", FSM_NAME_LEN);
446 | }
447 |
448 | /*
449 | * initialize fsm config parms
450 | */
451 | temp_fsm->tag = FSM_TAG; /* for sanity cchecks */
452 |
453 | temp_fsm->curr_state = initial_state;
454 | temp_fsm->next_state = initial_state;
455 | temp_fsm->exception_state_indicator = FALSE;
456 |
457 | /* save the event description table */
458 | temp_fsm->state_description_table = state_description_table;
459 | temp_fsm->event_description_table = event_description_table;
460 |
461 | /* save the pointer to the state table */
462 | temp_fsm->state_table = state_table;
463 |
464 | /*
465 | * Find the size of the state table
466 | */
467 | temp_fsm->number_states = 0;
468 | for (i=0; inumber_states++;
480 | } else {
481 | free(temp_fsm);
482 | return (RC_FSM_INVALID_STATE_TABLE);
483 | }
484 | } else {
485 | break;
486 | }
487 | }
488 | if (temp_fsm->number_states < 1 ||
489 | temp_fsm->number_states > FSM_MAX_STATES-1) {
490 | free(temp_fsm);
491 | return (RC_FSM_INVALID_STATE_TABLE);
492 | }
493 | #if 0
494 | printf("number states=%u \n", temp_fsm->number_states);
495 | #endif
496 |
497 | /*
498 | * check zero based range for state
499 | */
500 | if (initial_state > temp_fsm->number_states-1) {
501 | free(temp_fsm);
502 | return (RC_FSM_INVALID_STATE);
503 | }
504 |
505 |
506 | /*
507 | * Find the size of the event table
508 | */
509 | temp_fsm->number_events = 0;
510 | for (i=0; inumber_events++;
525 | }
526 | if (temp_fsm->number_events < 1 ||
527 | temp_fsm->number_events > FSM_MAX_EVENTS-1) {
528 | free(temp_fsm);
529 | return (RC_FSM_INVALID_EVENT_TABLE);
530 | }
531 | #if 0
532 | printf("number events=%u \n", temp_fsm->number_events);
533 | #endif
534 |
535 | /*
536 | * Now verify the state table - event table relationships and
537 | * that the IDs are normalized.
538 | */
539 | for (i=0; inumber_states; i++) {
540 | state_ptr = &temp_fsm->state_table[i];
541 |
542 | event_ptr = state_ptr->p2event_tuple;
543 |
544 | for (j=0; jnumber_events; j++) {
545 | #if 0
546 | printf(" %u eventID=%u \n",
547 | j,
548 | event_ptr[j].eventID);
549 | #endif
550 | if (j != event_ptr[j].eventID) {
551 | free(temp_fsm);
552 | return (RC_FSM_INVALID_EVENT_TABLE);
553 | }
554 | }
555 | }
556 |
557 | /*
558 | * allocate memory for history
559 | */
560 | temp_fsm->history = malloc(FSM_HISTORY * sizeof(fsm_history_t));
561 | if (temp_fsm->history == NULL) {
562 | free(temp_fsm);
563 | return (RC_FSM_NO_RESOURCES);
564 | }
565 |
566 | /*
567 | * initialize history buffer
568 | */
569 | temp_fsm->history_index = 0;
570 | for (i=0; ihistory[i].prevStateID = FSM_NULL_STATE_ID;
572 | temp_fsm->history[i].stateID = FSM_NULL_STATE_ID;
573 | temp_fsm->history[i].eventID = FSM_NULL_EVENT_ID;
574 | temp_fsm->history[i].handler_rc = RC_FSM_NULL;
575 | }
576 |
577 | /* return handle to the user */
578 | *fsm = temp_fsm;
579 | return (RC_FSM_OK);
580 | }
581 |
582 |
583 | /*
584 | * internal routine to record a state transition history
585 | */
586 | static void
587 | fsm_record_history (fsm_t *fsm,
588 | uint32_t normalized_event,
589 | uint32_t nextState,
590 | RC_FSM_t handler_rc)
591 | {
592 | fsm_history_t *history_ptr;
593 |
594 | /*
595 | * get next index to record a little history
596 | */
597 | fsm->history_index = (fsm->history_index+1)%FSM_HISTORY;
598 |
599 | /*
600 | * Get a local pointer to the history buffer to populate
601 | */
602 | history_ptr = &fsm->history[fsm->history_index];
603 |
604 | history_ptr->prevStateID = fsm->curr_state;
605 | history_ptr->stateID = nextState;
606 | history_ptr->eventID = normalized_event;
607 | history_ptr->handler_rc = handler_rc;
608 | return;
609 | }
610 |
611 |
612 | /**
613 | * NAME
614 | * fsm_engine
615 | *
616 | * SYNOPSIS
617 | * #include "fsm.h"
618 | * RC_FSM_t
619 | * fsm_engine(fsm_t *fsm,
620 | * uint32_t normalized_event,
621 | * void *p2event_buffer,
622 | * void *p2parm)
623 | *
624 | * DESCRIPTION
625 | * Drives a state machine defined by normalized event
626 | * and a states.
627 | *
628 | * INPUT PARAMETERS
629 | * *fsm state machine handle
630 | *
631 | * normalized_event the event id to process
632 | *
633 | * *p2event pointer to the raw event which
634 | * is driving the event. This is
635 | * passed through to the handler.
636 | *
637 | * *p2parm pointer parameter that is simply
638 | * passed through to each event
639 | * handler.
640 | *
641 | * OUTPUT PARAMETERS
642 | * none
643 | *
644 | * RETURN VALUE
645 | * RC_FSM_OK
646 | * error otherwise
647 | *
648 | */
649 | RC_FSM_t
650 | fsm_engine (fsm_t *fsm,
651 | uint32_t normalized_event,
652 | void *p2event_buffer,
653 | void *p2parm)
654 | {
655 | event_tuple_t *event_ptr;
656 | event_cb_t event_handler;
657 | RC_FSM_t rc;
658 |
659 | /*
660 | * verify pointers & handles are valid
661 | */
662 | if (fsm == NULL) {
663 | return (RC_FSM_NULL);
664 | }
665 |
666 | if (fsm->tag != FSM_TAG) {
667 | return (RC_FSM_INVALID_HANDLE);
668 | }
669 |
670 | /*
671 | * verify that "event id" is valid: [0-(number_events-1)]
672 | */
673 | if (normalized_event > fsm->number_events-1) {
674 | fsm_record_history(fsm, normalized_event,
675 | fsm->curr_state, RC_FSM_INVALID_EVENT);
676 | return (RC_FSM_INVALID_EVENT);
677 | }
678 |
679 | /*
680 | * Index into the state table to get to the event table
681 | * so we can get the next state and the event handler.
682 | */
683 | event_ptr =
684 | &fsm->state_table[fsm->curr_state].p2event_tuple[normalized_event];
685 |
686 | /*
687 | * If the handler was NULL then we have a quiet event ,
688 | * no processing possible.
689 | */
690 | event_handler = event_ptr->event_handler;
691 | if (event_handler == NULL) {
692 | fsm_record_history(fsm,
693 | normalized_event,
694 | event_ptr->next_state,
695 | RC_FSM_INVALID_EVENT_HANDLER);
696 | return (RC_FSM_OK);
697 | }
698 |
699 | rc = (*event_handler)(p2event_buffer, p2parm);
700 |
701 | /*
702 | * Event handler wants to stop processing events. There is no access
703 | * to the fsm data structure in case the state machine has ended.
704 | */
705 | if (rc == RC_FSM_STOP_PROCESSING) {
706 | return (rc);
707 | }
708 |
709 | /*
710 | * If the return code is not OK, simply record the
711 | * result without a state change.
712 | */
713 | if (rc != RC_FSM_OK) {
714 | fsm_record_history(fsm, normalized_event,
715 | event_ptr->next_state, rc);
716 | return (rc);
717 | }
718 |
719 | /*
720 | * If the exception state indicator is set, use the exception
721 | * state provided by the event handler. This is an unexpected
722 | * state transition. Else use the event table next state.
723 | */
724 | if (fsm->exception_state_indicator) {
725 | /*
726 | * event handler detected an exception to the state transition
727 | */
728 | fsm->exception_state_indicator = FALSE;
729 | fsm->next_state = fsm->exception_state;
730 |
731 | } else {
732 | /*
733 | * we have a valid event table transition
734 | */
735 | fsm->next_state = event_ptr->next_state;
736 | }
737 |
738 | /*
739 | * Validate the next state from the event table
740 | * knowing that the event id is 0,1,2,...
741 | * Then use the event id to directly index into the state
742 | * table to set the next state.
743 | */
744 | if (fsm->next_state > (fsm->number_states-1)) {
745 | fsm_record_history(fsm,
746 | normalized_event,
747 | fsm->next_state,
748 | RC_FSM_INVALID_STATE);
749 | rc = RC_FSM_INVALID_STATE;
750 |
751 | } else {
752 |
753 | /* record a bit of history. */
754 | fsm_record_history(fsm,
755 | normalized_event,
756 | fsm->next_state,
757 | rc);
758 |
759 | /*
760 | * and update the current state completing the transition
761 | */
762 | fsm->curr_state = fsm->next_state;
763 | }
764 | return (rc);
765 | }
766 |
767 |
--------------------------------------------------------------------------------