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

📄 l3dss1.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: l3dss1.c,v 2.30.6.2 2001/09/23 22:24:49 kai Exp $ * * EURO/DSS1 D-channel protocol * * German 1TR6 D-channel protocol * * Author       Karsten Keil *              based on the teles driver from Jan den Ouden * Copyright    by Karsten Keil      <keil@isdn4linux.de> *  * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * For changes and modifications please read * ../../../Documentation/isdn/HiSax.cert * * Thanks to    Jan den Ouden *              Fritz Elfert * */#define __NO_VERSION__#include "hisax.h"#include "isdnl3.h"#include "l3dss1.h"#include <linux/ctype.h>#include <linux/config.h>extern char *HiSax_getrev(const char *revision);const char *dss1_revision = "$Revision: 2.30.6.2 $";#define EXT_BEARER_CAPS 1#define	MsgHead(ptr, cref, mty) \	*ptr++ = 0x8; \	if (cref == -1) { \		*ptr++ = 0x0; \	} else { \		*ptr++ = 0x1; \		*ptr++ = cref^0x80; \	} \	*ptr++ = mty/**********************************************//* get a new invoke id for remote operations. *//* Only a return value != 0 is valid          *//**********************************************/static unsigned char new_invoke_id(struct PStack *p){	unsigned char retval;	unsigned long flags;	int i;  	i = 32; /* maximum search depth */	save_flags(flags);	cli();	retval = p->prot.dss1.last_invoke_id + 1; /* try new id */	while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {		p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;		i--;	}  	if (i) {		while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))		retval++; 	} else		retval = 0;	p->prot.dss1.last_invoke_id = retval;	p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));	restore_flags(flags);	return(retval);  } /* new_invoke_id *//*************************//* free a used invoke id *//*************************/static void free_invoke_id(struct PStack *p, unsigned char id){ unsigned long flags;  if (!id) return; /* 0 = invalid value */  save_flags(flags);  cli();  p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));  restore_flags(flags);} /* free_invoke_id */  /**********************************************************//* create a new l3 process and fill in dss1 specific data *//**********************************************************/static struct l3_process*dss1_new_l3_process(struct PStack *st, int cr){  struct l3_process *proc;   if (!(proc = new_l3_process(st, cr)))      return(NULL);   proc->prot.dss1.invoke_id = 0;   proc->prot.dss1.remote_operation = 0;   proc->prot.dss1.uus1_data[0] = '\0';      return(proc);} /* dss1_new_l3_process *//************************************************//* free a l3 process and all dss1 specific data *//************************************************/ static voiddss1_release_l3_process(struct l3_process *p){   free_invoke_id(p->st,p->prot.dss1.invoke_id);   release_l3_process(p);} /* dss1_release_l3_process */ /********************************************************//* search a process with invoke id id and dummy callref *//********************************************************/static struct l3_process *l3dss1_search_dummy_proc(struct PStack *st, int id){ struct l3_process *pc = st->l3.proc; /* start of processes */  if (!id) return(NULL);  while (pc)   { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))       return(pc);     pc = pc->next;   }   return(NULL);} /* l3dss1_search_dummy_proc *//*******************************************************************//* called when a facility message with a dummy callref is received *//* and a return result is delivered. id specifies the invoke id.   *//*******************************************************************/ static void l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen){ isdn_ctrl ic;  struct IsdnCardState *cs;  struct l3_process *pc = NULL;   if ((pc = l3dss1_search_dummy_proc(st, id)))   { L3DelTimer(&pc->timer); /* remove timer */     cs = pc->st->l1.hardware;     ic.driver = cs->myid;     ic.command = ISDN_STAT_PROT;     ic.arg = DSS1_STAT_INVOKE_RES;     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;     ic.parm.dss1_io.proc = pc->prot.dss1.proc;     ic.parm.dss1_io.timeout= 0;     ic.parm.dss1_io.datalen = nlen;     ic.parm.dss1_io.data = p;     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);     pc->prot.dss1.invoke_id = 0; /* reset id */     cs->iif.statcallb(&ic);     dss1_release_l3_process(pc);    }  else   l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);} /* l3dss1_dummy_return_result *//*******************************************************************//* called when a facility message with a dummy callref is received *//* and a return error is delivered. id specifies the invoke id.    *//*******************************************************************/ static void l3dss1_dummy_error_return(struct PStack *st, int id, ulong error){ isdn_ctrl ic;  struct IsdnCardState *cs;  struct l3_process *pc = NULL;   if ((pc = l3dss1_search_dummy_proc(st, id)))   { L3DelTimer(&pc->timer); /* remove timer */     cs = pc->st->l1.hardware;     ic.driver = cs->myid;     ic.command = ISDN_STAT_PROT;     ic.arg = DSS1_STAT_INVOKE_ERR;     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;     ic.parm.dss1_io.proc = pc->prot.dss1.proc;     ic.parm.dss1_io.timeout= error;     ic.parm.dss1_io.datalen = 0;     ic.parm.dss1_io.data = NULL;     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);     pc->prot.dss1.invoke_id = 0; /* reset id */     cs->iif.statcallb(&ic);     dss1_release_l3_process(pc);    }  else   l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);} /* l3dss1_error_return *//*******************************************************************//* called when a facility message with a dummy callref is received *//* and a invoke is delivered. id specifies the invoke id.          *//*******************************************************************/ static void l3dss1_dummy_invoke(struct PStack *st, int cr, int id,                     int ident, u_char *p, u_char nlen){ isdn_ctrl ic;  struct IsdnCardState *cs;    l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",               (cr == -1) ? "local" : "broadcast",id,ident,nlen);  if (cr >= -1) return; /* ignore local data */  cs = st->l1.hardware;  ic.driver = cs->myid;  ic.command = ISDN_STAT_PROT;  ic.arg = DSS1_STAT_INVOKE_BRD;  ic.parm.dss1_io.hl_id = id;  ic.parm.dss1_io.ll_id = 0;  ic.parm.dss1_io.proc = ident;  ic.parm.dss1_io.timeout= 0;  ic.parm.dss1_io.datalen = nlen;  ic.parm.dss1_io.data = p;  cs->iif.statcallb(&ic);} /* l3dss1_dummy_invoke */static voidl3dss1_parse_facility(struct PStack *st, struct l3_process *pc,                      int cr, u_char * p){	int qd_len = 0;	unsigned char nlen = 0, ilen, cp_tag;	int ident, id;	ulong err_ret;	if (pc) 		st = pc->st; /* valid Stack */	else		if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */	p++;	qd_len = *p++;	if (qd_len == 0) {		l3_debug(st, "qd_len == 0");		return;	}	if ((*p & 0x1F) != 0x11) {	/* Service discriminator, supplementary service */		l3_debug(st, "supplementary service != 0x11");		return;	}	while (qd_len > 0 && !(*p & 0x80)) {	/* extension ? */		p++;		qd_len--;	}	if (qd_len < 2) {		l3_debug(st, "qd_len < 2");		return;	}	p++;	qd_len--;	if ((*p & 0xE0) != 0xA0) {	/* class and form */		l3_debug(st, "class and form != 0xA0");		return;	}               cp_tag = *p & 0x1F; /* remember tag value */        p++;	qd_len--;	if (qd_len < 1)           { l3_debug(st, "qd_len < 1");	    return;	  }	if (*p & 0x80)           { /* length format indefinite or limited */	    nlen = *p++ & 0x7F; /* number of len bytes or indefinite */            if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||                (nlen > 1))   	     { l3_debug(st, "length format error or not implemented");	       return;             }            if (nlen == 1)	     { nlen = *p++; /* complete length */               qd_len--;             }             else	     { qd_len -= 2; /* trailing null bytes */               if ((*(p+qd_len)) || (*(p+qd_len+1)))		{ l3_debug(st,"length format indefinite error");                  return;                }               nlen = qd_len;             }	  }        else	  { nlen = *p++;	    qd_len--;          } 	if (qd_len < nlen)           { l3_debug(st, "qd_len < nlen");	    return;	  }	qd_len -= nlen;	if (nlen < 2)           { l3_debug(st, "nlen < 2");	    return;	  }        if (*p != 0x02)           {  /* invoke identifier tag */	     l3_debug(st, "invoke identifier tag !=0x02");	     return;	  }	p++;	nlen--;	if (*p & 0x80)           { /* length format */	    l3_debug(st, "invoke id length format 2");	    return;	  }	ilen = *p++;	nlen--;	if (ilen > nlen || ilen == 0)           { l3_debug(st, "ilen > nlen || ilen == 0");	    return;	  }	nlen -= ilen;	id = 0;	while (ilen > 0)           { id = (id << 8) | (*p++ & 0xFF);	/* invoke identifier */	    ilen--;	  }	switch (cp_tag) {	/* component tag */		case 1:	/* invoke */				if (nlen < 2) {					l3_debug(st, "nlen < 2 22");					return;				}				if (*p != 0x02) {	/* operation value */					l3_debug(st, "operation value !=0x02");					return;				}				p++;				nlen--;				ilen = *p++;				nlen--;				if (ilen > nlen || ilen == 0) {					l3_debug(st, "ilen > nlen || ilen == 0 22");					return;				}				nlen -= ilen;				ident = 0;				while (ilen > 0) {					ident = (ident << 8) | (*p++ & 0xFF);					ilen--;				}                                if (!pc) 			         { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);                                   return;                                 } #if HISAX_DE_AOC			{#define FOO1(s,a,b) \	    while(nlen > 1) {		\		    int ilen = p[1];	\		    if(nlen < ilen+2) {	\			    l3_debug(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) {					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;														     st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);									}														     if (st->l3.debug & L3_DEB_CHARGE) {														     if (*(p + 2) == 0) {														     l3_debug(st, "charging info during %d", pc->para.chargeinfo);									}								   else {														     l3_debug(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;																      st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);									}																      if (st->l3.debug & L3_DEB_CHARGE) {																      l3_debug(st, "charging info final %d", pc->para.chargeinfo);									}									}								   ))))))							break;					default:                                                       l3_debug(st, "invoke break invalid ident %02x",ident);						break;				}#undef FOO1			}#else  /* not HISAX_DE_AOC */                        l3_debug(st, "invoke break");#endif /* not HISAX_DE_AOC */			break;		case 2:	/* return result */			 /* if no process available handle separately */                         if (!pc)			 { if (cr == -1)                              l3dss1_dummy_return_result(st, id, p, nlen);                           return;                          }                           if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))                          { /* Diversion successful */                            free_invoke_id(st,pc->prot.dss1.invoke_id);                            pc->prot.dss1.remote_result = 0; /* success */                                 pc->prot.dss1.invoke_id = 0;                            pc->redir_result = pc->prot.dss1.remote_result;                             L3L4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */                        else                          l3_debug(st,"return error unknown identifier");			break;		case 3:	/* return error */                            err_ret = 0;	                    if (nlen < 2)                               { l3_debug(st, "return error nlen < 2");	                        return;	                      }                            if (*p != 0x02)                               { /* result tag */	                        l3_debug(st, "invoke error tag !=0x02");	                        return;	                      }	                    p++;	                    nlen--;	                    if (*p > 4)                               { /* length format */	                        l3_debug(st, "invoke return errlen > 4 ");	                        return;	                      }	                    ilen = *p++;	                    nlen--;	                    if (ilen > nlen || ilen == 0)                               { l3_debug(st, "error return ilen > nlen || ilen == 0");	                        return;	                       }	                    nlen -= ilen;	                    while (ilen > 0)                              { err_ret = (err_ret << 8) | (*p++ & 0xFF);	/* error value */	                       ilen--;	                     }			 /* if no process available handle separately */                         if (!pc)			 { if (cr == -1)                             l3dss1_dummy_error_return(st, id, err_ret);                           return;                          }                           if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))                          { /* Deflection error */                            free_invoke_id(st,pc->prot.dss1.invoke_id);                            pc->prot.dss1.remote_result = err_ret; /* result */                            pc->prot.dss1.invoke_id = 0;                             pc->redir_result = pc->prot.dss1.remote_result;                             L3L4(st, CC_REDIR | INDICATION, pc);                            } /* Deflection error */                        else                          l3_debug(st,"return result unknown identifier");			break;		default:			l3_debug(st, "facility default break tag=0x%02x",cp_tag);			break;	}}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_message_cause(struct l3_process *pc, u_char mt, u_char cause){	struct sk_buff *skb;	u_char tmp[16];	u_char *p = tmp;

⌨️ 快捷键说明

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