diff options
author | Karsten Keil <kkeil@suse.de> | 2008-07-26 19:54:58 -0400 |
---|---|---|
committer | Karsten Keil <kkeil@suse.de> | 2008-07-26 19:54:58 -0400 |
commit | 1b2b03f8e514e4f68e293846ba511a948b80243c (patch) | |
tree | 5ffb07d532afca95170ea0615bb74af78b0d0483 /drivers/isdn/mISDN/fsm.c | |
parent | 04578dd330f1ec6bc9c4233833bee0d0ca73ff09 (diff) |
Add mISDN core files
Add mISDN core files
Signed-off-by: Karsten Keil <kkeil@suse.de>
Diffstat (limited to 'drivers/isdn/mISDN/fsm.c')
-rw-r--r-- | drivers/isdn/mISDN/fsm.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c new file mode 100644 index 000000000000..b5d6553f2dc8 --- /dev/null +++ b/drivers/isdn/mISDN/fsm.c | |||
@@ -0,0 +1,183 @@ | |||
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 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/string.h> | ||
25 | #include "fsm.h" | ||
26 | |||
27 | #define FSM_TIMER_DEBUG 0 | ||
28 | |||
29 | void | ||
30 | mISDN_FsmNew(struct Fsm *fsm, | ||
31 | struct FsmNode *fnlist, int fncount) | ||
32 | { | ||
33 | int i; | ||
34 | |||
35 | fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count * | ||
36 | fsm->event_count, GFP_KERNEL); | ||
37 | |||
38 | for (i = 0; i < fncount; i++) | ||
39 | if ((fnlist[i].state >= fsm->state_count) || | ||
40 | (fnlist[i].event >= fsm->event_count)) { | ||
41 | printk(KERN_ERR | ||
42 | "mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n", | ||
43 | i, (long)fnlist[i].state, (long)fsm->state_count, | ||
44 | (long)fnlist[i].event, (long)fsm->event_count); | ||
45 | } else | ||
46 | fsm->jumpmatrix[fsm->state_count * fnlist[i].event + | ||
47 | fnlist[i].state] = (FSMFNPTR) fnlist[i].routine; | ||
48 | } | ||
49 | EXPORT_SYMBOL(mISDN_FsmNew); | ||
50 | |||
51 | void | ||
52 | mISDN_FsmFree(struct Fsm *fsm) | ||
53 | { | ||
54 | kfree((void *) fsm->jumpmatrix); | ||
55 | } | ||
56 | EXPORT_SYMBOL(mISDN_FsmFree); | ||
57 | |||
58 | int | ||
59 | mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg) | ||
60 | { | ||
61 | FSMFNPTR r; | ||
62 | |||
63 | if ((fi->state >= fi->fsm->state_count) || | ||
64 | (event >= fi->fsm->event_count)) { | ||
65 | printk(KERN_ERR | ||
66 | "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n", | ||
67 | (long)fi->state, (long)fi->fsm->state_count, event, | ||
68 | (long)fi->fsm->event_count); | ||
69 | return 1; | ||
70 | } | ||
71 | r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state]; | ||
72 | if (r) { | ||
73 | if (fi->debug) | ||
74 | fi->printdebug(fi, "State %s Event %s", | ||
75 | fi->fsm->strState[fi->state], | ||
76 | fi->fsm->strEvent[event]); | ||
77 | r(fi, event, arg); | ||
78 | return 0; | ||
79 | } else { | ||
80 | if (fi->debug) | ||
81 | fi->printdebug(fi, "State %s Event %s no action", | ||
82 | fi->fsm->strState[fi->state], | ||
83 | fi->fsm->strEvent[event]); | ||
84 | return 1; | ||
85 | } | ||
86 | } | ||
87 | EXPORT_SYMBOL(mISDN_FsmEvent); | ||
88 | |||
89 | void | ||
90 | mISDN_FsmChangeState(struct FsmInst *fi, int newstate) | ||
91 | { | ||
92 | fi->state = newstate; | ||
93 | if (fi->debug) | ||
94 | fi->printdebug(fi, "ChangeState %s", | ||
95 | fi->fsm->strState[newstate]); | ||
96 | } | ||
97 | EXPORT_SYMBOL(mISDN_FsmChangeState); | ||
98 | |||
99 | static void | ||
100 | FsmExpireTimer(struct FsmTimer *ft) | ||
101 | { | ||
102 | #if FSM_TIMER_DEBUG | ||
103 | if (ft->fi->debug) | ||
104 | ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); | ||
105 | #endif | ||
106 | mISDN_FsmEvent(ft->fi, ft->event, ft->arg); | ||
107 | } | ||
108 | |||
109 | void | ||
110 | mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft) | ||
111 | { | ||
112 | ft->fi = fi; | ||
113 | ft->tl.function = (void *) FsmExpireTimer; | ||
114 | ft->tl.data = (long) ft; | ||
115 | #if FSM_TIMER_DEBUG | ||
116 | if (ft->fi->debug) | ||
117 | ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft); | ||
118 | #endif | ||
119 | init_timer(&ft->tl); | ||
120 | } | ||
121 | EXPORT_SYMBOL(mISDN_FsmInitTimer); | ||
122 | |||
123 | void | ||
124 | mISDN_FsmDelTimer(struct FsmTimer *ft, int where) | ||
125 | { | ||
126 | #if FSM_TIMER_DEBUG | ||
127 | if (ft->fi->debug) | ||
128 | ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d", | ||
129 | (long) ft, where); | ||
130 | #endif | ||
131 | del_timer(&ft->tl); | ||
132 | } | ||
133 | EXPORT_SYMBOL(mISDN_FsmDelTimer); | ||
134 | |||
135 | int | ||
136 | mISDN_FsmAddTimer(struct FsmTimer *ft, | ||
137 | int millisec, int event, void *arg, int where) | ||
138 | { | ||
139 | |||
140 | #if FSM_TIMER_DEBUG | ||
141 | if (ft->fi->debug) | ||
142 | ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d", | ||
143 | (long) ft, millisec, where); | ||
144 | #endif | ||
145 | |||
146 | if (timer_pending(&ft->tl)) { | ||
147 | if (ft->fi->debug) { | ||
148 | printk(KERN_WARNING | ||
149 | "mISDN_FsmAddTimer: timer already active!\n"); | ||
150 | ft->fi->printdebug(ft->fi, | ||
151 | "mISDN_FsmAddTimer already active!"); | ||
152 | } | ||
153 | return -1; | ||
154 | } | ||
155 | init_timer(&ft->tl); | ||
156 | ft->event = event; | ||
157 | ft->arg = arg; | ||
158 | ft->tl.expires = jiffies + (millisec * HZ) / 1000; | ||
159 | add_timer(&ft->tl); | ||
160 | return 0; | ||
161 | } | ||
162 | EXPORT_SYMBOL(mISDN_FsmAddTimer); | ||
163 | |||
164 | void | ||
165 | mISDN_FsmRestartTimer(struct FsmTimer *ft, | ||
166 | int millisec, int event, void *arg, int where) | ||
167 | { | ||
168 | |||
169 | #if FSM_TIMER_DEBUG | ||
170 | if (ft->fi->debug) | ||
171 | ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d", | ||
172 | (long) ft, millisec, where); | ||
173 | #endif | ||
174 | |||
175 | if (timer_pending(&ft->tl)) | ||
176 | del_timer(&ft->tl); | ||
177 | init_timer(&ft->tl); | ||
178 | ft->event = event; | ||
179 | ft->arg = arg; | ||
180 | ft->tl.expires = jiffies + (millisec * HZ) / 1000; | ||
181 | add_timer(&ft->tl); | ||
182 | } | ||
183 | EXPORT_SYMBOL(mISDN_FsmRestartTimer); | ||