fsm.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* $Id: fsm.h,v 1.1.1.1 2002/03/13 19:33:09 mschwide Exp $
  2. */
  3. #ifndef _FSM_H_
  4. #define _FSM_H_
  5. #include <linux/kernel.h>
  6. #include <linux/types.h>
  7. #include <linux/timer.h>
  8. #include <linux/time.h>
  9. #include <linux/slab.h>
  10. #include <linux/sched.h>
  11. #include <linux/string.h>
  12. #include <asm/atomic.h>
  13. /**
  14. * Define this to get debugging messages.
  15. */
  16. #define FSM_DEBUG 0
  17. /**
  18. * Define this to get debugging massages for
  19. * timer handling.
  20. */
  21. #define FSM_TIMER_DEBUG 0
  22. /**
  23. * Define these to record a history of
  24. * Events/Statechanges and print it if a
  25. * action_function is not found.
  26. */
  27. #define FSM_DEBUG_HISTORY 0
  28. #define FSM_HISTORY_SIZE 40
  29. struct fsm_instance_t;
  30. /**
  31. * Definition of an action function, called by a FSM
  32. */
  33. typedef void (*fsm_function_t)(struct fsm_instance_t *, int, void *);
  34. /**
  35. * Internal jump table for a FSM
  36. */
  37. typedef struct {
  38. fsm_function_t *jumpmatrix;
  39. int nr_events;
  40. int nr_states;
  41. const char **event_names;
  42. const char **state_names;
  43. } fsm;
  44. #if FSM_DEBUG_HISTORY
  45. /**
  46. * Element of State/Event history used for debugging.
  47. */
  48. typedef struct {
  49. int state;
  50. int event;
  51. } fsm_history;
  52. #endif
  53. /**
  54. * Representation of a FSM
  55. */
  56. typedef struct fsm_instance_t {
  57. fsm *f;
  58. atomic_t state;
  59. char name[16];
  60. void *userdata;
  61. int userint;
  62. #if FSM_DEBUG_HISTORY
  63. int history_index;
  64. int history_size;
  65. fsm_history history[FSM_HISTORY_SIZE];
  66. #endif
  67. } fsm_instance;
  68. /**
  69. * Description of a state-event combination
  70. */
  71. typedef struct {
  72. int cond_state;
  73. int cond_event;
  74. fsm_function_t function;
  75. } fsm_node;
  76. /**
  77. * Description of a FSM Timer.
  78. */
  79. typedef struct {
  80. fsm_instance *fi;
  81. struct timer_list tl;
  82. int expire_event;
  83. void *event_arg;
  84. } fsm_timer;
  85. /**
  86. * Creates an FSM
  87. *
  88. * @param name Name of this instance for logging purposes.
  89. * @param state_names An array of names for all states for logging purposes.
  90. * @param event_names An array of names for all events for logging purposes.
  91. * @param nr_states Number of states for this instance.
  92. * @param nr_events Number of events for this instance.
  93. * @param tmpl An array of fsm_nodes, describing this FSM.
  94. * @param tmpl_len Length of the describing array.
  95. * @param order Parameter for allocation of the FSM data structs.
  96. */
  97. extern fsm_instance *
  98. init_fsm(char *name, const char **state_names,
  99. const char **event_names,
  100. int nr_states, int nr_events, const fsm_node *tmpl,
  101. int tmpl_len, int order);
  102. /**
  103. * Releases an FSM
  104. *
  105. * @param fi Pointer to an FSM, previously created with init_fsm.
  106. */
  107. extern void kfree_fsm(fsm_instance *fi);
  108. #if FSM_DEBUG_HISTORY
  109. extern void
  110. fsm_print_history(fsm_instance *fi);
  111. extern void
  112. fsm_record_history(fsm_instance *fi, int state, int event);
  113. #endif
  114. /**
  115. * Emits an event to a FSM.
  116. * If an action function is defined for the current state/event combination,
  117. * this function is called.
  118. *
  119. * @param fi Pointer to FSM which should receive the event.
  120. * @param event The event do be delivered.
  121. * @param arg A generic argument, handed to the action function.
  122. *
  123. * @return 0 on success,
  124. * 1 if current state or event is out of range
  125. * !0 if state and event in range, but no action defined.
  126. */
  127. extern __inline__ int
  128. fsm_event(fsm_instance *fi, int event, void *arg)
  129. {
  130. fsm_function_t r;
  131. int state = atomic_read(&fi->state);
  132. if ((state >= fi->f->nr_states) ||
  133. (event >= fi->f->nr_events) ) {
  134. printk(KERN_ERR "fsm(%s): Invalid state st(%ld/%ld) ev(%d/%ld)\n",
  135. fi->name, (long)state,(long)fi->f->nr_states, event,
  136. (long)fi->f->nr_events);
  137. #if FSM_DEBUG_HISTORY
  138. fsm_print_history(fi);
  139. #endif
  140. return 1;
  141. }
  142. r = fi->f->jumpmatrix[fi->f->nr_states * event + state];
  143. if (r) {
  144. #if FSM_DEBUG
  145. printk(KERN_DEBUG "fsm(%s): state %s event %s\n",
  146. fi->name, fi->f->state_names[state],
  147. fi->f->event_names[event]);
  148. #endif
  149. #if FSM_DEBUG_HISTORY
  150. fsm_record_history(fi, state, event);
  151. #endif
  152. r(fi, event, arg);
  153. return 0;
  154. } else {
  155. #if FSM_DEBUG || FSM_DEBUG_HISTORY
  156. printk(KERN_DEBUG "fsm(%s): no function for event %s in state %s\n",
  157. fi->name, fi->f->event_names[event],
  158. fi->f->state_names[state]);
  159. #endif
  160. #if FSM_DEBUG_HISTORY
  161. fsm_print_history(fi);
  162. #endif
  163. return !0;
  164. }
  165. }
  166. /**
  167. * Modifies the state of an FSM.
  168. * This does <em>not</em> trigger an event or calls an action function.
  169. *
  170. * @param fi Pointer to FSM
  171. * @param state The new state for this FSM.
  172. */
  173. extern __inline__ void
  174. fsm_newstate(fsm_instance *fi, int newstate)
  175. {
  176. atomic_set(&fi->state,newstate);
  177. #if FSM_DEBUG_HISTORY
  178. fsm_record_history(fi, newstate, -1);
  179. #endif
  180. #if FSM_DEBUG
  181. printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name,
  182. fi->f->state_names[newstate]);
  183. #endif
  184. }
  185. /**
  186. * Retrieves the state of an FSM
  187. *
  188. * @param fi Pointer to FSM
  189. *
  190. * @return The current state of the FSM.
  191. */
  192. extern __inline__ int
  193. fsm_getstate(fsm_instance *fi)
  194. {
  195. return atomic_read(&fi->state);
  196. }
  197. /**
  198. * Retrieves the name of the state of an FSM
  199. *
  200. * @param fi Pointer to FSM
  201. *
  202. * @return The current state of the FSM in a human readable form.
  203. */
  204. extern const char *fsm_getstate_str(fsm_instance *fi);
  205. /**
  206. * Initializes a timer for an FSM.
  207. * This prepares an fsm_timer for usage with fsm_addtimer.
  208. *
  209. * @param fi Pointer to FSM
  210. * @param timer The timer to be initialized.
  211. */
  212. extern void fsm_settimer(fsm_instance *fi, fsm_timer *);
  213. /**
  214. * Clears a pending timer of an FSM instance.
  215. *
  216. * @param timer The timer to clear.
  217. */
  218. extern void fsm_deltimer(fsm_timer *timer);
  219. /**
  220. * Adds and starts a timer to an FSM instance.
  221. *
  222. * @param timer The timer to be added. The field fi of that timer
  223. * must have been set to point to the instance.
  224. * @param millisec Duration, after which the timer should expire.
  225. * @param event Event, to trigger if timer expires.
  226. * @param arg Generic argument, provided to expiry function.
  227. *
  228. * @return 0 on success, -1 if timer is already active.
  229. */
  230. extern int fsm_addtimer(fsm_timer *timer, int millisec, int event, void *arg);
  231. /**
  232. * Modifies a timer of an FSM.
  233. *
  234. * @param timer The timer to modify.
  235. * @param millisec Duration, after which the timer should expire.
  236. * @param event Event, to trigger if timer expires.
  237. * @param arg Generic argument, provided to expiry function.
  238. */
  239. extern void fsm_modtimer(fsm_timer *timer, int millisec, int event, void *arg);
  240. #endif /* _FSM_H_ */