brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 7c5c2ca Raw
177 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * finite state machine implementation4 *5 * Author       Karsten Keil <kkeil@novell.com>6 *7 * Thanks to    Jan den Ouden8 *              Fritz Elfert9 * Copyright 2008  by Karsten Keil <kkeil@novell.com>10 */11 12#include <linux/kernel.h>13#include <linux/slab.h>14#include <linux/module.h>15#include <linux/string.h>16#include "fsm.h"17 18#define FSM_TIMER_DEBUG 019 20int21mISDN_FsmNew(struct Fsm *fsm,22	     struct FsmNode *fnlist, int fncount)23{24	int i;25 26	fsm->jumpmatrix =27		kzalloc(array3_size(sizeof(FSMFNPTR), fsm->state_count,28				    fsm->event_count),29			GFP_KERNEL);30	if (fsm->jumpmatrix == NULL)31		return -ENOMEM;32 33	for (i = 0; i < fncount; i++)34		if ((fnlist[i].state >= fsm->state_count) ||35		    (fnlist[i].event >= fsm->event_count)) {36			printk(KERN_ERR37			       "mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n",38			       i, (long)fnlist[i].state, (long)fsm->state_count,39			       (long)fnlist[i].event, (long)fsm->event_count);40		} else41			fsm->jumpmatrix[fsm->state_count * fnlist[i].event +42					fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;43	return 0;44}45EXPORT_SYMBOL(mISDN_FsmNew);46 47void48mISDN_FsmFree(struct Fsm *fsm)49{50	kfree((void *) fsm->jumpmatrix);51}52EXPORT_SYMBOL(mISDN_FsmFree);53 54int55mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)56{57	FSMFNPTR r;58 59	if ((fi->state >= fi->fsm->state_count) ||60	    (event >= fi->fsm->event_count)) {61		printk(KERN_ERR62		       "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",63		       (long)fi->state, (long)fi->fsm->state_count, event,64		       (long)fi->fsm->event_count);65		return 1;66	}67	r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];68	if (r) {69		if (fi->debug)70			fi->printdebug(fi, "State %s Event %s",71				       fi->fsm->strState[fi->state],72				       fi->fsm->strEvent[event]);73		r(fi, event, arg);74		return 0;75	} else {76		if (fi->debug)77			fi->printdebug(fi, "State %s Event %s no action",78				       fi->fsm->strState[fi->state],79				       fi->fsm->strEvent[event]);80		return 1;81	}82}83EXPORT_SYMBOL(mISDN_FsmEvent);84 85void86mISDN_FsmChangeState(struct FsmInst *fi, int newstate)87{88	fi->state = newstate;89	if (fi->debug)90		fi->printdebug(fi, "ChangeState %s",91			       fi->fsm->strState[newstate]);92}93EXPORT_SYMBOL(mISDN_FsmChangeState);94 95static void96FsmExpireTimer(struct timer_list *t)97{98	struct FsmTimer *ft = from_timer(ft, t, tl);99#if FSM_TIMER_DEBUG100	if (ft->fi->debug)101		ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);102#endif103	mISDN_FsmEvent(ft->fi, ft->event, ft->arg);104}105 106void107mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)108{109	ft->fi = fi;110#if FSM_TIMER_DEBUG111	if (ft->fi->debug)112		ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);113#endif114	timer_setup(&ft->tl, FsmExpireTimer, 0);115}116EXPORT_SYMBOL(mISDN_FsmInitTimer);117 118void119mISDN_FsmDelTimer(struct FsmTimer *ft, int where)120{121#if FSM_TIMER_DEBUG122	if (ft->fi->debug)123		ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d",124				   (long) ft, where);125#endif126	del_timer(&ft->tl);127}128EXPORT_SYMBOL(mISDN_FsmDelTimer);129 130int131mISDN_FsmAddTimer(struct FsmTimer *ft,132		  int millisec, int event, void *arg, int where)133{134 135#if FSM_TIMER_DEBUG136	if (ft->fi->debug)137		ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",138				   (long) ft, millisec, where);139#endif140 141	if (timer_pending(&ft->tl)) {142		if (ft->fi->debug) {143			printk(KERN_WARNING144			       "mISDN_FsmAddTimer: timer already active!\n");145			ft->fi->printdebug(ft->fi,146					   "mISDN_FsmAddTimer already active!");147		}148		return -1;149	}150	ft->event = event;151	ft->arg = arg;152	ft->tl.expires = jiffies + (millisec * HZ) / 1000;153	add_timer(&ft->tl);154	return 0;155}156EXPORT_SYMBOL(mISDN_FsmAddTimer);157 158void159mISDN_FsmRestartTimer(struct FsmTimer *ft,160		      int millisec, int event, void *arg, int where)161{162 163#if FSM_TIMER_DEBUG164	if (ft->fi->debug)165		ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",166				   (long) ft, millisec, where);167#endif168 169	if (timer_pending(&ft->tl))170		del_timer(&ft->tl);171	ft->event = event;172	ft->arg = arg;173	ft->tl.expires = jiffies + (millisec * HZ) / 1000;174	add_timer(&ft->tl);175}176EXPORT_SYMBOL(mISDN_FsmRestartTimer);177