📄 capidrv.c
字号:
plcip->leasedline = isleasedline; plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ); send_message(card, &cmdcmsg); return 0; } case ISDN_CMD_ACCEPTD: bchan = &card->bchans[c->arg % card->nbchan]; if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n", card->contrnr, c->arg, bchan->l2, bchan->l3); capi_fill_CONNECT_RESP(&cmdcmsg, global.appid, card->msgid++, bchan->plcip->plci, /* adr */ 0, /* Reject */ 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, /* ConnectedNumber */ 0, /* ConnectedSubaddress */ 0, /* LLC */ 0, /* BChannelinformation */ 0, /* Keypadfacility */ 0, /* Useruserdata */ 0 /* Facilitydataarray */ ); capi_cmsg2message(&cmdcmsg, cmdcmsg.buf); plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP); send_message(card, &cmdcmsg); return 0; case ISDN_CMD_ACCEPTB: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n", card->contrnr, c->arg); return -ENOSYS; case ISDN_CMD_HANGUP: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n", card->contrnr, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; if (bchan->disconnecting) { if (debugmode) printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n", card->contrnr, c->arg); return 0; } if (bchan->nccip) { bchan->disconnecting = 1; capi_fill_DISCONNECT_B3_REQ(&cmdcmsg, global.appid, card->msgid++, bchan->nccip->ncci, 0 /* NCPI */ ); ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ); send_message(card, &cmdcmsg); return 0; } else if (bchan->plcip) { if (bchan->plcip->state == ST_PLCI_INCOMING) { /* * just ignore, we a called from * isdn_status_callback(), * which will return 0 or 2, this is handled * by the CONNECT_IND handler */ bchan->disconnecting = 1; return 0; } else if (bchan->plcip->plci) { bchan->disconnecting = 1; capi_fill_DISCONNECT_REQ(&cmdcmsg, global.appid, card->msgid++, bchan->plcip->plci, 0, /* BChannelinformation */ 0, /* Keypadfacility */ 0, /* Useruserdata */ 0 /* Facilitydataarray */ ); plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ); send_message(card, &cmdcmsg); return 0; } else { printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n", card->contrnr, c->arg); return -EINVAL; } } printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n", card->contrnr, c->arg); return -EINVAL;/* ready */ case ISDN_CMD_SETL2: if (debugmode) printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n", card->contrnr, (c->arg & 0xff), (c->arg >> 8)); bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; bchan->l2 = (c->arg >> 8); return 0; case ISDN_CMD_SETL3: if (debugmode) printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n", card->contrnr, (c->arg & 0xff), (c->arg >> 8)); bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; bchan->l3 = (c->arg >> 8); return 0; case ISDN_CMD_SETEAZ: if (debugmode) printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n", card->contrnr, c->parm.num, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN); return 0; case ISDN_CMD_CLREAZ: if (debugmode) printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n", card->contrnr, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; bchan->msn[0] = 0; return 0; case ISDN_CMD_LOCK: if (debugmode > 1) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg); MOD_INC_USE_COUNT; break; case ISDN_CMD_UNLOCK: if (debugmode > 1) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n", card->contrnr, c->arg); MOD_DEC_USE_COUNT; break;/* never called */ case ISDN_CMD_GETL2: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n", card->contrnr); return -ENODEV; case ISDN_CMD_GETL3: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n", card->contrnr); return -ENODEV; case ISDN_CMD_GETEAZ: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n", card->contrnr); return -ENODEV; case ISDN_CMD_SETSIL: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n", card->contrnr); return -ENODEV; case ISDN_CMD_GETSIL: if (debugmode) printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n", card->contrnr); return -ENODEV; default: printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n", card->contrnr, c->command); return -EINVAL; } return 0;}static int if_command(isdn_ctrl * c){ capidrv_contr *card = findcontrbydriverid(c->driver); if (card) return capidrv_command(c, card); printk(KERN_ERR "capidrv: if_command %d called with invalid driverId %d!\n", c->command, c->driver); return -ENODEV;}static _cmsg sendcmsg;static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb){ capidrv_contr *card = findcontrbydriverid(id); capidrv_bchan *bchan; capidrv_ncci *nccip; int len = skb->len; size_t msglen; __u16 errcode; __u16 datahandle; if (!card) { printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n", card->contrnr, id); return 0; } if (debugmode > 1) printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n", card->contrnr, len, skb, doack); bchan = &card->bchans[channel % card->nbchan]; nccip = bchan->nccip; if (!nccip || nccip->state != ST_NCCI_ACTIVE) { printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n", card->contrnr, card->name, channel); return 0; } datahandle = nccip->datahandle; capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++, nccip->ncci, /* adr */ (__u32) skb->data, /* Data */ skb->len, /* DataLength */ datahandle, /* DataHandle */ 0 /* Flags */ ); if (capidrv_add_ack(nccip, datahandle, doack ? skb->len : -1) < 0) return 0; capi_cmsg2message(&sendcmsg, sendcmsg.buf); msglen = CAPIMSG_LEN(sendcmsg.buf); if (skb_headroom(skb) < msglen) { struct sk_buff *nskb = skb_realloc_headroom(skb, msglen); if (!nskb) { printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n", card->contrnr); (void)capidrv_del_ack(nccip, datahandle); return 0; } printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n", card->contrnr, skb_headroom(skb), msglen); memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen); errcode = (*capifuncs->capi_put_message) (global.appid, nskb); if (errcode == CAPI_NOERROR) { dev_kfree_skb(skb); nccip->datahandle++; global.nsentdatapkt++; return len; } (void)capidrv_del_ack(nccip, datahandle); dev_kfree_skb(nskb); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; } else { memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen); errcode = (*capifuncs->capi_put_message) (global.appid, skb); if (errcode == CAPI_NOERROR) { nccip->datahandle++; global.nsentdatapkt++; return len; } skb_pull(skb, msglen); (void)capidrv_del_ack(nccip, datahandle); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; }}static int if_readstat(__u8 *buf, int len, int user, int id, int channel){ capidrv_contr *card = findcontrbydriverid(id); int count; __u8 *p; if (!card) { printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n", card->contrnr, id); return -ENODEV; } for (p=buf, count=0; count < len; p++, count++) { if (user) put_user(*card->q931_read++, p); else *p = *card->q931_read++; if (card->q931_read > card->q931_end) card->q931_read = card->q931_buf; } return count;}static void enable_dchannel_trace(capidrv_contr *card){ __u8 manufacturer[CAPI_MANUFACTURER_LEN]; capi_version version; __u16 contr = card->contrnr; __u16 errcode; __u16 avmversion[3]; errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer); if (errcode != CAPI_NOERROR) { printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n", card->name, errcode); return; } if (strstr(manufacturer, "AVM") == 0) { printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n", card->name, manufacturer); return; } errcode = (*capifuncs->capi_get_version)(contr, &version); if (errcode != CAPI_NOERROR) { printk(KERN_ERR "%s: can't get version (0x%x)\n", card->name, errcode); return; } avmversion[0] = (version.majormanuversion >> 4) & 0x0f; avmversion[1] = (version.majormanuversion << 4) & 0xf0; avmversion[1] |= (version.minormanuversion >> 4) & 0x0f; avmversion[2] |= version.minormanuversion & 0x0f; if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) { printk(KERN_INFO "%s: D2 trace enabled\n", card->name); capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, card->msgid++, contr, 0x214D5641, /* ManuID */ 0, /* Class */ 1, /* Function */ (_cstruct)"\004\200\014\000\000"); } else { printk(KERN_INFO "%s: D3 trace enabled\n", card->name); capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, card->msgid++, contr, 0x214D5641, /* ManuID */ 0, /* Class */ 1, /* Function */ (_cstruct)"\004\002\003\000\000"); } send_message(card, &cmdcmsg);}static void send_listen(capidrv_contr *card){ capi_fill_LISTEN_REQ(&cmdcmsg, global.appid, card->msgid++, card->contrnr, /* controller */ 1 << 6, /* Infomask */ card->cipmask, card->cipmask2, 0, 0); send_message(card, &cmdcmsg); listen_change_state(card, EV_LISTEN_REQ);}static void listentimerfunc(unsigned long x){ capidrv_contr *card = (capidrv_contr *)x; if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE) printk(KERN_ERR "%s: controller dead ??\n", card->name); send_listen(card); mod_timer(&card->listentimer, jiffies + 60*HZ);}static int capidrv_addcontr(__u16 contr, struct capi_profile *profp){ capidrv_contr *card; long flags; isdn_ctrl cmd; char id[20]; int i; MOD_INC_USE_COUNT; sprintf(id, "capidrv-%d", contr); if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { printk(KERN_WARNING "capidrv: (%s) Could not allocate contr-struct.\n", id); MOD_DEC_USE_COUNT; return -1; } memset(card, 0, sizeof(capidrv_contr)); init_timer(&card->listentimer); strcpy(card->name, id); card->contrnr = contr; card->nbchan = profp->nbchannel; card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC); if (!card->bchans) { printk(KERN_WARNING "capidrv: (%s) Could not allocate bchan-structs.\n", id); kfree(card); MOD_DEC_USE_COUNT; return -1; } card->interface.channels = profp->nbchannel; card->interface.maxbufsize = 2048; card->interface.command = if_command; card->interface.writebuf_skb = if_sendbuf; card->interface.writecmd = 0; card->interface.readstat = if_readstat; card->interface.features = ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_X75UI | ISDN_FEATURE_L2_X75BUI; if (profp->support1 & (1<<2)) card->interface.features |= ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038; if (profp->support1 & (1<<8)) card->interface.features |= ISDN_FEATURE_L2_MODEM; card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); card->q931_read = card->q931_buf; card->q931_write = card->q931_buf; card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1; if (!register_isdn(&card->interface)) { printk(KERN_ERR "capidrv: Unable to register contr %s\n", id); kfree(card->bchans); kfree(card); MOD_DEC_USE_COUNT; return -1; } card->myid = card->interface.channels; spin_lock_irqsave(&global_lock, flags); card->next = global.contr_list; global.contr_list = card; global.ncontr++; spin_unlock_irqrestore(&global_lock, flags); memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan); for (i = 0; i < card->nbchan; i++) { card->bchans[i].contr = card; } cmd.command = ISDN_STAT_RUN; cmd.driver = card->myid; card->i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -