📄 callc.c
字号:
/* $Id: callc.c,v 1.1.1.1 1999/11/15 13:42:17 vadim Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * * This file is (c) under GNU PUBLIC LICENSE * For changes and modifications please read * ../../../Documentation/isdn/HiSax.cert * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: callc.c,v $ * Revision 1.1.1.1 1999/11/15 13:42:17 vadim * Initial import * * Revision 1.30.2.13 1998/11/05 21:13:32 keil * minor fixes * * Revision 1.30.2.12 1998/11/03 00:05:51 keil * certification related changes * fixed logging for smaller stack use * * Revision 1.30.2.11 1998/09/30 22:20:05 keil * Cosmetics * * Revision 1.30.2.10 1998/09/27 13:05:35 keil * Apply most changes from 2.1.X (HiSax 3.1) * * Revision 1.30.2.9 1998/05/27 18:04:53 keil * HiSax 3.0 * * Revision 1.30.2.8 1998/04/11 18:48:26 keil * remove debug * * Revision 1.30.2.7 1998/04/08 21:51:50 keil * new debug * * Revision 1.30.2.6 1998/03/07 23:15:02 tsbogend * made HiSax working on Linux/Alpha * * Revision 1.30.2.5 1998/02/09 11:24:17 keil * New leased line support (Read README.HiSax!) * * Revision 1.30.2.4 1998/01/27 22:46:00 keil * B-channel send delay now configurable * * Revision 1.30.2.3 1998/01/11 23:21:03 keil * Missing callc state * * Revision 1.30.2.2 1997/11/15 18:54:31 keil * cosmetics * * Revision 1.30.2.1 1997/10/17 22:13:32 keil * update to last hisax version * * Revision 2.6 1997/09/11 17:26:58 keil * Open B-channel if here are incomming packets * * Revision 2.5 1997/08/07 17:46:05 keil * Fix Incomming Call without broadcast * * Revision 2.4 1997/08/03 14:37:58 keil * Activate Layer2 in PtP mode * * Revision 2.3 1997/07/31 19:23:40 keil * LAYER2_WATCHING for PtP * * Revision 2.2 1997/07/31 11:48:18 keil * experimental REJECT after ALERTING * * Revision 2.1 1997/07/30 17:12:59 keil * more changes for 'One TEI per card' * * Revision 2.0 1997/07/27 21:12:21 keil * CRef based L3; new channel handling; many other stuff * * Revision 1.31 1997/06/26 11:09:23 keil * New managment and minor changes * * old logs removed /KKe * */#define __NO_VERSION__#include "hisax.h"#include "../avmb1/capicmd.h" /* this should be moved in a common place */#ifdef MODULEextern long mod_use_count_;#define MOD_USE_COUNT mod_use_count_#endif /* MODULE */const char *lli_revision = "$Revision: 1.1.1.1 $";extern struct IsdnCard cards[];extern int nrcards;extern void HiSax_mod_dec_use_count(void);extern void HiSax_mod_inc_use_count(void);static int init_b_st(struct Channel *chanp, int incoming);static void release_b_st(struct Channel *chanp);static struct Fsm callcfsm ={NULL, 0, 0, NULL, NULL};static int chancount = 0;/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */#define ALERT_REJECT 0/* Value to delay the sending of the first B-channel paket after CONNECT * here is no value given by ITU, but experience shows that 300 ms will * work on many networks, if you or your other side is behind local exchanges * a greater value may be recommented. If the delay is to short the first paket * will be lost and autodetect on many comercial routers goes wrong ! * You can adjust this value on runtime with * hisaxctrl <id> 2 <value> * value is in milliseconds */#define DEFAULT_B_DELAY 300/* Flags for remembering action done in lli */#define FLG_START_D 0#define FLG_ESTAB_D 1#define FLG_CALL_SEND 2#define FLG_CALL_REC 3#define FLG_CALL_ALERT 4#define FLG_START_B 5#define FLG_CONNECT_B 6#define FLG_LL_DCONN 7#define FLG_LL_BCONN 8#define FLG_DISC_SEND 9#define FLG_DISC_REC 10#define FLG_REL_REC 11#define FLG_DO_ALERT 12#define FLG_DO_HANGUP 13#define FLG_DO_CONNECT 14#define FLG_DO_ESTAB 15#define FLG_RESUME 16/* * Because of callback it's a good idea to delay the shutdown of the d-channel */#define DREL_TIMER_VALUE 40000/* * Find card with given driverId */static inline struct IsdnCardState*hisax_findcard(int driverid){ int i; for (i = 0; i < nrcards; i++) if (cards[i].cs) if (cards[i].cs->myid == driverid) return (cards[i].cs); return (struct IsdnCardState *) 0;}intdiscard_queue(struct sk_buff_head *q){ struct sk_buff *skb; int ret=0; while ((skb = skb_dequeue(q))) { dev_kfree_skb(skb, FREE_READ); ret++; } return(ret);}static voidlink_debug(struct Channel *chanp, int direction, char *fmt, ...){ va_list args; char tmp[16]; va_start(args, fmt); sprintf(tmp, "Ch%d %s ", chanp->chan, direction ? "LL->HL" : "HL->LL"); VHiSax_putstatus(chanp->cs, tmp, fmt, args); va_end(args);}enum { ST_NULL, /* 0 inactive */ ST_OUT_WAIT_D, /* 1 outgoing, awaiting d-channel establishment */ ST_IN_WAIT_D, /* 2 incoming, awaiting d-channel establishment */ ST_OUT_DIAL, /* 3 outgoing, SETUP send; awaiting confirm */ ST_IN_WAIT_LL, /* 4 incoming call received; wait for LL confirm */ ST_IN_ALERT_SEND, /* 5 incoming call received; ALERT send */ ST_IN_WAIT_CONN_ACK, /* 6 incoming CONNECT send; awaiting CONN_ACK */ ST_WAIT_BCONN, /* 7 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */ ST_ACTIVE, /* 8 active, b channel prot. established */ ST_WAIT_BRELEASE, /* 9 call clear. (initiator), awaiting b channel prot. rel. */ ST_WAIT_BREL_DISC, /* 10 call clear. (receiver), DISCONNECT req. received */ ST_WAIT_DCOMMAND, /* 11 call clear. (receiver), awaiting DCHANNEL message */ ST_WAIT_DRELEASE, /* 12 DISCONNECT sent, awaiting RELEASE */ ST_WAIT_D_REL_CNF, /* 13 RELEASE sent, awaiting RELEASE confirm */ ST_WAIT_DSHUTDOWN, /* 14 awaiting d-channel shutdown */};#define STATE_COUNT (ST_WAIT_DSHUTDOWN +1)static char *strState[] ={ "ST_NULL", "ST_OUT_WAIT_D", "ST_IN_WAIT_D", "ST_OUT_DIAL", "ST_IN_WAIT_LL", "ST_IN_ALERT_SEND", "ST_IN_WAIT_CONN_ACK", "ST_WAIT_BCONN", "ST_ACTIVE", "ST_WAIT_BRELEASE", "ST_WAIT_BREL_DISC", "ST_WAIT_DCOMMAND", "ST_WAIT_DRELEASE", "ST_WAIT_D_REL_CNF", "ST_WAIT_DSHUTDOWN",};enum { EV_DIAL, /* 0 */ EV_SETUP_CNF, /* 1 */ EV_ACCEPTB, /* 2 */ EV_DISCONNECT_IND, /* 3 */ EV_RELEASE_CNF, /* 4 */ EV_DLEST, /* 5 */ EV_DLRL, /* 6 */ EV_SETUP_IND, /* 7 */ EV_RELEASE_IND, /* 8 */ EV_ACCEPTD, /* 9 */ EV_SETUP_CMPL_IND, /* 10 */ EV_BC_EST, /* 11 */ EV_WRITEBUF, /* 12 */ EV_ESTABLISH, /* 13 */ EV_HANGUP, /* 14 */ EV_BC_REL, /* 15 */ EV_CINF, /* 16 */ EV_SUSPEND, /* 17 */ EV_RESUME, /* 18 */ EV_SHUTDOWN_D, /* 19 */ EV_NOSETUP_RSP, /* 20 */ EV_SETUP_ERR, /* 21 */ EV_CONNECT_ERR, /* 22 */ EV_RELEASE_ERR, /* 23 */};#define EVENT_COUNT (EV_RELEASE_ERR +1)static char *strEvent[] ={ "EV_DIAL", "EV_SETUP_CNF", "EV_ACCEPTB", "EV_DISCONNECT_IND", "EV_RELEASE_CNF", "EV_DLEST", "EV_DLRL", "EV_SETUP_IND", "EV_RELEASE_IND", "EV_ACCEPTD", "EV_SETUP_CMPL_IND", "EV_BC_EST", "EV_WRITEBUF", "EV_ESTABLISH", "EV_HANGUP", "EV_BC_REL", "EV_CINF", "EV_SUSPEND", "EV_RESUME", "EV_SHUTDOWN_D", "EV_NOSETUP_RSP", "EV_SETUP_ERR", "EV_CONNECT_ERR", "EV_RELEASE_ERR",};static inline voidlli_deliver_cause(struct Channel *chanp, isdn_ctrl *ic){ if (chanp->proc->para.cause < 0) return; ic->driver = chanp->cs->myid; ic->command = ISDN_STAT_CAUSE; ic->arg = chanp->chan; if (chanp->cs->protocol == ISDN_PTYPE_EURO) sprintf(ic->parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f, chanp->proc->para.cause & 0x7f); else sprintf(ic->parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f, chanp->proc->para.cause & 0x7f); chanp->cs->iif.statcallb(ic);}static voidlli_d_established(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); if (chanp->leased) { isdn_ctrl ic; int ret; chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); FsmChangeState(fi, ST_IN_WAIT_LL); test_and_set_bit(FLG_CALL_REC, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_ICALL_LEASED"); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_ICALL; ic.arg = chanp->chan; ic.parm.setup.si1 = 7; ic.parm.setup.si2 = 0; ic.parm.setup.plan = 0; ic.parm.setup.screen = 0; sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid); ret = chanp->cs->iif.statcallb(&ic); if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); if (!ret) { chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); } } else if (fi->state == ST_WAIT_DSHUTDOWN) FsmChangeState(fi, ST_NULL);}static voidlli_d_released(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; test_and_clear_bit(FLG_START_D, &chanp->Flags);}/* * Dial out */static voidlli_prep_dialout(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_OUT_WAIT_D); FsmDelTimer(&chanp->drel_timer, 60); FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { FsmEvent(fi, EV_DLEST, NULL); } else { chanp->Flags = 0; if (EV_RESUME == event) test_and_set_bit(FLG_RESUME, &chanp->Flags); test_and_set_bit(FLG_START_D, &chanp->Flags); chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); }}static voidlli_do_dialout(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; int ev; FsmChangeState(fi, ST_OUT_DIAL); chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); if (test_and_clear_bit(FLG_RESUME, &chanp->Flags)) ev = CC_RESUME | REQUEST; else ev = CC_SETUP | REQUEST; if (chanp->leased) { FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); } else { test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); chanp->d_st->lli.l4l3(chanp->d_st, ev, chanp); test_and_set_bit(FLG_CALL_SEND, &chanp->Flags); }}static voidlli_init_bchan_out(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; isdn_ctrl ic; FsmChangeState(fi, ST_WAIT_BCONN); test_and_set_bit(FLG_LL_DCONN, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_DCONN"); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_DCONN; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); init_b_st(chanp, 0); test_and_set_bit(FLG_START_B, &chanp->Flags); chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);}static voidlli_go_active(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; isdn_ctrl ic; FsmChangeState(fi, ST_ACTIVE); chanp->data_open = !0; test_and_set_bit(FLG_CONNECT_B, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_BCONN"); test_and_set_bit(FLG_LL_BCONN, &chanp->Flags); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_BCONN; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);}/* * RESUME *//* incomming call */static voidlli_start_dchan(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_IN_WAIT_D); FsmDelTimer(&chanp->drel_timer, 61); if (event == EV_ACCEPTD) test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags); else if (event == EV_HANGUP) { test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags);#ifdef ALERT_REJECT test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);#endif } if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { FsmEvent(fi, EV_DLEST, NULL); } else if (!test_and_set_bit(FLG_START_D, &chanp->Flags)) chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);}static voidlli_deliver_call(struct FsmInst *fi, int event, void *arg){ struct Channel *chanp = fi->userdata; isdn_ctrl ic; int ret; chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); /* * Report incoming calls only once to linklevel, use CallFlags * which is set to 3 with each broadcast message in isdnl1.c * and resetted if a interface answered the STAT_ICALL. */ if (1) { /* for only one TEI */ FsmChangeState(fi, ST_IN_WAIT_LL); test_and_set_bit(FLG_CALL_REC, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_ICALL"); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_ICALL; ic.arg = chanp->chan; /* * No need to return "unknown" for calls without OAD, * cause that's handled in linklevel now (replaced by '0') */ ic.parm.setup = chanp->proc->para.setup; ret = chanp->cs->iif.statcallb(&ic); if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); switch (ret) { case 1: /* OK, anybody likes this call */ FsmDelTimer(&chanp->drel_timer, 61); if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { FsmChangeState(fi, ST_IN_ALERT_SEND); test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags); chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); } else { test_and_set_bit(FLG_DO_ALERT, &chanp->Flags); FsmChangeState(fi, ST_IN_WAIT_D); test_and_set_bit(FLG_START_D, &chanp->Flags); chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); } break; case 2: /* Rejecting Call */ test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); break; case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); if (test_bit(FLG_ESTAB_D, &chanp->Flags) && !test_bit(FLG_PTP, &chanp->d_st->l2.flag)) FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -