fsm.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * finite state machine implementation
  3. *
  4. * Author Karsten Keil <kkeil@novell.com>
  5. *
  6. * Thanks to Jan den Ouden
  7. * Fritz Elfert
  8. * Copyright 2008 by Karsten Keil <kkeil@novell.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/slab.h>
  22. #include <linux/module.h>
  23. #include <linux/string.h>
  24. #include "fsm.h"
  25. #define FSM_TIMER_DEBUG 0
  26. int
  27. mISDN_FsmNew(struct Fsm *fsm,
  28. struct FsmNode *fnlist, int fncount)
  29. {
  30. int i;
  31. fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
  32. fsm->event_count, GFP_KERNEL);
  33. if (fsm->jumpmatrix == NULL)
  34. return -ENOMEM;
  35. for (i = 0; i < fncount; i++)
  36. if ((fnlist[i].state >= fsm->state_count) ||
  37. (fnlist[i].event >= fsm->event_count)) {
  38. printk(KERN_ERR
  39. "mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n",
  40. i, (long)fnlist[i].state, (long)fsm->state_count,
  41. (long)fnlist[i].event, (long)fsm->event_count);
  42. } else
  43. fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
  44. fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
  45. return 0;
  46. }
  47. EXPORT_SYMBOL(mISDN_FsmNew);
  48. void
  49. mISDN_FsmFree(struct Fsm *fsm)
  50. {
  51. kfree((void *) fsm->jumpmatrix);
  52. }
  53. EXPORT_SYMBOL(mISDN_FsmFree);
  54. int
  55. mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
  56. {
  57. FSMFNPTR r;
  58. if ((fi->state >= fi->fsm->state_count) ||
  59. (event >= fi->fsm->event_count)) {
  60. printk(KERN_ERR
  61. "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
  62. (long)fi->state, (long)fi->fsm->state_count, event,
  63. (long)fi->fsm->event_count);
  64. return 1;
  65. }
  66. r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
  67. if (r) {
  68. if (fi->debug)
  69. fi->printdebug(fi, "State %s Event %s",
  70. fi->fsm->strState[fi->state],
  71. fi->fsm->strEvent[event]);
  72. r(fi, event, arg);
  73. return 0;
  74. } else {
  75. if (fi->debug)
  76. fi->printdebug(fi, "State %s Event %s no action",
  77. fi->fsm->strState[fi->state],
  78. fi->fsm->strEvent[event]);
  79. return 1;
  80. }
  81. }
  82. EXPORT_SYMBOL(mISDN_FsmEvent);
  83. void
  84. mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
  85. {
  86. fi->state = newstate;
  87. if (fi->debug)
  88. fi->printdebug(fi, "ChangeState %s",
  89. fi->fsm->strState[newstate]);
  90. }
  91. EXPORT_SYMBOL(mISDN_FsmChangeState);
  92. static void
  93. FsmExpireTimer(struct FsmTimer *ft)
  94. {
  95. #if FSM_TIMER_DEBUG
  96. if (ft->fi->debug)
  97. ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
  98. #endif
  99. mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
  100. }
  101. void
  102. mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
  103. {
  104. ft->fi = fi;
  105. #if FSM_TIMER_DEBUG
  106. if (ft->fi->debug)
  107. ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
  108. #endif
  109. setup_timer(&ft->tl, (void *)FsmExpireTimer, (long)ft);
  110. }
  111. EXPORT_SYMBOL(mISDN_FsmInitTimer);
  112. void
  113. mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
  114. {
  115. #if FSM_TIMER_DEBUG
  116. if (ft->fi->debug)
  117. ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d",
  118. (long) ft, where);
  119. #endif
  120. del_timer(&ft->tl);
  121. }
  122. EXPORT_SYMBOL(mISDN_FsmDelTimer);
  123. int
  124. mISDN_FsmAddTimer(struct FsmTimer *ft,
  125. int millisec, int event, void *arg, int where)
  126. {
  127. #if FSM_TIMER_DEBUG
  128. if (ft->fi->debug)
  129. ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",
  130. (long) ft, millisec, where);
  131. #endif
  132. if (timer_pending(&ft->tl)) {
  133. if (ft->fi->debug) {
  134. printk(KERN_WARNING
  135. "mISDN_FsmAddTimer: timer already active!\n");
  136. ft->fi->printdebug(ft->fi,
  137. "mISDN_FsmAddTimer already active!");
  138. }
  139. return -1;
  140. }
  141. init_timer(&ft->tl);
  142. ft->event = event;
  143. ft->arg = arg;
  144. ft->tl.expires = jiffies + (millisec * HZ) / 1000;
  145. add_timer(&ft->tl);
  146. return 0;
  147. }
  148. EXPORT_SYMBOL(mISDN_FsmAddTimer);
  149. void
  150. mISDN_FsmRestartTimer(struct FsmTimer *ft,
  151. int millisec, int event, void *arg, int where)
  152. {
  153. #if FSM_TIMER_DEBUG
  154. if (ft->fi->debug)
  155. ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",
  156. (long) ft, millisec, where);
  157. #endif
  158. if (timer_pending(&ft->tl))
  159. del_timer(&ft->tl);
  160. init_timer(&ft->tl);
  161. ft->event = event;
  162. ft->arg = arg;
  163. ft->tl.expires = jiffies + (millisec * HZ) / 1000;
  164. add_timer(&ft->tl);
  165. }
  166. EXPORT_SYMBOL(mISDN_FsmRestartTimer);