├── 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 | --------------------------------------------------------------------------------