📄 capidrv.c
字号:
card->contrnr, nccip->chan, nccip->ncci); break; case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */ goto ignored; case CAPI_CONNECT_B3_IND: /* ncci */ plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI); if (plcip) { nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI); if (nccip) { ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND); capi_fill_CONNECT_B3_RESP(cmsg, global.appid, card->msgid++, nccip->ncci, /* adr */ 0, /* Reject */ 0 /* NCPI */ ); send_message(card, cmsg); ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP); break; } printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); } else { printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); } capi_fill_CONNECT_B3_RESP(cmsg, global.appid, card->msgid++, cmsg->adr.adrNCCI, 2, /* Reject */ 0 /* NCPI */ ); send_message(card, cmsg); break; case CAPI_CONNECT_B3_CONF: /* ncci */ if (!(nccip = find_ncci_by_msgid(card, cmsg->adr.adrNCCI, cmsg->Messagenumber))) goto notfound; nccip->ncci = cmsg->adr.adrNCCI; if (cmsg->Info) { printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrNCCI); } if (cmsg->Info) ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR); else ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK); break; case CAPI_CONNECT_B3_T90_ACTIVE_IND: /* ncci */ capi_cmsg_answer(cmsg); send_message(card, cmsg); break; case CAPI_DATA_B3_IND: /* ncci */ /* handled in handle_data() */ goto ignored; case CAPI_DATA_B3_CONF: /* ncci */ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; len = capidrv_del_ack(nccip, cmsg->DataHandle); if (len < 0) break; cmd.command = ISDN_STAT_BSENT; cmd.driver = card->myid; cmd.arg = nccip->chan; cmd.parm.length = len; card->interface.statcallb(&cmd); break; case CAPI_DISCONNECT_B3_IND: /* ncci */ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; card->bchans[nccip->chan].disconnecting = 1; ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND); capi_cmsg_answer(cmsg); send_message(card, cmsg); ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP); break; case CAPI_DISCONNECT_B3_CONF: /* ncci */ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; if (cmsg->Info) { printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrNCCI); ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR); } break; case CAPI_RESET_B3_IND: /* ncci */ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND); capi_cmsg_answer(cmsg); send_message(card, cmsg); break; case CAPI_RESET_B3_CONF: /* ncci */ goto ignored; /* $$$$ */ case CAPI_FACILITY_IND: /* Controller/plci/ncci */ goto ignored; case CAPI_FACILITY_CONF: /* Controller/plci/ncci */ goto ignored; default: printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); } return; ignored: printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); return; notfound: printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI);}static void handle_data(_cmsg * cmsg, struct sk_buff *skb){ capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); capidrv_ncci *nccip; if (!card) { printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController & 0x7f); kfree_skb(skb); return; } if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) { printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); kfree_skb(skb); return; } (void) skb_pull(skb, CAPIMSG_LEN(skb->data)); card->interface.rcvcallb_skb(card->myid, nccip->chan, skb); capi_cmsg_answer(cmsg); send_message(card, cmsg);}static _cmsg s_cmsg;static void capidrv_signal(__u16 applid, void *dummy){ struct sk_buff *skb = 0; while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) { capi_message2cmsg(&s_cmsg, skb->data); if (debugmode > 2) printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", applid, capi_cmsg2str(&s_cmsg)); if (s_cmsg.Command == CAPI_DATA_B3 && s_cmsg.Subcommand == CAPI_IND) { handle_data(&s_cmsg, skb); global.nrecvdatapkt++; continue; } if ((s_cmsg.adr.adrController & 0xffffff00) == 0) handle_controller(&s_cmsg); else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0) handle_plci(&s_cmsg); else handle_ncci(&s_cmsg); /* * data of skb used in s_cmsg, * free data when s_cmsg is not used again * thanks to Lars Heete <hel@admin.de> */ kfree_skb(skb); global.nrecvctlpkt++; }}/* ------------------------------------------------------------------- */#define PUTBYTE_TO_STATUS(card, byte) \ do { \ *(card)->q931_write++ = (byte); \ if ((card)->q931_write > (card)->q931_end) \ (card)->q931_write = (card)->q931_buf; \ } while (0)static void handle_dtrace_data(capidrv_contr *card, int send, int level2, __u8 *data, __u16 len){ __u8 *p, *end; isdn_ctrl cmd; if (!len) { printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n", card->contrnr, len); return; } if (level2) { PUTBYTE_TO_STATUS(card, 'D'); PUTBYTE_TO_STATUS(card, '2'); PUTBYTE_TO_STATUS(card, send ? '>' : '<'); PUTBYTE_TO_STATUS(card, ':'); } else { PUTBYTE_TO_STATUS(card, 'D'); PUTBYTE_TO_STATUS(card, '3'); PUTBYTE_TO_STATUS(card, send ? '>' : '<'); PUTBYTE_TO_STATUS(card, ':'); } for (p = data, end = data+len; p < end; p++) { __u8 w; PUTBYTE_TO_STATUS(card, ' '); w = (*p >> 4) & 0xf; PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w); w = *p & 0xf; PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w); } PUTBYTE_TO_STATUS(card, '\n'); cmd.command = ISDN_STAT_STAVAIL; cmd.driver = card->myid; cmd.arg = len*3+5; card->interface.statcallb(&cmd);}/* ------------------------------------------------------------------- */static _cmsg cmdcmsg;static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card){ switch (c->arg) { case 1: debugmode = (int)(*((unsigned int *)c->parm.num)); printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n", card->contrnr, debugmode); return 0; default: printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n", card->contrnr, c->arg); return -EINVAL; } return -EINVAL;}/* * Handle leased lines (CAPI-Bundling) */struct internal_bchannelinfo { unsigned short channelalloc; unsigned short operation; unsigned char cmask[31];};static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep){ unsigned long bmask = 0; int active = !0; char *s; int i; if (strncmp(teln, "FV:", 3) != 0) return 1; s = teln + 3; while (*s && *s == ' ') s++; if (!*s) return -2; if (*s == 'p' || *s == 'P') { active = 0; s++; } if (*s == 'a' || *s == 'A') { active = !0; s++; } while (*s) { int digit1 = 0; int digit2 = 0; if (!isdigit(*s)) return -3; while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } if (digit1 <= 0 && digit1 > 30) return -4; if (*s == 0 || *s == ',' || *s == ' ') { bmask |= (1 << digit1); digit1 = 0; if (*s) s++; continue; } if (*s != '-') return -5; s++; if (!isdigit(*s)) return -3; while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } if (digit2 <= 0 && digit2 > 30) return -4; if (*s == 0 || *s == ',' || *s == ' ') { if (digit1 > digit2) for (i = digit2; i <= digit1 ; i++) bmask |= (1 << i); else for (i = digit1; i <= digit2 ; i++) bmask |= (1 << i); digit1 = digit2 = 0; if (*s) s++; continue; } return -6; } if (activep) *activep = active; if (bmaskp) *bmaskp = bmask; return 0;}static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31]){ unsigned long bmask; int active; int rc, i; rc = decodeFVteln(teln, &bmask, &active); if (rc) return rc; /* Length */ AdditionalInfo[0] = 2+2+31; /* Channel: 3 => use channel allocation */ AdditionalInfo[1] = 3; AdditionalInfo[2] = 0; /* Operation: 0 => DTE mode, 1 => DCE mode */ if (active) { AdditionalInfo[3] = 0; AdditionalInfo[4] = 0; } else { AdditionalInfo[3] = 1; AdditionalInfo[4] = 0; } /* Channel mask array */ AdditionalInfo[5] = 0; /* no D-Channel */ for (i=1; i <= 30; i++) AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0; return 0;}static int capidrv_command(isdn_ctrl * c, capidrv_contr * card){ isdn_ctrl cmd; struct capidrv_bchan *bchan; struct capidrv_plci *plcip; __u8 AdditionalInfo[1+2+2+31]; int rc, isleasedline = 0; if (c->command == ISDN_CMD_IOCTL) return capidrv_ioctl(c, card); switch (c->command) { case ISDN_CMD_DIAL:{ __u8 calling[ISDN_MSNLEN + 3]; __u8 called[ISDN_MSNLEN + 2]; if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n", card->contrnr, c->arg, c->parm.setup.phone, c->parm.setup.si1, c->parm.setup.si2, c->parm.setup.eazmsn); bchan = &card->bchans[c->arg % card->nbchan]; if (bchan->plcip) { printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n", card->contrnr, c->arg, c->parm.setup.phone, c->parm.setup.si1, c->parm.setup.si2, c->parm.setup.eazmsn, bchan->plcip->plci); return 0; } bchan->si1 = c->parm.setup.si1; bchan->si2 = c->parm.setup.si2; strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num)); strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum)); rc = FVteln2capi20(bchan->num, AdditionalInfo); isleasedline = (rc == 0); if (rc < 0) printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num); if (isleasedline) { calling[0] = 0; called[0] = 0; if (debugmode) printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr); } else { calling[0] = strlen(bchan->mynum) + 2; calling[1] = 0; calling[2] = 0x80; strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN); called[0] = strlen(bchan->num) + 1; called[1] = 0x80; strncpy(called + 2, bchan->num, ISDN_MSNLEN); } capi_fill_CONNECT_REQ(&cmdcmsg, global.appid, card->msgid++, card->contrnr, /* adr */ si2cip(bchan->si1, bchan->si2), /* cipvalue */ called, /* CalledPartyNumber */ calling, /* CallingPartyNumber */ 0, /* CalledPartySubaddress */ 0, /* CallingPartySubaddress */ b1prot(bchan->l2, bchan->l3), /* B1protocol */ b2prot(bchan->l2, bchan->l3), /* B2protocol */ b3prot(bchan->l2, bchan->l3), /* B3protocol */ b1config(bchan->l2, bchan->l3), /* B1configuration */ 0, /* B2configuration */ 0, /* B3configuration */ 0, /* BC */ 0, /* LLC */ 0, /* HLC */ /* BChannelinformation */ isleasedline ? AdditionalInfo : 0, 0, /* Keypadfacility */ 0, /* Useruserdata */ 0 /* Facilitydataarray */ ); if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) { cmd.command = ISDN_STAT_DHUP; cmd.driver = card->myid; cmd.arg = (c->arg % card->nbchan); card->interface.statcallb(&cmd); return -1; } plcip->msgid = cmdcmsg.Messagenumber;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -