⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callc.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $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 + -