?? capi.c
字號(hào):
chan->fsm_state = ACT2000_STATE_BHWAIT; ACTCAPI_QUEUE_TX;}voidactcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(3, 0x02, 0x03); ACTCAPI_CHKSKB; m->msg.connect_resp.plci = chan->plci; m->msg.connect_resp.rejectcause = cause; if (cause) { chan->fsm_state = ACT2000_STATE_NULL; chan->plci = 0x8000; } else chan->fsm_state = ACT2000_STATE_IWAIT; ACTCAPI_QUEUE_TX;}static voidactcapi_connect_active_resp(act2000_card *card, act2000_chan *chan){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(2, 0x03, 0x03); ACTCAPI_CHKSKB; m->msg.connect_resp.plci = chan->plci; if (chan->fsm_state == ACT2000_STATE_IWAIT) chan->fsm_state = ACT2000_STATE_IBWAIT; ACTCAPI_QUEUE_TX;}static voidactcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR((rejectcause?3:17), 0x82, 0x03); ACTCAPI_CHKSKB; m->msg.connect_b3_resp.ncci = chan->ncci; m->msg.connect_b3_resp.rejectcause = rejectcause; if (!rejectcause) { memset(&m->msg.connect_b3_resp.ncpi, 0, sizeof(m->msg.connect_b3_resp.ncpi)); m->msg.connect_b3_resp.ncpi.len = 13; m->msg.connect_b3_resp.ncpi.modulo = 8; chan->fsm_state = ACT2000_STATE_BWAIT; } ACTCAPI_QUEUE_TX;}static voidactcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(2, 0x83, 0x03); ACTCAPI_CHKSKB; m->msg.connect_b3_active_resp.ncci = chan->ncci; chan->fsm_state = ACT2000_STATE_ACTIVE; ACTCAPI_QUEUE_TX;}static voidactcapi_info_resp(act2000_card *card, act2000_chan *chan){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(2, 0x07, 0x03); ACTCAPI_CHKSKB; m->msg.info_resp.plci = chan->plci; ACTCAPI_QUEUE_TX;}static voidactcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(2, 0x84, 0x03); ACTCAPI_CHKSKB; m->msg.disconnect_b3_resp.ncci = chan->ncci; chan->ncci = 0x8000; chan->queued = 0; ACTCAPI_QUEUE_TX;}static voidactcapi_disconnect_resp(act2000_card *card, act2000_chan *chan){ actcapi_msg *m; struct sk_buff *skb; ACTCAPI_MKHDR(2, 0x04, 0x03); ACTCAPI_CHKSKB; m->msg.disconnect_resp.plci = chan->plci; chan->plci = 0x8000; ACTCAPI_QUEUE_TX;}static intnew_plci(act2000_card *card, __u16 plci){ int i; for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].plci == 0x8000) { card->bch[i].plci = plci; return i; } return -1;}static intfind_plci(act2000_card *card, __u16 plci){ int i; for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].plci == plci) return i; return -1;}static intfind_ncci(act2000_card *card, __u16 ncci){ int i; for (i = 0; i < ACT2000_BCH; i++) if (card->bch[i].ncci == ncci) return i; return -1;}static intfind_dialing(act2000_card *card, __u16 callref){ int i; for (i = 0; i < ACT2000_BCH; i++) if ((card->bch[i].callref == callref) && (card->bch[i].fsm_state == ACT2000_STATE_OCALL)) return i; return -1;}static intactcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) { __u16 plci; __u16 ncci; __u16 controller; __u8 blocknr; int chan; actcapi_msg *msg = (actcapi_msg *)skb->data; EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci); chan = find_ncci(card, ncci); if (chan < 0) return 0; if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE) return 0; if (card->bch[chan].plci != plci) return 0; blocknr = msg->msg.data_b3_ind.blocknr; skb_pull(skb, 19); card->interface.rcvcallb_skb(card->myid, chan, skb); if (!(skb = alloc_skb(11, GFP_ATOMIC))) { printk(KERN_WARNING "actcapi: alloc_skb failed\n"); return 1; } msg = (actcapi_msg *)skb_put(skb, 11); msg->hdr.len = 11; msg->hdr.applicationID = 1; msg->hdr.cmd.cmd = 0x86; msg->hdr.cmd.subcmd = 0x03; msg->hdr.msgnum = actcapi_nextsmsg(card); msg->msg.data_b3_resp.ncci = ncci; msg->msg.data_b3_resp.blocknr = blocknr; ACTCAPI_QUEUE_TX; return 1;}/* * Walk over ackq, unlink DATA_B3_REQ from it, if * ncci and blocknr are matching. * Decrement queued-bytes counter. */static inthandle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { unsigned long flags; struct sk_buff *skb; struct sk_buff *tmp; struct actcapi_msg *m; int ret = 0; save_flags(flags); cli(); skb = skb_peek(&card->ackq); restore_flags(flags); if (!skb) { printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; } tmp = skb; while (1) { m = (actcapi_msg *)tmp->data; if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) && (m->msg.data_b3_req.blocknr == blocknr)) { /* found corresponding DATA_B3_REQ */ skb_unlink(tmp); chan->queued -= m->msg.data_b3_req.datalen; if (m->msg.data_b3_req.flags) ret = m->msg.data_b3_req.datalen; dev_kfree_skb(tmp); if (chan->queued < 0) chan->queued = 0; return ret; } save_flags(flags); cli(); tmp = skb_peek((struct sk_buff_head *)tmp); restore_flags(flags); if ((tmp == skb) || (tmp == NULL)) { /* reached end of queue */ printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; } }}voidactcapi_dispatch(act2000_card *card){ struct sk_buff *skb; actcapi_msg *msg; __u16 ccmd; int chan; int len; act2000_chan *ctmp; isdn_ctrl cmd; char tmp[170]; while ((skb = skb_dequeue(&card->rcvq))) { actcapi_debug_msg(skb, 0); msg = (actcapi_msg *)skb->data; ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd); switch (ccmd) { case 0x8602: /* DATA_B3_IND */ if (actcapi_data_b3_ind(card, skb)) return; break; case 0x8601: /* DATA_B3_CONF */ chan = find_ncci(card, msg->msg.data_b3_conf.ncci); if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) { if (msg->msg.data_b3_conf.info != 0) printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n", msg->msg.data_b3_conf.info); len = handle_ack(card, &card->bch[chan], msg->msg.data_b3_conf.blocknr); if (len) { cmd.driver = card->myid; cmd.command = ISDN_STAT_BSENT; cmd.arg = chan; cmd.parm.length = len; card->interface.statcallb(&cmd); } } break; case 0x0201: /* CONNECT_CONF */ chan = find_dialing(card, msg->hdr.msgnum); if (chan >= 0) { if (msg->msg.connect_conf.info) { card->bch[chan].fsm_state = ACT2000_STATE_NULL; cmd.driver = card->myid; cmd.command = ISDN_STAT_DHUP; cmd.arg = chan; card->interface.statcallb(&cmd); } else { card->bch[chan].fsm_state = ACT2000_STATE_OWAIT; card->bch[chan].plci = msg->msg.connect_conf.plci; } } break; case 0x0202: /* CONNECT_IND */ chan = new_plci(card, msg->msg.connect_ind.plci); if (chan < 0) { ctmp = (act2000_chan *)tmp; ctmp->plci = msg->msg.connect_ind.plci; actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ } else { card->bch[chan].fsm_state = ACT2000_STATE_ICALL; cmd.driver = card->myid; cmd.command = ISDN_STAT_ICALL; cmd.arg = chan; cmd.parm.setup.si1 = msg->msg.connect_ind.si1; cmd.parm.setup.si2 = msg->msg.connect_ind.si2; if (card->ptype == ISDN_PTYPE_EURO) strcpy(cmd.parm.setup.eazmsn, act2000_find_eaz(card, msg->msg.connect_ind.eaz)); else { cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz; cmd.parm.setup.eazmsn[1] = 0; } memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone)); memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num, msg->msg.connect_ind.addr.len - 1); cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp; cmd.parm.setup.screen = 0; if (card->interface.statcallb(&cmd) == 2) actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */ } break; case 0x0302: /* CONNECT_ACTIVE_IND */ chan = find_plci(card, msg->msg.connect_active_ind.plci); if (chan >= 0) switch (card->bch[chan].fsm_state) { case ACT2000_STATE_IWAIT: actcapi_connect_active_resp(card, &card->bch[chan]); break; case ACT2000_STATE_OWAIT: actcapi_connect_active_resp(card, &card->bch[chan]); actcapi_select_b2_protocol_req(card, &card->bch[chan]); break; } break; case 0x8202: /* CONNECT_B3_IND */ chan = find_plci(card, msg->msg.connect_b3_ind.plci); if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) { card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci; actcapi_connect_b3_resp(card, &card->bch[chan], 0); } else { ctmp = (act2000_chan *)tmp; ctmp->ncci = msg->msg.connect_b3_ind.ncci; actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ } break; case 0x8302: /* CONNECT_B3_ACTIVE_IND */ chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci); if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) { actcapi_connect_b3_active_resp(card, &card->bch[chan]); cmd.driver = card->myid; cmd.command = ISDN_STAT_BCONN; cmd.arg = chan; card->interface.statcallb(&cmd); } break; case 0x8402: /* DISCONNECT_B3_IND */ chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci); if (chan >= 0) { ctmp = &card->bch[chan]; actcapi_disconnect_b3_resp(card, ctmp); switch (ctmp->fsm_state) { case ACT2000_STATE_ACTIVE: ctmp->fsm_state = ACT2000_STATE_DHWAIT2; cmd.driver = card->myid; cmd.command = ISDN_STAT_BHUP; cmd.arg = chan; card->interface.statcallb(&cmd); break; case ACT2000_STATE_BHWAIT2: actcapi_disconnect_req(card, ctmp); ctmp->fsm_state = ACT2000_STATE_DHWAIT; cmd.driver = card->myid; cmd.command = ISDN_STAT_BHUP; cmd.arg = chan; card->interface.statcallb(&cmd); break; } } break; case 0x0402: /* DISCONNECT_IND */ chan = find_plci(card, msg->msg.disconnect_ind.plci); if (chan >= 0) { ctmp = &card->bch[chan]; actcapi_disconnect_resp(card, ctmp); ctmp->fsm_state = ACT2000_STATE_NULL; cmd.driver = card->myid; cmd.command = ISDN_STAT_DHUP; cmd.arg = chan; card->interface.statcallb(&cmd);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -