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

📄 l3dss1.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: l3dss1.c,v 1.1.1.1 1999/11/15 13:42:18 vadim Exp $ * EURO/DSS1 D-channel protocol * * Author       Karsten Keil (keil@temic-ech.spacenet.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: l3dss1.c,v $ * Revision 1.1.1.1  1999/11/15 13:42:18  vadim * Initial import * * Revision 1.16.2.8  1998/11/03 00:07:14  keil * certification related changes * fixed logging for smaller stack use * * Revision 1.16.2.7  1998/10/25 18:16:25  fritz * Replaced some read-only variables by defines. * * Revision 1.16.2.6  1998/10/23 15:00:56  fritz * Eliminated a compiler warning. * * Revision 1.16.2.5  1998/09/27 13:06:48  keil * Apply most changes from 2.1.X (HiSax 3.1) * * Revision 1.16.2.4  1998/05/27 18:06:08  keil * HiSax 3.0 * * Revision 1.16.2.3  1998/02/03 23:16:06  keil * german AOC * * Revision 1.16.2.2  1997/11/15 18:54:15  keil * cosmetics * * Revision 1.16.2.1  1997/10/17 22:14:16  keil * update to last hisax version * * Revision 2.2  1997/08/07 17:44:36  keil * Fix RESTART * * Revision 2.1  1997/08/03 14:36:33  keil * Implement RESTART procedure * * Revision 2.0  1997/07/27 21:15:43  keil * New Callref based layer3 * * Revision 1.17  1997/06/26 11:11:46  keil * SET_SKBFREE now on creation of a SKB * * Revision 1.15  1997/04/17 11:50:48  keil * pa->loc was undefined, if it was not send by the exchange * * Old log removed /KKe * */#define __NO_VERSION__#include "hisax.h"#include "isdnl3.h"#include "l3dss1.h"#include <linux/ctype.h>extern char *HiSax_getrev(const char *revision);const char *dss1_revision = "$Revision: 1.1.1.1 $";#define EXT_BEARER_CAPS 1#define	MsgHead(ptr, cref, mty) \	*ptr++ = 0x8; \	*ptr++ = 0x1; \	*ptr++ = cref^0x80; \	*ptr++ = mty#if HISAX_DE_AOCstatic voidl3dss1_parse_facility(struct l3_process *pc, u_char * p){	int qd_len = 0;	p++;	qd_len = *p++;	if (qd_len == 0) {		l3_debug(pc->st, "qd_len == 0");		return;	}	if ((*p & 0x1F) != 0x11) {	/* Service discriminator, supplementary service */		l3_debug(pc->st, "supplementary service != 0x11");		return;	}	while (qd_len > 0 && !(*p & 0x80)) {	/* extension ? */		p++;		qd_len--;	}	if (qd_len < 2) {		l3_debug(pc->st, "qd_len < 2");		return;	}	p++;	qd_len--;	if ((*p & 0xE0) != 0xA0) {	/* class and form */		l3_debug(pc->st, "class and form != 0xA0");		return;	}	switch (*p & 0x1F) {	/* component tag */		case 1:	/* invoke */			{				unsigned char nlen = 0, ilen;				int ident;				p++;				qd_len--;				if (qd_len < 1) {					l3_debug(pc->st, "qd_len < 1");					break;				}				if (*p & 0x80) {	/* length format */					l3_debug(pc->st, "*p & 0x80 length format");					break;				}				nlen = *p++;				qd_len--;				if (qd_len < nlen) {					l3_debug(pc->st, "qd_len < nlen");					return;				}				qd_len -= nlen;				if (nlen < 2) {					l3_debug(pc->st, "nlen < 2");					return;				}				if (*p != 0x02) {	/* invoke identifier tag */					l3_debug(pc->st, "invoke identifier tag !=0x02");					return;				}				p++;				nlen--;				if (*p & 0x80) {	/* length format */					l3_debug(pc->st, "*p & 0x80 length format 2");					break;				}				ilen = *p++;				nlen--;				if (ilen > nlen || ilen == 0) {					l3_debug(pc->st, "ilen > nlen || ilen == 0");					return;				}				nlen -= ilen;				ident = 0;				while (ilen > 0) {					ident = (ident << 8) | (*p++ & 0xFF);	/* invoke identifier */					ilen--;				}				if (nlen < 2) {					l3_debug(pc->st, "nlen < 2 22");					return;				}				if (*p != 0x02) {	/* operation value */					l3_debug(pc->st, "operation value !=0x02");					return;				}				p++;				nlen--;				ilen = *p++;				nlen--;				if (ilen > nlen || ilen == 0) {					l3_debug(pc->st, "ilen > nlen || ilen == 0 22");					return;				}				nlen -= ilen;				ident = 0;				while (ilen > 0) {					ident = (ident << 8) | (*p++ & 0xFF);					ilen--;				}#define FOO1(s,a,b) \	    while(nlen > 1) {		\		    int ilen = p[1];	\		    if(nlen < ilen+2) {	\			    l3_debug(pc->st, "FOO1  nlen < ilen+2"); \			    return;		\		    }			\		    nlen -= ilen+2;		\		    if((*p & 0xFF) == (a)) {	\			    int nlen = ilen;	\			    p += 2;		\			    b;		\		    } else {		\			    p += ilen+2;	\		    }			\	    }				switch (ident) {					default:						break;					case 0x22:	/* during */						FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {							       ident = 0;							nlen = (nlen)?nlen:0; /* Make gcc happy */							while (ilen > 0) {														     ident = (ident << 8) | *p++;								  ilen--;									}														     if (ident > pc->para.chargeinfo) {														     pc->para.chargeinfo = ident;														     pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);									}														     if (pc->st->l3.debug & L3_DEB_CHARGE) {														     if (*(p + 2) == 0) {														     l3_debug(pc->st, "charging info during %d", pc->para.chargeinfo);									}								   else {														     l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);									}									}									}								    )))))							break;					case 0x24:	/* final */						FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {							       ident = 0;							nlen = (nlen)?nlen:0; /* Make gcc happy */							while (ilen > 0) {																      ident = (ident << 8) | *p++;								  ilen--;									}																      if (ident > pc->para.chargeinfo) {																      pc->para.chargeinfo = ident;																      pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);									}																      if (pc->st->l3.debug & L3_DEB_CHARGE) {																      l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);									}									}								   ))))))							break;				}#undef FOO1			}			break;		case 2:	/* return result */			l3_debug(pc->st, "return result break");			break;		case 3:	/* return error */			l3_debug(pc->st, "return error break");			break;		default:			l3_debug(pc->st, "default break");			break;	}}#endifstatic intl3dss1_check_messagetype_validity(int mt){/* verify if a message type exists */	switch (mt) {		case MT_ALERTING:		case MT_CALL_PROCEEDING:		case MT_CONNECT:		case MT_CONNECT_ACKNOWLEDGE:		case MT_PROGRESS:		case MT_SETUP:		case MT_SETUP_ACKNOWLEDGE:		case MT_RESUME:		case MT_RESUME_ACKNOWLEDGE:		case MT_RESUME_REJECT:		case MT_SUSPEND:		case MT_SUSPEND_ACKNOWLEDGE:		case MT_SUSPEND_REJECT:		case MT_USER_INFORMATION:		case MT_DISCONNECT:		case MT_RELEASE:		case MT_RELEASE_COMPLETE:		case MT_RESTART:		case MT_RESTART_ACKNOWLEDGE:		case MT_SEGMENT:		case MT_CONGESTION_CONTROL:		case MT_INFORMATION:		case MT_FACILITY:		case MT_NOTIFY:		case MT_STATUS:		case MT_STATUS_ENQUIRY:			return(1);		default:			return(0);	}	return(0);}static voidl3dss1_message(struct l3_process *pc, u_char mt){	struct sk_buff *skb;	u_char *p;	if (!(skb = l3_alloc_skb(4)))		return;	p = skb_put(skb, 4);	MsgHead(p, pc->callref, mt);	l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3dss1_release_req(struct l3_process *pc, u_char pr, void *arg){	StopAllL3Timer(pc);	newl3state(pc, 19);	l3dss1_message(pc, MT_RELEASE);	L3AddTimer(&pc->timer, T308, CC_T308_1);}static voidl3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg){	u_char *p;	struct sk_buff *skb = arg;	int cause = -1;	p = skb->data;	pc->para.loc = 0;	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {		p++;		if (*p++ == 2)			pc->para.loc = *p++;		cause = *p & 0x7f;	}	dev_kfree_skb(skb, FREE_READ);	StopAllL3Timer(pc);	pc->para.cause = cause;	newl3state(pc, 0);	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);	release_l3_process(pc);}#if EXT_BEARER_CAPSu_char *EncodeASyncParams(u_char * p, u_char si2){				// 7c 06 88  90 21 42 00 bb	p[0] = p[1] = 0;	p[2] = 0x80;	if (si2 & 32)		// 7 data bits		p[2] += 16;	else			// 8 data bits		p[2] += 24;	if (si2 & 16)		// 2 stop bits		p[2] += 96;	else			// 1 stop bit		p[2] = 32;	if (si2 & 8)		// even parity		p[2] += 2;	else			// no parity		p[2] += 3;	switch (si2 & 0x07) {		case 0:			p[0] = 66;	// 1200 bit/s			break;		case 1:			p[0] = 88;	// 1200/75 bit/s			break;		case 2:			p[0] = 87;	// 75/1200 bit/s			break;		case 3:			p[0] = 67;	// 2400 bit/s			break;		case 4:			p[0] = 69;	// 4800 bit/s			break;		case 5:			p[0] = 72;	// 9600 bit/s			break;		case 6:			p[0] = 73;	// 14400 bit/s			break;		case 7:			p[0] = 75;	// 19200 bit/s			break;	}	return p + 3;}u_charEncodeSyncParams(u_char si2, u_char ai){	switch (si2) {		case 0:			return ai + 2;	// 1200 bit/s		case 1:			return ai + 24;		// 1200/75 bit/s		case 2:			return ai + 23;		// 75/1200 bit/s		case 3:			return ai + 3;	// 2400 bit/s		case 4:			return ai + 5;	// 4800 bit/s		case 5:			return ai + 8;	// 9600 bit/s		case 6:			return ai + 9;	// 14400 bit/s		case 7:			return ai + 11;		// 19200 bit/s		case 8:			return ai + 14;		// 48000 bit/s		case 9:			return ai + 15;		// 56000 bit/s		case 15:			return ai + 40;		// negotiate bit/s		default:			break;	}	return ai;}static u_charDecodeASyncParams(u_char si2, u_char * p){	u_char info;	switch (p[5]) {		case 66:	// 1200 bit/s			break;	// si2 don't change		case 88:	// 1200/75 bit/s			si2 += 1;			break;		case 87:	// 75/1200 bit/s			si2 += 2;			break;		case 67:	// 2400 bit/s			si2 += 3;			break;		case 69:	// 4800 bit/s			si2 += 4;			break;		case 72:	// 9600 bit/s			si2 += 5;			break;		case 73:	// 14400 bit/s			si2 += 6;			break;		case 75:	// 19200 bit/s			si2 += 7;			break;	}	info = p[7] & 0x7f;	if ((info & 16) && (!(info & 8)))	// 7 data bits		si2 += 32;	// else 8 data bits	if ((info & 96) == 96)	// 2 stop bits		si2 += 16;	// else 1 stop bit	if ((info & 2) && (!(info & 1)))	// even parity		si2 += 8;	// else no parity	return si2;}static u_charDecodeSyncParams(u_char si2, u_char info){	info &= 0x7f;	switch (info) {		case 40:	// bit/s negotiation failed  ai := 165 not 175!			return si2 + 15;		case 15:	// 56000 bit/s failed, ai := 0 not 169 !			return si2 + 9;		case 14:	// 48000 bit/s			return si2 + 8;		case 11:	// 19200 bit/s			return si2 + 7;		case 9:	// 14400 bit/s			return si2 + 6;		case 8:	// 9600  bit/s			return si2 + 5;		case 5:	// 4800  bit/s			return si2 + 4;		case 3:	// 2400  bit/s			return si2 + 3;		case 23:	// 75/1200 bit/s			return si2 + 2;		case 24:	// 1200/75 bit/s			return si2 + 1;		default:	// 1200 bit/s			return si2;	}}static u_charDecodeSI2(struct sk_buff *skb){	u_char *p;		//, *pend=skb->data + skb->len;	if ((p = findie(skb->data, skb->len, 0x7c, 0))) {		switch (p[4] & 0x0f) {			case 0x01:				if (p[1] == 0x04)	// sync. Bitratenadaption					return DecodeSyncParams(160, p[5]);	// V.110/X.30				else if (p[1] == 0x06)	// async. Bitratenadaption					return DecodeASyncParams(192, p);	// V.110/X.30				break;			case 0x08:	// if (p[5] == 0x02) // sync. Bitratenadaption				return DecodeSyncParams(176, p[5]);	// V.120				break;		}	}	return 0;}#endifstatic voidl3dss1_setup_req(struct l3_process *pc, u_char pr,		 void *arg){	struct sk_buff *skb;	u_char tmp[128];	u_char *p = tmp;	u_char channel = 0;	u_char screen = 0x80;	u_char *teln;	u_char *msn;	u_char *sub;	u_char *sp;	int l;	MsgHead(p, pc->callref, MT_SETUP);	/*	 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1	 */#if HISAX_EURO_SENDCOMPLETE	*p++ = 0xa1;		/* complete indicator */#endif	switch (pc->para.setup.si1) {		case 1:	/* Telephony                               */			*p++ = 0x4;	/* BC-IE-code                              */			*p++ = 0x3;	/* Length                                  */			*p++ = 0x90;	/* Coding Std. CCITT, 3.1 kHz audio     */			*p++ = 0x90;	/* Circuit-Mode 64kbps                     */			*p++ = 0xa3;	/* A-Law Audio                             */			break;		case 5:	/* Datatransmission 64k, BTX               */		case 7:	/* Datatransmission 64k                    */		default:			*p++ = 0x4;	/* BC-IE-code                              */			*p++ = 0x2;	/* Length                                  */			*p++ = 0x88;	/* Coding Std. CCITT, unrestr. dig. Inform. */			*p++ = 0x90;	/* Circuit-Mode 64kbps                      */			break;	}	/*	 * What about info2? Mapping to High-Layer-Compatibility?	 */	teln = pc->para.setup.phone;	if (*teln) {		/* parse number for special things */		if (!isdigit(*teln)) {			switch (0x5f & *teln) {				case 'C':					channel = 0x08;				case 'P':					channel |= 0x80;					teln++;					if (*teln == '1')						channel |= 0x01;					else						channel |= 0x02;					break;				case 'R':					screen = 0xA0;					break;				case 'D':					screen = 0x80;					break;				default:					if (pc->debug & L3_DEB_WARN)						l3_debug(pc->st, "Wrong MSN Code");					break;			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -