--- /dev/null
+/* $Id: fsm.c,v 1.14.6.4 2001/09/23 22:24:47 kai Exp $
+ *
+ * Finite state machine
+ *
+ * Author Karsten Keil
+ * Copyright by Karsten Keil <keil@isdn4linux.de>
+ * by Kai Germaschewski <kai.germaschewski@gmx.de>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Thanks to Jan den Ouden
+ * Fritz Elfert
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include "isdn_fsm.h"
+
+int
+fsm_new(struct fsm *fsm)
+{
+ int i;
+ int size = sizeof(fsm_fn) * fsm->st_cnt * fsm->ev_cnt;
+
+ fsm->jumpmatrix = kmalloc(size, GFP_KERNEL);
+ if (!fsm->jumpmatrix)
+ return -ENOMEM;
+
+ memset(fsm->jumpmatrix, 0, size);
+
+ for (i = 0; i < fsm->fn_cnt; i++) {
+ if (fsm->fn_tbl[i].st >= fsm->st_cnt ||
+ fsm->fn_tbl[i].ev >= fsm->ev_cnt) {
+ printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n", i,
+ fsm->fn_tbl[i].st, fsm->st_cnt,
+ fsm->fn_tbl[i].ev, fsm->ev_cnt);
+ continue;
+ }
+ fsm->jumpmatrix[fsm->st_cnt * fsm->fn_tbl[i].ev + fsm->fn_tbl[i].st] = fsm->fn_tbl[i].routine;
+ }
+ return 0;
+}
+
+void
+fsm_free(struct fsm *fsm)
+{
+ kfree(fsm->jumpmatrix);
+}
+
+int
+fsm_event(struct fsm_inst *fi, int event, void *arg)
+{
+ fsm_fn fn;
+
+ if (fi->state >= fi->fsm->st_cnt ||
+ event >= fi->fsm->ev_cnt) {
+ printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n",
+ fi->state, fi->fsm->st_cnt,event,
+ fi->fsm->ev_cnt);
+ return -EINVAL;
+ }
+ fn = fi->fsm->jumpmatrix[fi->fsm->st_cnt * event + fi->state];
+ if (!fn) {
+ if (fi->debug)
+ fi->printdebug(fi, "State %s Event %s no routine",
+ fi->fsm->st_str[fi->state],
+ fi->fsm->ev_str[event]);
+ return -ESRCH;
+ }
+ if (fi->debug)
+ fi->printdebug(fi, "State %s Event %s",
+ fi->fsm->st_str[fi->state],
+ fi->fsm->ev_str[event]);
+
+ fn(fi, event, arg);
+ return 0;
+}
+
+void
+fsm_change_state(struct fsm_inst *fi, int newstate)
+{
+ fi->state = newstate;
+ if (fi->debug)
+ fi->printdebug(fi, "ChangeState %s",
+ fi->fsm->st_str[newstate]);
+}
+
+#if 0
+static void
+FsmExpireTimer(struct FsmTimer *ft)
+{
+#if FSM_TIMER_DEBUG
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
+#endif
+ FsmEvent(ft->fi, ft->event, ft->arg);
+}
+
+void
+FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
+{
+ ft->fi = fi;
+ ft->tl.function = (void *) FsmExpireTimer;
+ ft->tl.data = (long) ft;
+#if FSM_TIMER_DEBUG
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
+#endif
+ init_timer(&ft->tl);
+}
+
+void
+FsmDelTimer(struct FsmTimer *ft, int where)
+{
+#if FSM_TIMER_DEBUG
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
+#endif
+ del_timer(&ft->tl);
+}
+
+int
+FsmAddTimer(struct FsmTimer *ft,
+ int millisec, int event, void *arg, int where)
+{
+
+#if FSM_TIMER_DEBUG
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
+ (long) ft, millisec, where);
+#endif
+
+ if (timer_pending(&ft->tl)) {
+ printk(KERN_WARNING "FsmAddTimer: timer already active!\n");
+ ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
+ return -1;
+ }
+ init_timer(&ft->tl);
+ ft->event = event;
+ ft->arg = arg;
+ ft->tl.expires = jiffies + (millisec * HZ) / 1000;
+ add_timer(&ft->tl);
+ return 0;
+}
+
+void
+FsmRestartTimer(struct FsmTimer *ft,
+ int millisec, int event, void *arg, int where)
+{
+
+#if FSM_TIMER_DEBUG
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
+ (long) ft, millisec, where);
+#endif
+
+ if (timer_pending(&ft->tl))
+ del_timer(&ft->tl);
+ init_timer(&ft->tl);
+ ft->event = event;
+ ft->arg = arg;
+ ft->tl.expires = jiffies + (millisec * HZ) / 1000;
+ add_timer(&ft->tl);
+}
+#endif
#include "isdn_common.h"
#include "isdn_net.h"
#include "isdn_ppp.h"
+#include "isdn_fsm.h"
#define ISDN_NET_TX_TIMEOUT (20*HZ)
static void isdn_net_tasklet(unsigned long data);
static void isdn_net_dial_timer(unsigned long data);
static int isdn_init_netif(struct net_device *ndev);
+static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...);
+
+static struct fsm isdn_net_fsm;
+
+enum {
+ ST_NULL,
+ ST_OUT_WAIT_DCONN,
+ ST_OUT_WAIT_BCONN,
+ ST_IN_WAIT_DCONN,
+ ST_IN_WAIT_BCONN,
+ ST_ACTIVE,
+ ST_WAIT_BEFORE_CB,
+ ST_OUT_DIAL_WAIT,
+};
+
+static char *isdn_net_st_str[] = {
+ "ST_NULL",
+ "ST_OUT_WAIT_DCONN",
+ "ST_OUT_WAIT_BCONN",
+ "ST_IN_WAIT_DCONN",
+ "ST_IN_WAIT_BCONN",
+ "ST_ACTIVE",
+ "ST_WAIT_BEFORE_CB",
+ "ST_OUT_DIAL_WAIT",
+};
+
+enum {
+ EV_TIMER_INCOMING,
+ EV_TIMER_DIAL,
+ EV_TIMER_DIAL_WAIT,
+ EV_TIMER_CB_OUT,
+ EV_TIMER_CB_IN,
+ EV_TIMER_HUP,
+ EV_STAT_DCONN,
+ EV_STAT_BCONN,
+ EV_STAT_DHUP,
+ EV_STAT_BHUP,
+ EV_STAT_CINF,
+ EV_STAT_BSENT,
+};
+
+static char *isdn_net_ev_str[] = {
+ "EV_NET_TIMER_INCOMING",
+ "EV_NET_TIMER_DIAL",
+ "EV_NET_TIMER_DIAL_WAIT",
+ "EV_NET_TIMER_CB_OUT",
+ "EV_NET_TIMER_CB_IN",
+ "EV_NET_TIMER_HUP",
+ "EV_STAT_DCONN",
+ "EV_STAT_BCONN",
+ "EV_STAT_DHUP",
+ "EV_STAT_BHUP",
+ "EV_STAT_CINF",
+ "EV_STAT_BSENT",
+};
/* ====================================================================== */
/* Registration of ISDN network interface types */
idev->dial_timer.data = (unsigned long) idev;
idev->dial_timer.function = isdn_net_dial_timer;
+ idev->fi.fsm = &isdn_net_fsm;
+ idev->fi.state = ST_NULL;
+ idev->fi.debug = 1;
+ idev->fi.userdata = idev;
+ idev->fi.printdebug = isdn_net_dev_debug;
+
if (!mlp) {
/* Device shall be a master */
mlp = kmalloc(sizeof(*mlp), GFP_KERNEL);
if (retval)
isdn_BUG();
}
-
up(&sem);
+
+ // FIXME
+ isdn_net_lib_exit();
}
/* ====================================================================== */
/* call control state machine */
/* ====================================================================== */
-enum {
- ST_NULL,
- ST_OUT_WAIT_DCONN,
- ST_OUT_WAIT_BCONN,
- ST_IN_WAIT_DCONN,
- ST_IN_WAIT_BCONN,
- ST_ACTIVE,
- ST_WAIT_BEFORE_CB,
- ST_OUT_DIAL_WAIT,
-};
-
-/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
-enum {
- EV_NET_DIAL = 0x200,
- EV_NET_TIMER_INCOMING = 0x201,
- EV_NET_TIMER_DIAL = 0x203,
- EV_NET_TIMER_DIAL_WAIT = 0x204,
- EV_NET_TIMER_CB_OUT = 0x205,
- EV_NET_TIMER_CB_IN = 0x206,
- EV_NET_TIMER_HUP = 0x207,
-};
-
-static int init_dialout(isdn_net_dev *idev);
-static int do_dialout(isdn_net_dev *idev);
+static void dialout_first(struct fsm_inst *fi, int pr, void *arg);
+static void dialout_next(struct fsm_inst *fi, int pr, void *arg);
+// FIXME
int isdn_net_online(isdn_net_dev *idev)
{
- return idev->dialstate == ST_ACTIVE;
+ return idev->fi.state == ST_ACTIVE;
}
static void
skb_queue_purge(&idev->super_tx_queue);
- idev->dialstate = ST_NULL;
+ fsm_change_state(&idev->fi, ST_NULL);
isdn_slot_set_idev(idev->isdn_slot, NULL);
isdn_slot_free(idev->isdn_slot, ISDN_USAGE_NET);
goto err;
/* Initiate dialing */
- init_dialout(idev);
+ dialout_first(&idev->fi, 0, NULL); // FIXME
return 0;
isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL3, &cmd);
idev->dial_timer.expires = jiffies + mlp->dialtimeout;
- idev->dial_event = EV_NET_TIMER_INCOMING;
+ idev->dial_event = EV_TIMER_INCOMING;
add_timer(&idev->dial_timer);
- idev->dialstate = ST_IN_WAIT_DCONN;
+ fsm_change_state(&idev->fi, ST_IN_WAIT_DCONN);
}
int
/* Setup dialstate. */
idev->dial_timer.expires = jiffies + mlp->cbdelay;
- idev->dial_event = EV_NET_TIMER_CB_IN;
+ idev->dial_event = EV_TIMER_CB_IN;
add_timer(&idev->dial_timer);
- idev->dialstate = ST_WAIT_BEFORE_CB;
+ fsm_change_state(&idev->fi, ST_WAIT_BEFORE_CB);
/* Initiate dialing by returning 2 or 4 */
return (mlp->flags & ISDN_NET_CBHUP) ? 2 : 4;
/* Initiate dialout. */
-static int
-init_dialout(isdn_net_dev *idev)
+static void
+dialout_first(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
- if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF)
- return 1;
-
- if (list_empty(&mlp->phone[1]))
- return 1;
+ if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) {
+ isdn_net_unbind_channel(idev);
+ return;
+ }
+ if (list_empty(&mlp->phone[1])) {
+ isdn_net_unbind_channel(idev);
+ return;
+ }
idev->dial = 0;
idev->dialretry = 0;
- return do_dialout(idev);
+ dialout_next(fi, pr, arg);
}
/* Try dialing the next number. */
-static int
-do_dialout(isdn_net_dev *idev)
+static void
+dialout_next(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
struct dial_info dial = {
.l2_proto = mlp->l2_proto,
/* For outgoing callback, use cbdelay instead of dialtimeout */
if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) {
idev->dial_timer.expires = jiffies + mlp->cbdelay;
- idev->dial_event = EV_NET_TIMER_CB_OUT;
+ idev->dial_event = EV_TIMER_CB_OUT;
} else {
idev->dial_timer.expires = jiffies + mlp->dialtimeout;
- idev->dial_event = EV_NET_TIMER_DIAL;
+ idev->dial_event = EV_TIMER_DIAL;
}
- idev->dialstate = ST_OUT_WAIT_DCONN;
+ fsm_change_state(&idev->fi, ST_OUT_WAIT_DCONN);
add_timer(&idev->dial_timer);
/* Dial */
isdn_slot_dial(idev->isdn_slot, &dial);
- return 1;
}
/* If we didn't connect within dialtimeout, we give up for now
* and wait for dialwait jiffies before trying again.
*/
-static int
-dial_timeout(isdn_net_dev *idev)
+static void
+dial_timeout(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
isdn_ctrl cmd;
- idev->dialstate = ST_OUT_DIAL_WAIT;
+ fsm_change_state(&idev->fi, ST_OUT_DIAL_WAIT);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
/* get next phone number */
}
if (idev->dialretry >= mlp->dialmax) {
isdn_net_hangup(idev);
- return 1;
+ return;
}
- idev->dial_event = EV_NET_TIMER_DIAL_WAIT;
+ idev->dial_event = EV_TIMER_DIAL_WAIT;
mod_timer(&idev->dial_timer, jiffies + mlp->dialwait);
- return 1;
}
-static int
-isdn_net_connect_failure(isdn_net_dev *idev)
+static void
+connect_fail(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
+
del_timer(&idev->dial_timer);
isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: connection failed\n", idev->name);
isdn_net_unbind_channel(idev);
- return 1;
}
-static int
-isdn_net_out_dconn(isdn_net_dev *idev)
+static void
+out_dconn(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_ctrl cmd;
- idev->dialstate = ST_OUT_WAIT_BCONN;
+ fsm_change_state(&idev->fi, ST_OUT_WAIT_BCONN);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
- return 1;
}
-static int
-isdn_net_in_dconn(isdn_net_dev *idev)
+static void
+in_dconn(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_ctrl cmd;
- idev->dialstate = ST_IN_WAIT_BCONN;
+ fsm_change_state(&idev->fi, ST_IN_WAIT_BCONN);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
- return 1;
}
-static int
-isdn_net_bconn(isdn_net_dev *idev)
+static void
+bconn(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
- idev->dialstate = ST_ACTIVE;
+ fsm_change_state(&idev->fi, ST_ACTIVE);
if (mlp->onhtime) {
idev->huptimer = 0;
- idev->dial_event = EV_NET_TIMER_HUP;
+ idev->dial_event = EV_TIMER_HUP;
mod_timer(&idev->dial_timer, jiffies + HZ);
} else {
del_timer(&idev->dial_timer);
mlp->ops->connected(idev);
else
isdn_net_dev_wake_queue(idev);
-
- return 1;
}
/* Check if it's time for idle hang-up */
-static int
-isdn_net_check_hup(isdn_net_dev *idev)
+static void
+check_hup(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
dbg_net_dial("%s: huptimer %d onhtime %d chargetime %ld chargeint %d\n",
+ idev->chargeint - 2 * HZ))
goto mod_timer;
}
- if (idev->outgoing || mlp->hupflags & ISDN_INHUP)
- return isdn_net_hangup(idev);
-
+ if (idev->outgoing || mlp->hupflags & ISDN_INHUP) {
+ isdn_net_hangup(idev);
+ return;
+ }
mod_timer:
mod_timer(&idev->dial_timer, idev->dial_timer.expires + HZ);
- return 1;
}
/* Charge-info from TelCo. */
-static int
-isdn_net_cinf(isdn_net_dev *idev)
+static void
+got_cinf(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
+
idev->charge++;
switch (idev->charge_state) {
case ST_CHARGE_NULL:
}
idev->chargetime = jiffies;
dbg_net_dial("%s: got CINF\n", idev->name);
- return 1;
}
-static int
-isdn_net_disconnected(isdn_net_dev *idev)
+static void
+disconnected(struct fsm_inst *fi, int pr, void *arg)
{
+ isdn_net_dev *idev = fi->userdata;
isdn_net_local *mlp = idev->mlp;
del_timer(&idev->dial_timer);
idev->charge);
isdn_slot_all_eaz(idev->isdn_slot);
isdn_net_unbind_channel(idev);
-
- return 1;
}
/* Perform hangup for a net-interface. */
return 1;
}
-
-static int
-isdn_net_event_out_wait_dconn(isdn_net_dev *idev, int pr, void *arg)
+/*
+ * Handle status-messages from ISDN-interfacecard.
+ * This function is called from within the main-status-dispatcher
+ * isdn_status_callback, which itself is called from the low-level driver.
+ * Return: 1 = event handled, 0 = not handled
+ */
+int
+isdn_net_stat_callback(int idx, isdn_ctrl *c)
{
- switch (pr) {
- case EV_NET_TIMER_DIAL:
- return dial_timeout(idev);
- case EV_NET_TIMER_CB_OUT:
- return isdn_net_hangup(idev);
- case ISDN_STAT_DCONN:
- return isdn_net_out_dconn(idev);
- case ISDN_STAT_DHUP:
- return isdn_net_connect_failure(idev);
- }
- isdn_BUG();
- return 0;
-}
+ isdn_net_dev *idev = isdn_slot_idev(idx);
-static int
-isdn_net_event_out_wait_bconn(isdn_net_dev *idev, int pr, void *arg)
-{
- switch (pr) {
- case EV_NET_TIMER_DIAL:
- return dial_timeout(idev);
+ if (!idev) {
+ HERE;
+ return 0;
+ }
+ switch (c->command) {
+ case ISDN_STAT_DCONN:
+ return fsm_event(&idev->fi, EV_STAT_DCONN, c);
case ISDN_STAT_BCONN:
- return isdn_net_bconn(idev);
+ return fsm_event(&idev->fi, EV_STAT_BCONN, c);
+ case ISDN_STAT_BHUP:
+ return fsm_event(&idev->fi, EV_STAT_BHUP, c);
case ISDN_STAT_DHUP:
- return isdn_net_connect_failure(idev);
+ return fsm_event(&idev->fi, EV_STAT_DHUP, c);
+ case ISDN_STAT_CINF:
+ return fsm_event(&idev->fi, EV_STAT_CINF, c);
+ case ISDN_STAT_BSENT:
+ return fsm_event(&idev->fi, EV_STAT_BSENT, c);
+ default:
+ printk("unknown stat %d\n", c->command);
+ return 0;
}
- isdn_BUG();
- return 0;
}
-static int
-isdn_net_event_in_wait_dconn(isdn_net_dev *idev, int pr, void *arg)
+int
+isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
{
- switch (pr) {
- case EV_NET_TIMER_INCOMING:
- return isdn_net_hangup(idev);
- case ISDN_STAT_DCONN:
- return isdn_net_in_dconn(idev);
- case ISDN_STAT_DHUP:
- return isdn_net_connect_failure(idev);
- }
- isdn_BUG();
- return 0;
+ fsm_event(&idev->fi, pr, arg);
}
-static int
-isdn_net_event_in_wait_bconn(isdn_net_dev *idev, int pr, void *arg)
+static void
+hang_up(struct fsm_inst *fi, int pr, void *arg)
{
- switch (pr) {
- case EV_NET_TIMER_INCOMING:
- return isdn_net_hangup(idev);
- case ISDN_STAT_BCONN:
- return isdn_net_bconn(idev);
- case ISDN_STAT_DHUP:
- return isdn_net_connect_failure(idev);
- }
- isdn_BUG();
- return 0;
+ isdn_net_dev *idev = fi->userdata;
+
+ isdn_net_hangup(idev);
}
-static int
-isdn_net_event_wait_before_cb(isdn_net_dev *idev, int pr, void *arg)
+static void
+got_bsent(struct fsm_inst *fi, int pr, void *arg)
{
- switch (pr) {
- case EV_NET_TIMER_CB_IN:
- return init_dialout(idev);
- }
- isdn_BUG();
- return 0;
+ isdn_net_dev *idev = fi->userdata;
+ isdn_ctrl *c = arg;
+
+ isdn_net_bsent(idev, c);
}
-static int
-isdn_net_event_active(isdn_net_dev *idev, int pr, void *arg)
+static struct fsm_node isdn_net_fn_tbl[] = {
+ { ST_OUT_WAIT_DCONN, EV_TIMER_DIAL, dial_timeout },
+ { ST_OUT_WAIT_DCONN, EV_STAT_DCONN, out_dconn },
+ { ST_OUT_WAIT_DCONN, EV_STAT_DHUP, connect_fail },
+ { ST_OUT_WAIT_DCONN, EV_TIMER_CB_OUT, hang_up },
+
+ { ST_OUT_WAIT_BCONN, EV_TIMER_DIAL, dial_timeout },
+ { ST_OUT_WAIT_BCONN, EV_STAT_BCONN, bconn },
+ { ST_OUT_WAIT_BCONN, EV_STAT_DHUP, connect_fail },
+
+ { ST_IN_WAIT_DCONN, EV_TIMER_INCOMING, hang_up },
+ { ST_IN_WAIT_DCONN, EV_STAT_DCONN, in_dconn },
+ { ST_IN_WAIT_DCONN, EV_STAT_DHUP, connect_fail },
+
+ { ST_IN_WAIT_BCONN, EV_TIMER_INCOMING, hang_up },
+ { ST_IN_WAIT_BCONN, EV_STAT_BCONN, bconn },
+ { ST_IN_WAIT_BCONN, EV_STAT_DHUP, connect_fail },
+
+ { ST_ACTIVE, EV_TIMER_HUP, check_hup },
+ { ST_ACTIVE, EV_STAT_BHUP, disconnected },
+ { ST_ACTIVE, EV_STAT_CINF, got_cinf },
+ { ST_ACTIVE, EV_STAT_BSENT, got_bsent },
+
+ { ST_WAIT_BEFORE_CB, EV_TIMER_CB_IN, dialout_first },
+
+ { ST_OUT_DIAL_WAIT, EV_TIMER_DIAL_WAIT, dialout_next },
+};
+
+static struct fsm isdn_net_fsm = {
+ .st_cnt = ARRAY_SIZE(isdn_net_st_str),
+ .st_str = isdn_net_st_str,
+ .ev_cnt = ARRAY_SIZE(isdn_net_ev_str),
+ .ev_str = isdn_net_ev_str,
+ .fn_cnt = ARRAY_SIZE(isdn_net_fn_tbl),
+ .fn_tbl = isdn_net_fn_tbl,
+};
+
+static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...)
{
- switch (pr) {
- case EV_NET_TIMER_HUP:
- return isdn_net_check_hup(idev);
- case ISDN_STAT_BSENT:
- return isdn_net_bsent(idev, arg);
- case ISDN_STAT_BHUP:
- case ISDN_STAT_DHUP:
- return isdn_net_disconnected(idev);
- case ISDN_STAT_CINF:
- return isdn_net_cinf(idev);
- }
- isdn_BUG();
- return 0;
+ va_list args;
+ isdn_net_dev *idev = fi->userdata;
+ char buf[128];
+ char *p = buf;
+
+ va_start(args, fmt);
+ p += sprintf(p, "%s: ", idev->name);
+ p += vsprintf(p, fmt, args);
+ va_end(args);
+ printk(KERN_DEBUG "%s\n", buf);
}
-static int
-isdn_net_event_dial_wait(isdn_net_dev *idev, int pr, void *arg)
+void
+isdn_net_lib_init(void)
{
- switch (pr) {
- case EV_NET_TIMER_DIAL_WAIT:
- return do_dialout(idev);
- }
- isdn_BUG();
- return 0;
+ fsm_new(&isdn_net_fsm);
}
-/*
- * For ISDN_STAT_*, return 1 if event was for us
- */
-int
-isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
+void
+isdn_net_lib_exit(void)
{
- dbg_net_dial("%s: dialstate=%d pr=%#x\n", idev->name,
- idev->dialstate, pr);
-
- switch (idev->dialstate) {
- case ST_ACTIVE:
- return isdn_net_event_active(idev, pr, arg);
- case ST_OUT_WAIT_DCONN:
- return isdn_net_event_out_wait_dconn(idev, pr, arg);
- case ST_OUT_WAIT_BCONN:
- return isdn_net_event_out_wait_bconn(idev, pr, arg);
- case ST_IN_WAIT_DCONN:
- return isdn_net_event_in_wait_dconn(idev, pr, arg);
- case ST_IN_WAIT_BCONN:
- return isdn_net_event_in_wait_bconn(idev, pr, arg);
- case ST_WAIT_BEFORE_CB:
- return isdn_net_event_wait_before_cb(idev, pr, arg);
- case ST_OUT_DIAL_WAIT:
- return isdn_net_event_dial_wait(idev, pr, arg);
- default:
- isdn_BUG();
- return 0;
- }
+ fsm_free(&isdn_net_fsm);
}
-