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

📄 capidrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * data of skb used in s_cmsg,	 * free data when s_cmsg is not used again	 * thanks to Lars Heete <hel@admin.de>	 */	kfree_skb(skb);}/* ------------------------------------------------------------------- */#define PUTBYTE_TO_STATUS(card, byte) \	do { \		*(card)->q931_write++ = (byte); \        	if ((card)->q931_write > (card)->q931_end) \	  		(card)->q931_write = (card)->q931_buf; \	} while (0)static void handle_dtrace_data(capidrv_contr *card,			     int send, int level2, u8 *data, u16 len){    	u8 *p, *end;    	isdn_ctrl cmd;    	if (!len) {		printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",				card->contrnr, len);		return;	}	if (level2) {		PUTBYTE_TO_STATUS(card, 'D');		PUTBYTE_TO_STATUS(card, '2');        	PUTBYTE_TO_STATUS(card, send ? '>' : '<');        	PUTBYTE_TO_STATUS(card, ':');	} else {        	PUTBYTE_TO_STATUS(card, 'D');        	PUTBYTE_TO_STATUS(card, '3');        	PUTBYTE_TO_STATUS(card, send ? '>' : '<');        	PUTBYTE_TO_STATUS(card, ':');    	}	for (p = data, end = data+len; p < end; p++) {		u8 w;		PUTBYTE_TO_STATUS(card, ' ');		w = (*p >> 4) & 0xf;		PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);		w = *p & 0xf;		PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);	}	PUTBYTE_TO_STATUS(card, '\n');	cmd.command = ISDN_STAT_STAVAIL;	cmd.driver = card->myid;	cmd.arg = len*3+5;	card->interface.statcallb(&cmd);}/* ------------------------------------------------------------------- */static _cmsg cmdcmsg;static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card){	switch (c->arg) {	case 1:		debugmode = (int)(*((unsigned int *)c->parm.num));		printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",				card->contrnr, debugmode);		return 0;	default:		printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",				card->contrnr, c->arg);		return -EINVAL;	}	return -EINVAL;}/* * Handle leased lines (CAPI-Bundling) */struct internal_bchannelinfo {   unsigned short channelalloc;   unsigned short operation;   unsigned char  cmask[31];};static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep){	unsigned long bmask = 0;	int active = !0;	char *s;	int i;	if (strncmp(teln, "FV:", 3) != 0)		return 1;	s = teln + 3;	while (*s && *s == ' ') s++;	if (!*s) return -2;	if (*s == 'p' || *s == 'P') {		active = 0;		s++;	}	if (*s == 'a' || *s == 'A') {		active = !0;		s++;	}	while (*s) {		int digit1 = 0;		int digit2 = 0;		if (!isdigit(*s)) return -3;		while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }		if (digit1 <= 0 && digit1 > 30) return -4;		if (*s == 0 || *s == ',' || *s == ' ') {			bmask |= (1 << digit1);			digit1 = 0;			if (*s) s++;			continue;		}		if (*s != '-') return -5;		s++;		if (!isdigit(*s)) return -3;		while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }		if (digit2 <= 0 && digit2 > 30) return -4;		if (*s == 0 || *s == ',' || *s == ' ') {			if (digit1 > digit2)				for (i = digit2; i <= digit1 ; i++)					bmask |= (1 << i);			else 				for (i = digit1; i <= digit2 ; i++)					bmask |= (1 << i);			digit1 = digit2 = 0;			if (*s) s++;			continue;		}		return -6;	}	if (activep) *activep = active;	if (bmaskp) *bmaskp = bmask;	return 0;}static int FVteln2capi20(char *teln, u8 AdditionalInfo[1+2+2+31]){	unsigned long bmask;	int active;	int rc, i;   	rc = decodeFVteln(teln, &bmask, &active);	if (rc) return rc;	/* Length */	AdditionalInfo[0] = 2+2+31;        /* Channel: 3 => use channel allocation */        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;	/* Operation: 0 => DTE mode, 1 => DCE mode */        if (active) {   		AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;   	} else {   		AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;	}	/* Channel mask array */	AdditionalInfo[5] = 0; /* no D-Channel */	for (i=1; i <= 30; i++)		AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;	return 0;}static int capidrv_command(isdn_ctrl * c, capidrv_contr * card){	isdn_ctrl cmd;	struct capidrv_bchan *bchan;	struct capidrv_plci *plcip;	u8 AdditionalInfo[1+2+2+31];        int rc, isleasedline = 0;	if (c->command == ISDN_CMD_IOCTL)		return capidrv_ioctl(c, card);	switch (c->command) {	case ISDN_CMD_DIAL:{			u8 calling[ISDN_MSNLEN + 3];			u8 called[ISDN_MSNLEN + 2];			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",					card->contrnr,					c->arg,				        c->parm.setup.phone,				        c->parm.setup.si1,				        c->parm.setup.si2,				        c->parm.setup.eazmsn);			bchan = &card->bchans[c->arg % card->nbchan];			if (bchan->plcip) {				printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",					card->contrnr,			        	c->arg, 				        c->parm.setup.phone,				        c->parm.setup.si1,				        c->parm.setup.si2,				        c->parm.setup.eazmsn,				        bchan->plcip->plci);				return 0;			}			bchan->si1 = c->parm.setup.si1;			bchan->si2 = c->parm.setup.si2;			strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));			strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));                        rc = FVteln2capi20(bchan->num, AdditionalInfo);			isleasedline = (rc == 0);			if (rc < 0)				printk(KERN_ERR "capidrv-%d: WARNING: invalid leased linedefinition \"%s\"\n", card->contrnr, bchan->num);			if (isleasedline) {				calling[0] = 0;				called[0] = 0;			        if (debugmode)					printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);			} else {		        	calling[0] = strlen(bchan->mynum) + 2;		        	calling[1] = 0;		     		calling[2] = 0x80;			   	strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);				called[0] = strlen(bchan->num) + 1;				called[1] = 0x80;				strncpy(called + 2, bchan->num, ISDN_MSNLEN);			}			capi_fill_CONNECT_REQ(&cmdcmsg,					      global.ap.applid,					      card->msgid++,					      card->contrnr,	/* adr */					  si2cip(bchan->si1, bchan->si2),	/* cipvalue */					      called,	/* CalledPartyNumber */					      calling,	/* CallingPartyNumber */					      NULL,	/* CalledPartySubaddress */					      NULL,	/* CallingPartySubaddress */					    b1prot(bchan->l2, bchan->l3),	/* B1protocol */					    b2prot(bchan->l2, bchan->l3),	/* B2protocol */					    b3prot(bchan->l2, bchan->l3),	/* B3protocol */					    b1config(bchan->l2, bchan->l3),	/* B1configuration */					      NULL,	/* B2configuration */					      NULL,	/* B3configuration */					      NULL,	/* BC */					      NULL,	/* LLC */					      NULL,	/* HLC */					      /* BChannelinformation */					      isleasedline ? AdditionalInfo : NULL,					      NULL,	/* Keypadfacility */					      NULL,	/* Useruserdata */					      NULL	/* Facilitydataarray */			    );			if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) {				cmd.command = ISDN_STAT_DHUP;				cmd.driver = card->myid;				cmd.arg = (c->arg % card->nbchan);				card->interface.statcallb(&cmd);				return -1;			}			plcip->msgid = cmdcmsg.Messagenumber;			plcip->leasedline = isleasedline;			plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);			send_message(card, &cmdcmsg);			return 0;		}	case ISDN_CMD_ACCEPTD:		bchan = &card->bchans[c->arg % card->nbchan];		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",			       card->contrnr,			       c->arg, bchan->l2, bchan->l3);		capi_fill_CONNECT_RESP(&cmdcmsg,				       global.ap.applid,				       card->msgid++,				       bchan->plcip->plci,	/* adr */				       0,	/* Reject */				       b1prot(bchan->l2, bchan->l3),	/* B1protocol */				       b2prot(bchan->l2, bchan->l3),	/* B2protocol */				       b3prot(bchan->l2, bchan->l3),	/* B3protocol */				       b1config(bchan->l2, bchan->l3),	/* B1configuration */				       NULL,	/* B2configuration */				       NULL,	/* B3configuration */				       NULL,	/* ConnectedNumber */				       NULL,	/* ConnectedSubaddress */				       NULL,	/* LLC */				       NULL,	/* BChannelinformation */				       NULL,	/* Keypadfacility */				       NULL,	/* Useruserdata */				       NULL	/* Facilitydataarray */		);		capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);		plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);		send_message(card, &cmdcmsg);		return 0;	case ISDN_CMD_ACCEPTB:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",			       card->contrnr,			       c->arg);		return -ENOSYS;	case ISDN_CMD_HANGUP:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",			       card->contrnr,			       c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		if (bchan->disconnecting) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",				       card->contrnr,				       c->arg);			return 0;		}		if (bchan->nccip) {			bchan->disconnecting = 1;			capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,						    global.ap.applid,						    card->msgid++,						    bchan->nccip->ncci,						    NULL	/* NCPI */			);			ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);			send_message(card, &cmdcmsg);			return 0;		} else if (bchan->plcip) {			if (bchan->plcip->state == ST_PLCI_INCOMING) {				/*				 * just ignore, we a called from				 * isdn_status_callback(),				 * which will return 0 or 2, this is handled				 * by the CONNECT_IND handler				 */				bchan->disconnecting = 1;				return 0;			} else if (bchan->plcip->plci) {				bchan->disconnecting = 1;				capi_fill_DISCONNECT_REQ(&cmdcmsg,							 global.ap.applid,							 card->msgid++,						      bchan->plcip->plci,							 NULL,	/* BChannelinformation */							 NULL,	/* Keypadfacility */							 NULL,	/* Useruserdata */							 NULL	/* Facilitydataarray */				);				plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);				send_message(card, &cmdcmsg);				return 0;			} else {				printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",				       card->contrnr,				       c->arg);				return -EINVAL;			}		}		printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",				       card->contrnr,				       c->arg);		return -EINVAL;/* ready */	case ISDN_CMD_SETL2:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l2 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETL3:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l3 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETEAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",			       card->contrnr,			       c->parm.num, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);		return 0;	case ISDN_CMD_CLREAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",					card->contrnr, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		bchan->msn[0] = 0;		return 0;	default:		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",					card->contrnr, c->command);		return -EINVAL;	}	return 0;}static int if_command(isdn_ctrl * c){	capidrv_contr *card = findcontrbydriverid(c->driver);	if (card)		return capidrv_command(c, card);	printk(KERN_ERR	     "capidrv: if_command %d called with invalid driverId %d!\n",						c->command, c->driver);	return -ENODEV;}static _cmsg sendcmsg;static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb){	capidrv_contr *card = findcontrbydriverid(id);	capidrv_bchan *bchan;	capidrv_ncci *nccip;	int len = skb->len;	int msglen;	u16 errcode;	u16 datahandle;	if (!card) {		printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",		       id);		return 0;	}	if (debugmode > 4)		printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",					card->contrnr, len, skb, doack);	bchan = &card->bchans[channel % card->nbchan];	nccip = bchan->nccip;	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {		printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",		       card->contrnr, card->name, channel);		return 0;	}	datahandle = nccip->datahandle;	capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,			      nccip->ncci,	/* adr */			      (u32) skb->data,	/* Data */			      skb->len,		/* DataLength */			      datahandle,	/* DataHandle */			      0	/* Flags */	    );	if (capidrv_add_ack(nccip, datahandle, doack ? (int)skb->len : -1) < 0)	   return 0;	capi_cmsg2message(&sendcmsg, sendcmsg.buf);

⌨️ 快捷键说明

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