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

📄 auerisdn_b.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		auerisdn_bchange(ip, paketsize);}/* Send activation/deactivation state to L2 */static void auerisdn_bconf(struct auerisdnbc *bc){	unsigned long flags;	struct sk_buff *skb;	if (bc->mode == L1_MODE_NULL) {		auerisdn_b_l1l2(bc, PH_DEACTIVATE | INDICATION, NULL);		/* recycle old txskb */		spin_lock_irqsave(&bc->txskb_lock, flags);		skb = bc->txskb;		bc->txskb = NULL;		spin_unlock_irqrestore(&bc->txskb_lock, flags);		if (skb) {			skb_pull(skb, skb->len);			auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,					(void *) skb->truesize);			dev_kfree_skb_any(skb);		}	} else {		auerisdn_b_l1l2(bc, PH_ACTIVATE | INDICATION, NULL);	}}/* B channel setup completion handler */static void auerisdn_bmode_complete(struct urb *urb){	struct auerswald *cp;	struct auerbuf *bp = (struct auerbuf *) urb->context;	struct auerisdnbc *bc;	int channel;	dbg("auerisdn_bmode_complete called");	cp = ((struct auerswald *) ((char *) (bp->list) -				    (unsigned				     long) (&((struct auerswald *) 0)->					    bufctl)));	/* select the B-channel */	channel = le16_to_cpu(bp->dr->wIndex);	channel -= AUH_B1CHANNEL;	if (channel < 0)		goto rel;	if (channel >= AUISDN_BCHANNELS)		goto rel;	bc = &cp->isdn.bc[channel];	/* Check for success */	if (urb->status) {		err("complete with non-zero status: %d", urb->status);	} else {		bc->mode = *bp->bufp;	}	/* Signal current mode to L2 */	auerisdn_bconf(bc);	/* reuse the buffer */      rel:auerbuf_releasebuf(bp);	/* Wake up all processes waiting for a buffer */	wake_up(&cp->bufferwait);}/* Setup a B channel transfer mode */static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode){	struct auerswald *cp = bc->cp;	struct auerbuf *bp;	int ret;	/* don't allow activation on disconnect */	if (cp->disconnecting) {		mode = L1_MODE_NULL;		/* Else check if something changed */	} else if (bc->mode != mode) {		if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) {			/* init RX hdlc decoder */			dbg("rcv init");			isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0);			/* init TX hdlc decoder */			dbg("out init");			isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0);		}		/* stop ASAP */		if (mode == L1_MODE_NULL)			bc->mode = mode;		if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) {			/* Activation or deactivation required */			/* get a buffer for the command */			bp = auerbuf_getbuf(&cp->bufctl);			/* if no buffer available: can't change the mode */			if (!bp) {				err("auerisdn_bmode: no data buffer available");				return;			}			/* fill the control message */			bp->dr->bRequestType = AUT_WREQ;			bp->dr->bRequest = AUV_CHANNELCTL;			if (mode != L1_MODE_NULL)				bp->dr->wValue = cpu_to_le16(1);			else				bp->dr->wValue = cpu_to_le16(0);			bp->dr->wIndex =			    cpu_to_le16(AUH_B1CHANNEL + bc->channel);			bp->dr->wLength = cpu_to_le16(0);			*bp->bufp = mode;			FILL_CONTROL_URB(bp->urbp, cp->usbdev,					 usb_sndctrlpipe(cp->usbdev, 0),					 (unsigned char *) bp->dr,					 bp->bufp, 0,					 (usb_complete_t)					 auerisdn_bmode_complete, bp);			/* submit the control msg */			ret =			    auerchain_submit_urb(&cp->controlchain,						 bp->urbp);			if (ret) {				bp->urbp->status = ret;				auerisdn_bmode_complete(bp->urbp);			}			return;		}	}	/* new mode is set */	bc->mode = mode;	/* send confirmation to L2 */	auerisdn_bconf(bc);}/* B-channel transfer function L2->L1 */void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg,		     unsigned int channel){	struct auerhisax *ahp;	struct auerisdnbc *bc;	struct auerswald *cp;	struct sk_buff *skb;	unsigned long flags;	int mode;	cp = NULL;	ahp = (struct auerhisax *) ifc->priv;	if (ahp)		cp = ahp->cp;	if (cp && !cp->disconnecting) {		/* normal execution */		bc = &cp->isdn.bc[channel];		switch (pr) {		case PH_ACTIVATE | REQUEST:	/* activation request */			mode = (int) arg;	/* one of the L1_MODE constants */			dbg("B%d, PH_ACTIVATE_REQUEST Mode = %d",			    bc->channel + 1, mode);			auerisdn_bmode(bc, mode);			break;		case PH_DEACTIVATE | REQUEST:	/* deactivation request */			dbg("B%d, PH_DEACTIVATE_REQUEST", bc->channel + 1);			auerisdn_bmode(bc, L1_MODE_NULL);			break;		case PH_DATA | REQUEST:	/* Transmit data request */			skb = (struct sk_buff *) arg;			spin_lock_irqsave(&bc->txskb_lock, flags);			if (bc->txskb) {				err("Overflow in B channel TX");				skb_pull(skb, skb->len);				dev_kfree_skb_any(skb);			} else {				if (cp->disconnecting				    || (bc->mode == L1_MODE_NULL)) {					skb_pull(skb, skb->len);					spin_unlock_irqrestore(&bc->							       txskb_lock,							       flags);					auerisdn_b_l1l2(bc,							PH_DATA | CONFIRM,							(void *) skb->							truesize);					dev_kfree_skb_any(skb);					goto next;				} else					bc->txskb = skb;			}			spin_unlock_irqrestore(&bc->txskb_lock, flags);		      next:break;		default:			warn("pr %#x\n", pr);			break;		}	} else {		/* hisax interface is down */		switch (pr) {		case PH_ACTIVATE | REQUEST:	/* activation request */			dbg("B channel: PH_ACTIVATE | REQUEST with interface down");			/* don't answer this request! Endless... */			break;		case PH_DEACTIVATE | REQUEST:	/* deactivation request */			dbg("B channel: PH_DEACTIVATE | REQUEST with interface down");			ifc->l1l2(ifc, PH_DEACTIVATE | INDICATION, NULL);			break;		case PH_DATA | REQUEST:	/* Transmit data request */			dbg("B channel: PH_DATA | REQUEST with interface down");			skb = (struct sk_buff *) arg;			/* free data buffer */			if (skb) {				skb_pull(skb, skb->len);				dev_kfree_skb_any(skb);			}			/* send confirmation back to layer 2 */			ifc->l1l2(ifc, PH_DATA | CONFIRM, NULL);			break;		default:			warn("pr %#x\n", pr);			break;		}	}}/* Completion handler for B channel input endpoint */void auerisdn_intbi_complete(struct urb *urb){	unsigned int bytecount;	unsigned char *ucp;	int channel;	unsigned int syncbit;	unsigned int syncdata;	struct auerisdnbc *bc;	struct sk_buff *skb;	int count;	int status;	struct auerswald *cp = (struct auerswald *) urb->context;	/* do not respond to an error condition */	if (urb->status != 0) {		dbg("nonzero URB status = %d", urb->status);		return;	}	if (cp->disconnecting)		return;	/* Parse and extract the header information */	bytecount = urb->actual_length;	ucp = cp->isdn.intbi_bufp;	if (!bytecount)		return;		/* no data */	channel = *ucp & AUH_TYPEMASK;	syncbit = *ucp & AUH_SYNC;	ucp++;	bytecount--;	channel -= AUH_B1CHANNEL;	if (channel < 0)		return;		/* unknown data channel, no B1,B2 */	if (channel >= AUISDN_BCHANNELS)		return;		/* unknown data channel, no B1,B2 */	bc = &cp->isdn.bc[channel];	if (!bytecount)		return;	/* Calculate amount of bytes which are free in tx device buffer */	bc->txfree = ((255 - *ucp++) * bc->ofsize) / 256;	/* dbg ("%d Bytes free in TX buffer", bc->txfree); */	bytecount--;	/* Next Byte: TX sync information */	if (syncbit) {		if (!bytecount)			goto int_tx;		syncdata = *ucp++;		dbg("Sync data = %d", syncdata);		bytecount--;	}	/* The rest of the paket is plain data */	if (!bytecount)		goto int_tx;	/* dump ("RX Data is:", ucp, bytecount); */	/* Send B channel data to upper layers */	while (bytecount > 0) {		if (bc->mode == L1_MODE_NULL) {			/* skip the data. Nobody needs them */			status = 0;			bytecount = 0;		} else if (bc->mode == L1_MODE_TRANS) {			{	/* swap rx bytes */				register unsigned char *dest = bc->rxbuf;				status = bytecount;				for (; bytecount; bytecount--)					*dest++ =					    isdnhdlc_bit_rev_tab[*ucp++];			}		} else {			status = isdnhdlc_decode(&bc->inp_hdlc_state, ucp,						 bytecount, &count,						 bc->rxbuf, AUISDN_RXSIZE);			ucp += count;			bytecount -= count;		}		if (status > 0) {			/* Good frame received */			if (!(skb = dev_alloc_skb(status))) {				warn("receive out of memory");				break;			}			memcpy(skb_put(skb, status), bc->rxbuf, status);			/* dump ("HDLC Paket", bc->rxbuf, status); */			auerisdn_b_l1l2(bc, PH_DATA | INDICATION, skb);			/* these errors may actually happen at the start of a connection! */		} else if (status == -HDLC_CRC_ERROR) {			dbg("CRC error");		} else if (status == -HDLC_FRAMING_ERROR) {			dbg("framing error");		} else if (status == -HDLC_LENGTH_ERROR) {			dbg("length error");		}	}      int_tx:			/* serve the outgoing B channel */	auerisdn_bserv(&cp->isdn);}/* Stop the B channel activity. The device is disconnecting *//* This function is called after cp->disconnecting is true */unsigned int auerisdn_b_disconnect(struct auerswald *cp){	unsigned int u;	struct auerisdnbc *bc;	unsigned int result = 0;	/* Close the B channels */	for (u = 0; u < AUISDN_BCHANNELS; u++) {		bc = &cp->isdn.bc[u];		if (bc->mode != L1_MODE_NULL) {	/* B channel is active */			auerisdn_bmode(bc, L1_MODE_NULL);			result = 1;		}	}	/* return 1 if there is B channel traffic */	return result;}

⌨️ 快捷键说明

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