📄 callc.c
字号:
return (NULL);}static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result){ isdn_ctrl ic; ic.driver = cs->myid; ic.command = ISDN_STAT_REDIR; ic.arg = chan; (ulong)(ic.parm.num[0]) = result; cs->iif.statcallb(&ic);} /* stat_redir_result */static voiddchan_l3l4(struct PStack *st, int pr, void *arg){ struct l3_process *pc = arg; struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp; if(!pc) return; if (pr == (CC_SETUP | INDICATION)) { if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) { pc->para.cause = 0x11; /* User busy */ L4L3(pc->st, CC_REJECT | REQUEST, pc); } else { chanp->proc = pc; pc->chan = chanp; FsmEvent(&chanp->fi, EV_SETUP_IND, NULL); } return; } if (!(chanp = pc->chan)) return; switch (pr) { case (CC_MORE_INFO | INDICATION): FsmEvent(&chanp->fi, EV_SETUP_IND, NULL); break; case (CC_DISCONNECT | INDICATION): FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL); break; case (CC_RELEASE | CONFIRM): FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_SUSPEND | CONFIRM): FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_RESUME | CONFIRM): FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); break; case (CC_RESUME_ERR): FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_RELEASE | INDICATION): FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_SETUP_COMPL | INDICATION): FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL); break; case (CC_SETUP | CONFIRM): FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); break; case (CC_CHARGE | INDICATION): FsmEvent(&chanp->fi, EV_CINF, NULL); break; case (CC_NOSETUP_RSP): FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL); break; case (CC_SETUP_ERR): FsmEvent(&chanp->fi, EV_SETUP_ERR, NULL); break; case (CC_CONNECT_ERR): FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL); break; case (CC_RELEASE_ERR): FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_PROCEED_SEND | INDICATION): case (CC_PROCEEDING | INDICATION): case (CC_ALERTING | INDICATION): case (CC_PROGRESS | INDICATION): case (CC_NOTIFY | INDICATION): break; case (CC_REDIR | INDICATION): stat_redir_result(cs, chanp->chan, pc->redir_result); break; default: if (chanp->debug & 0x800) { HiSax_putstatus(chanp->cs, "Ch", "%d L3->L4 unknown primitiv %#x", chanp->chan, pr); } }}static voiddummy_pstack(struct PStack *st, int pr, void *arg) { printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);}static intinit_PStack(struct PStack **stp) { *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); if (!*stp) return -ENOMEM; (*stp)->next = NULL; (*stp)->l1.l1hw = dummy_pstack; (*stp)->l1.l1tei = dummy_pstack; (*stp)->l1.l2l1 = dummy_pstack; (*stp)->l2.l1l2 = dummy_pstack; (*stp)->l2.l2tei = dummy_pstack; (*stp)->l2.l3l2 = dummy_pstack; (*stp)->l3.l2l3 = dummy_pstack; (*stp)->l3.l3ml3 = dummy_pstack; (*stp)->l3.l4l3 = dummy_pstack; (*stp)->lli.l3l4 = dummy_pstack; (*stp)->ma.layer = dummy_pstack; return 0;}static intinit_d_st(struct Channel *chanp){ struct PStack *st; struct IsdnCardState *cs = chanp->cs; char tmp[16]; int err; err = init_PStack(&chanp->d_st); if (err) return err; st = chanp->d_st; st->next = NULL; HiSax_addlist(cs, st); setstack_HiSax(st, cs); st->l2.sap = 0; st->l2.tei = -1; st->l2.flag = 0; test_and_set_bit(FLG_MOD128, &st->l2.flag); test_and_set_bit(FLG_LAPD, &st->l2.flag); test_and_set_bit(FLG_ORIG, &st->l2.flag); st->l2.maxlen = MAX_DFRAME_LEN; st->l2.window = 1; st->l2.T200 = 1000; /* 1000 milliseconds */ st->l2.N200 = 3; /* try 3 times */ st->l2.T203 = 10000; /* 10000 milliseconds */ if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) sprintf(tmp, "DCh%d Q.921 ", chanp->chan); else sprintf(tmp, "DCh Q.921 "); setstack_isdnl2(st, tmp); setstack_l3dc(st, chanp); st->lli.userdata = chanp; st->lli.l2writewakeup = NULL; st->lli.l3l4 = dchan_l3l4; return 0;}static voidcallc_debug(struct FsmInst *fi, char *fmt, ...){ va_list args; struct Channel *chanp = fi->userdata; char tmp[16]; va_start(args, fmt); sprintf(tmp, "Ch%d callc ", chanp->chan); VHiSax_putstatus(chanp->cs, tmp, fmt, args); va_end(args);}static intinit_chan(int chan, struct IsdnCardState *csta){ struct Channel *chanp = csta->channel + chan; int err; chanp->cs = csta; chanp->bcs = csta->bcs + chan; chanp->chan = chan; chanp->incoming = 0; chanp->debug = 0; chanp->Flags = 0; chanp->leased = 0; err = init_PStack(&chanp->b_st); if (err) return err; chanp->b_st->l1.delay = DEFAULT_B_DELAY; chanp->fi.fsm = &callcfsm; chanp->fi.state = ST_NULL; chanp->fi.debug = 0; chanp->fi.userdata = chanp; chanp->fi.printdebug = callc_debug; FsmInitTimer(&chanp->fi, &chanp->dial_timer); FsmInitTimer(&chanp->fi, &chanp->drel_timer); if (!chan || (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags) && chan < 2)) { err = init_d_st(chanp); if (err) return err; } else { chanp->d_st = csta->channel->d_st; } chanp->data_open = 0; return 0;}intCallcNewChan(struct IsdnCardState *csta) { int i, err; chancount += 2; err = init_chan(0, csta); if (err) return err; err = init_chan(1, csta); if (err) return err; printk(KERN_INFO "HiSax: 2 channels added\n"); for (i = 0; i < MAX_WAITING_CALLS; i++) { err = init_chan(i+2,csta); if (err) return err; } printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n"); if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); L4L3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL); } return (0);}static voidrelease_d_st(struct Channel *chanp){ struct PStack *st = chanp->d_st; if (!st) return; releasestack_isdnl2(st); releasestack_isdnl3(st); HiSax_rmlist(st->l1.hardware, st); kfree(st); chanp->d_st = NULL;}voidCallcFreeChan(struct IsdnCardState *csta){ int i; for (i = 0; i < 2; i++) { FsmDelTimer(&csta->channel[i].drel_timer, 74); FsmDelTimer(&csta->channel[i].dial_timer, 75); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) release_d_st(csta->channel + i); if (csta->channel[i].b_st) { release_b_st(csta->channel + i); kfree(csta->channel[i].b_st); csta->channel[i].b_st = NULL; } else printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); } else csta->channel[i].d_st = NULL; }}static voidlldata_handler(struct PStack *st, int pr, void *arg){ struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { case (DL_DATA | INDICATION): if (chanp->data_open) { if (chanp->debug & 0x800) link_debug(chanp, 0, "lldata: %d", skb->len); chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); } else { link_debug(chanp, 0, "lldata: channel not open"); dev_kfree_skb(skb); } break; case (DL_ESTABLISH | INDICATION): case (DL_ESTABLISH | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); break; case (DL_RELEASE | INDICATION): case (DL_RELEASE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_REL, NULL); break; default: printk(KERN_WARNING "lldata_handler unknown primitive %#x\n", pr); break; }}static voidlltrans_handler(struct PStack *st, int pr, void *arg){ struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | INDICATION): if (chanp->data_open) { if (chanp->debug & 0x800) link_debug(chanp, 0, "lltrans: %d", skb->len); chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); } else { link_debug(chanp, 0, "lltrans: channel not open"); dev_kfree_skb(skb); } break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); break; case (PH_DEACTIVATE | INDICATION): case (PH_DEACTIVATE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_REL, NULL); break; default: printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n", pr); break; }}static voidll_writewakeup(struct PStack *st, int len){ struct Channel *chanp = st->lli.userdata; isdn_ctrl ic; if (chanp->debug & 0x800) link_debug(chanp, 0, "llwakeup: %d", len); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_BSENT; ic.arg = chanp->chan; ic.parm.length = len; chanp->cs->iif.statcallb(&ic);}static intinit_b_st(struct Channel *chanp, int incoming){ struct PStack *st = chanp->b_st; struct IsdnCardState *cs = chanp->cs; char tmp[16]; st->l1.hardware = cs; if (chanp->leased) st->l1.bc = chanp->chan & 1; else st->l1.bc = chanp->proc->para.bchannel - 1; switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): case (ISDN_PROTO_L2_HDLC): st->l1.mode = L1_MODE_HDLC; break; case (ISDN_PROTO_L2_HDLC_56K): st->l1.mode = L1_MODE_HDLC_56K; break; case (ISDN_PROTO_L2_TRANS): st->l1.mode = L1_MODE_TRANS; break; case (ISDN_PROTO_L2_MODEM): st->l1.mode = L1_MODE_V32; break; case (ISDN_PROTO_L2_FAX): st->l1.mode = L1_MODE_FAX; break; } chanp->bcs->conmsg = NULL; if (chanp->bcs->BC_SetStack(st, chanp->bcs)) return (-1); st->l2.flag = 0; test_and_set_bit(FLG_LAPB, &st->l2.flag); st->l2.maxlen = MAX_DATA_SIZE; if (!incoming) test_and_set_bit(FLG_ORIG, &st->l2.flag); st->l2.T200 = 1000; /* 1000 milliseconds */ st->l2.window = 7; st->l2.N200 = 4; /* try 4 times */ st->l2.T203 = 5000; /* 5000 milliseconds */ st->l3.debug = 0; switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): sprintf(tmp, "Ch%d X.75", chanp->chan); setstack_isdnl2(st, tmp); setstack_l3bc(st, chanp); st->l3.l2l3 = lldata_handler; st->lli.userdata = chanp; st->lli.l1writewakeup = NULL; st->lli.l2writewakeup = ll_writewakeup; st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; break; case (ISDN_PROTO_L2_HDLC): case (ISDN_PROTO_L2_HDLC_56K): case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): st->l2.l1l2 = lltrans_handler; st->lli.userdata = chanp; st->lli.l1writewakeup = ll_writewakeup; setstack_transl2(st); setstack_l3bc(st, chanp); break; } test_and_set_bit(FLG_START_B, &chanp->Flags); return (0);}static voidleased_l4l3(struct PStack *st, int pr, void *arg){ struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { case (DL_DATA | REQUEST): link_debug(chanp, 0, "leased line d-channel DATA"); dev_kfree_skb(skb); break; case (DL_ESTABLISH | REQUEST): L2L1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): break; default: printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n", pr); break; }}static voidleased_l1l2(struct PStack *st, int pr, void *arg){ struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; int i,event = EV_LEASED_REL; switch (pr) { case (PH_DATA | INDICATION): link_debug(chanp, 0, "leased line d-channel DATA"); dev_kfree_skb(skb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -