static int
open_bchannel(struct hfcsusb *hw, struct channel_req *rq)
{
	struct bchannel		*bch;

	if (rq->adr.channel == 0 || rq->adr.channel > 2)
		return -EINVAL;
	if (rq->protocol == ISDN_P_NONE)
		return -EINVAL;

	if (debug & DBG_HFC_CALL_TRACE)
		printk(KERN_DEBUG "%s: %s B%i\n",
		       hw->name, __func__, rq->adr.channel);

	bch = &hw->bch[rq->adr.channel - 1];
	if (test_and_set_bit(FLG_OPEN, &bch->Flags))
		return -EBUSY; 
	test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
	bch->ch.protocol = rq->protocol;
	rq->ch = &bch->ch;

	
	if (rq->adr.channel  == 1)
		hfcsusb_start_endpoint(hw, HFC_CHAN_B1);
	else
		hfcsusb_start_endpoint(hw, HFC_CHAN_B2);

	if (!try_module_get(THIS_MODULE))
		printk(KERN_WARNING "%s: %s:cannot get module\n",
		       hw->name, __func__);
	return 0;
}
static int
open_dchannel(struct hfcsusb *hw, struct mISDNchannel *ch,
	      struct channel_req *rq)
{
	int err = 0;

	if (debug & DEBUG_HW_OPEN)
		printk(KERN_DEBUG "%s: %s: dev(%d) open addr(%i) from %p\n",
		       hw->name, __func__, hw->dch.dev.id, rq->adr.channel,
		       __builtin_return_address(0));
	if (rq->protocol == ISDN_P_NONE)
		return -EINVAL;

	test_and_clear_bit(FLG_ACTIVE, &hw->dch.Flags);
	test_and_clear_bit(FLG_ACTIVE, &hw->ech.Flags);
	hfcsusb_start_endpoint(hw, HFC_CHAN_D);

	
	if (rq->adr.channel == 1) {
		if (hw->fifos[HFCUSB_PCM_RX].pipe) {
			hfcsusb_start_endpoint(hw, HFC_CHAN_E);
			set_bit(FLG_ACTIVE, &hw->ech.Flags);
			_queue_data(&hw->ech.dev.D, PH_ACTIVATE_IND,
				    MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
		} else
			return -EINVAL;
	}

	if (!hw->initdone) {
		hw->protocol = rq->protocol;
		if (rq->protocol == ISDN_P_TE_S0) {
			err = create_l1(&hw->dch, hfc_l1callback);
			if (err)
				return err;
		}
		setPortMode(hw);
		ch->protocol = rq->protocol;
		hw->initdone = 1;
	} else {
		if (rq->protocol != ch->protocol)
			return -EPROTONOSUPPORT;
	}

	if (((ch->protocol == ISDN_P_NT_S0) && (hw->dch.state == 3)) ||
	    ((ch->protocol == ISDN_P_TE_S0) && (hw->dch.state == 7)))
		_queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
			    0, NULL, GFP_KERNEL);
	rq->ch = ch;
	if (!try_module_get(THIS_MODULE))
		printk(KERN_WARNING "%s: %s: cannot get module\n",
		       hw->name, __func__);
	return 0;
}
示例#3
0
static int
hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
{
	struct bchannel		*bch = container_of(ch, struct bchannel, ch);
	struct hfcsusb		*hw = bch->hw;
	int			ret = -EINVAL;
	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
	u_long			flags;

	if (debug & DBG_HFC_CALL_TRACE)
		printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);

	switch (hh->prim) {
	case PH_DATA_REQ:
		spin_lock_irqsave(&hw->lock, flags);
		ret = bchannel_senddata(bch, skb);
		spin_unlock_irqrestore(&hw->lock, flags);
		if (debug & DBG_HFC_CALL_TRACE)
			printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
				hw->name, __func__, ret);
		if (ret > 0) {
			
			queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
			ret = 0;
		}
		return ret;
	case PH_ACTIVATE_REQ:
		if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
			hfcsusb_start_endpoint(hw, bch->nr);
			ret = hfcsusb_setup_bch(bch, ch->protocol);
		} else
			ret = 0;
		if (!ret)
			_queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
				0, NULL, GFP_KERNEL);
		break;
	case PH_DEACTIVATE_REQ:
		deactivate_bchannel(bch);
		_queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY,
			0, NULL, GFP_KERNEL);
		ret = 0;
		break;
	}
	if (!ret)
		dev_kfree_skb(skb);
	return ret;
}