📄 callc.c
字号:
ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_DHUP; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); chanp->Flags = 0; } else { test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_DHUP"); if (chanp->cs->protocol == ISDN_PTYPE_EURO) { chanp->proc->para.cause = 0x2f; chanp->proc->para.loc = 0; } else { chanp->proc->para.cause = 0x70; chanp->proc->para.loc = 0; } lli_deliver_cause(chanp, &ic); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_DHUP; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc); chanp->Flags = 0; chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); } chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);}/* *INDENT-OFF* */static struct FsmNode fnlist[] HISAX_INITDATA ={ {ST_NULL, EV_DIAL, lli_prep_dialout}, {ST_NULL, EV_RESUME, lli_prep_dialout}, {ST_NULL, EV_SETUP_IND, lli_deliver_call}, {ST_NULL, EV_SHUTDOWN_D, lli_shutdown_d}, {ST_NULL, EV_DLRL, lli_go_null}, {ST_NULL, EV_DLEST, lli_d_established}, {ST_NULL, EV_ESTABLISH, lli_establish_d}, {ST_OUT_WAIT_D, EV_DLEST, lli_do_dialout}, {ST_OUT_WAIT_D, EV_DLRL, lli_no_dchan}, {ST_OUT_WAIT_D, EV_HANGUP, lli_no_dchan}, {ST_IN_WAIT_D, EV_DLEST, lli_do_action}, {ST_IN_WAIT_D, EV_DLRL, lli_no_dchan_in}, {ST_IN_WAIT_D, EV_ACCEPTD, lli_start_dchan}, {ST_IN_WAIT_D, EV_HANGUP, lli_start_dchan}, {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out}, {ST_OUT_DIAL, EV_HANGUP, lli_cancel_call}, {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_OUT_DIAL, EV_RELEASE_IND, lli_received_d_rel}, {ST_OUT_DIAL, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp}, {ST_OUT_DIAL, EV_SETUP_ERR, lli_setup_err}, {ST_OUT_DIAL, EV_DLRL, lli_got_dlrl}, {ST_IN_WAIT_LL, EV_DLEST, lli_d_established}, {ST_IN_WAIT_LL, EV_DLRL, lli_d_released}, {ST_IN_WAIT_LL, EV_ACCEPTD, lli_start_dchan}, {ST_IN_WAIT_LL, EV_HANGUP, lli_start_dchan}, {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_IN_WAIT_LL, EV_RELEASE_IND, lli_received_d_rel}, {ST_IN_WAIT_LL, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_IN_ALERT_SEND, EV_SETUP_CMPL_IND, lli_init_bchan_in}, {ST_IN_ALERT_SEND, EV_ACCEPTD, lli_send_dconnect}, {ST_IN_ALERT_SEND, EV_HANGUP, lli_send_d_disc}, {ST_IN_ALERT_SEND, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_IN_ALERT_SEND, EV_RELEASE_IND, lli_received_d_rel}, {ST_IN_ALERT_SEND, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_IN_ALERT_SEND, EV_DLRL, lli_got_dlrl}, {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in}, {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_send_d_disc}, {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_IN_WAIT_CONN_ACK, EV_RELEASE_IND, lli_received_d_rel}, {ST_IN_WAIT_CONN_ACK, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_connect_err}, {ST_IN_WAIT_CONN_ACK, EV_DLRL, lli_got_dlrl}, {ST_WAIT_BCONN, EV_BC_EST, lli_go_active}, {ST_WAIT_BCONN, EV_BC_REL, lli_send_d_disc}, {ST_WAIT_BCONN, EV_HANGUP, lli_send_d_disc}, {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_WAIT_BCONN, EV_RELEASE_IND, lli_received_d_rel}, {ST_WAIT_BCONN, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_WAIT_BCONN, EV_DLRL, lli_got_dlrl}, {ST_WAIT_BCONN, EV_CINF, lli_charge_info}, {ST_ACTIVE, EV_CINF, lli_charge_info}, {ST_ACTIVE, EV_BC_REL, lli_released_bchan}, {ST_ACTIVE, EV_SUSPEND, lli_suspend}, {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan}, {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan}, {ST_ACTIVE, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_ACTIVE, EV_RELEASE_IND, lli_received_d_rel}, {ST_ACTIVE, EV_DLRL, lli_got_dlrl}, {ST_WAIT_BRELEASE, EV_BC_REL, lli_send_d_disc}, {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_WAIT_BRELEASE, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_WAIT_BRELEASE, EV_RELEASE_IND, lli_received_d_rel}, {ST_WAIT_BRELEASE, EV_DLRL, lli_got_dlrl}, {ST_WAIT_BREL_DISC, EV_BC_REL, lli_received_d_disc}, {ST_WAIT_BREL_DISC, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_WAIT_BREL_DISC, EV_RELEASE_IND, lli_received_d_rel}, {ST_WAIT_BREL_DISC, EV_DLRL, lli_got_dlrl}, {ST_WAIT_DCOMMAND, EV_HANGUP, lli_send_d_disc}, {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_received_d_disc}, {ST_WAIT_DCOMMAND, EV_RELEASE_CNF, lli_received_d_relcnf}, {ST_WAIT_DCOMMAND, EV_RELEASE_IND, lli_received_d_rel}, {ST_WAIT_DCOMMAND, EV_DLRL, lli_got_dlrl}, {ST_WAIT_DRELEASE, EV_RELEASE_IND, lli_timeout_d}, {ST_WAIT_DRELEASE, EV_RELEASE_CNF, lli_timeout_d}, {ST_WAIT_DRELEASE, EV_RELEASE_ERR, lli_timeout_d}, {ST_WAIT_DRELEASE, EV_DIAL, lli_no_dchan_ready}, {ST_WAIT_DRELEASE, EV_DLRL, lli_got_dlrl}, {ST_WAIT_D_REL_CNF, EV_RELEASE_CNF, lli_timeout_d}, {ST_WAIT_D_REL_CNF, EV_RELEASE_ERR, lli_timeout_d},/* ETS 300-104 16.1 */ {ST_WAIT_D_REL_CNF, EV_RELEASE_IND, lli_timeout_d}, {ST_WAIT_D_REL_CNF, EV_DIAL, lli_no_dchan_ready}, {ST_WAIT_D_REL_CNF, EV_DLRL, lli_got_dlrl}, {ST_WAIT_DSHUTDOWN, EV_DLRL, lli_go_null}, {ST_WAIT_DSHUTDOWN, EV_DLEST, lli_d_established}, {ST_WAIT_DSHUTDOWN, EV_DIAL, lli_prep_dialout}, {ST_WAIT_DSHUTDOWN, EV_RESUME, lli_prep_dialout}, {ST_WAIT_DSHUTDOWN, EV_SETUP_IND, lli_deliver_call},};/* *INDENT-ON* */#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))HISAX_INITFUNC(voidCallcNew(void)){ callcfsm.state_count = STATE_COUNT; callcfsm.event_count = EVENT_COUNT; callcfsm.strEvent = strEvent; callcfsm.strState = strState; FsmNew(&callcfsm, fnlist, FNCOUNT);}voidCallcFree(void){ FsmFree(&callcfsm);}static voidrelease_b_st(struct Channel *chanp){ struct PStack *st = chanp->b_st; chanp->bcs->BC_Close(chanp->bcs); switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): releasestack_isdnl2(st); break; case (ISDN_PROTO_L2_HDLC): case (ISDN_PROTO_L2_TRANS):// case (ISDN_PROTO_L2_MODEM): releasestack_transl2(st); break; }}struct Channel*selectfreechannel(struct PStack *st){ struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp = st->lli.userdata; int i; if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) i=1; else i=0; while (i<2) { if (chanp->fi.state == ST_NULL) return (chanp); chanp++; i++; } return (NULL);}intis_activ(struct PStack *st){ struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp = st->lli.userdata; int i; if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) i=1; else i=0; while (i<2) { if (test_bit(FLG_ESTAB_D, &chanp->Flags)) return (1); chanp++; i++; } return (0);}static voiddchan_l3l4(struct PStack *st, int pr, void *arg){ struct l3_process *pc = arg; struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp; int event; switch (pr) { case (DL_ESTABLISH | INDICATION): event = EV_DLEST; break; case (DL_RELEASE | INDICATION): event = EV_DLRL; break; default: event = -1; break; } if (event >= 0) { int i; chanp = st->lli.userdata; if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) i = 1; else i = 0; while (i < 2) { FsmEvent(&chanp->fi, event, NULL); chanp++; i++; } return; } else if (pr == (CC_SETUP | INDICATION)) { if (!(chanp = selectfreechannel(pc->st))) { pc->st->lli.l4l3(pc->st, CC_DLRL | 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_DISCONNECT | INDICATION): FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL); break; case (CC_RELEASE | CONFIRM): FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); break; case (CC_SUSPEND | CONFIRM): FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); break; case (CC_RESUME | CONFIRM): FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); break; case (CC_RESUME_ERR): FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); break; case (CC_RELEASE | INDICATION): FsmEvent(&chanp->fi, EV_RELEASE_IND, 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_ERR, NULL); break; case (CC_PROCEEDING | INDICATION): case (CC_ALERTING | INDICATION): break; default: if (chanp->debug & 0x800) { HiSax_putstatus(chanp->cs, "Ch", "%d L3->L4 unknown primitiv %x", chanp->chan, pr); } }}static voidinit_d_st(struct Channel *chanp){ struct PStack *st = chanp->d_st; struct IsdnCardState *cs = chanp->cs; char tmp[16]; 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->l3.l3l4 = dchan_l3l4;}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 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 voidinit_PStack(struct PStack **stp) { *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); (*stp)->next = NULL; (*stp)->l1.l1l2 = dummy_pstack; (*stp)->l1.l1hw = dummy_pstack; (*stp)->l1.l1tei = dummy_pstack; (*stp)->l2.l2tei = dummy_pstack; (*stp)->l2.l2l1 = dummy_pstack; (*stp)->l2.l2l3 = dummy_pstack; (*stp)->l3.l3l2 = dummy_pstack; (*stp)->l3.l3l4 = dummy_pstack; (*stp)->lli.l4l3 = dummy_pstack; (*stp)->ma.layer = dummy_pstack;}static voidinit_chan(int chan, struct IsdnCardState *csta){ struct Channel *chanp = csta->channel + chan; chanp->cs = csta; chanp->bcs = csta->bcs + chan; chanp->chan = chan; chanp->incoming = 0; chanp->debug = 0; chanp->Flags = 0; chanp->leased = 0; init_PStack(&chanp->b_st); 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)) { init_PStack(&chanp->d_st); if (chan) csta->channel->d_st->next = chanp->d_st; chanp->d_st->next = NULL; init_d_st(chanp); } else { chanp->d_st = csta->channel->d_st; } chanp->data_open = 0;}intCallcNewChan(struct IsdnCardState *csta){ chancount += 2; init_chan(0, csta); init_chan(1, csta); printk(KERN_INFO "HiSax: 2 channels added\n"); if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); test_and_set_bit(FLG_START_D, &csta->channel->Flags); csta->channel->d_st->lli.l4l3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL); } return (2);}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) { if (test_and_clear_bit(FLG_START_B, &csta->channel[i].Flags)) 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) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { dev_kfree_skb(skb, FREE_READ); } 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) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { link_debug(chanp, 0, "channel not open"); dev_kfree_skb(skb, FREE_READ); } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -