📄 capidrv.c
字号:
}static inline __u8 cip2si1(__u16 cipval){ static const __u8 si[32] = {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */ 7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */ 1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */ 7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */ if (cipval > 31) cipval = 0; /* .... */ return si[cipval];}static inline __u8 cip2si2(__u16 cipval){ static const __u8 si[32] = {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */ 0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */ 1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */ 0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */ if (cipval > 31) cipval = 0; /* .... */ return si[cipval];}/* -------- controller managment ------------------------------------- */static inline capidrv_contr *findcontrbydriverid(int driverid){ unsigned long flags; capidrv_contr *p; spin_lock_irqsave(&global_lock, flags); for (p = global.contr_list; p; p = p->next) if (p->myid == driverid) break; spin_unlock_irqrestore(&global_lock, flags); return p;}static capidrv_contr *findcontrbynumber(__u32 contr){ unsigned long flags; capidrv_contr *p = global.contr_list; spin_lock_irqsave(&global_lock, flags); for (p = global.contr_list; p; p = p->next) if (p->contrnr == contr) break; spin_unlock_irqrestore(&global_lock, flags); return p;}/* -------- plci management ------------------------------------------ */static capidrv_plci *new_plci(capidrv_contr * card, int chan){ capidrv_plci *plcip; plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC); if (plcip == 0) return 0; memset(plcip, 0, sizeof(capidrv_plci)); plcip->state = ST_PLCI_NONE; plcip->plci = 0; plcip->msgid = 0; plcip->chan = chan; plcip->next = card->plci_list; card->plci_list = plcip; card->bchans[chan].plcip = plcip; return plcip;}static capidrv_plci *find_plci_by_plci(capidrv_contr * card, __u32 plci){ capidrv_plci *p; for (p = card->plci_list; p; p = p->next) if (p->plci == plci) return p; return 0;}static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, __u16 msgid){ capidrv_plci *p; for (p = card->plci_list; p; p = p->next) if (p->msgid == msgid) return p; return 0;}static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, __u32 ncci){ capidrv_plci *p; for (p = card->plci_list; p; p = p->next) if (p->plci == (ncci & 0xffff)) return p; return 0;}static void free_plci(capidrv_contr * card, capidrv_plci * plcip){ capidrv_plci **pp; for (pp = &card->plci_list; *pp; pp = &(*pp)->next) { if (*pp == plcip) { *pp = (*pp)->next; card->bchans[plcip->chan].plcip = 0; card->bchans[plcip->chan].disconnecting = 0; card->bchans[plcip->chan].incoming = 0; kfree(plcip); return; } } printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n", card->contrnr, plcip, plcip->plci);}/* -------- ncci management ------------------------------------------ */static inline capidrv_ncci *new_ncci(capidrv_contr * card, capidrv_plci * plcip, __u32 ncci){ capidrv_ncci *nccip; nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC); if (nccip == 0) return 0; memset(nccip, 0, sizeof(capidrv_ncci)); nccip->ncci = ncci; nccip->state = ST_NCCI_NONE; nccip->plcip = plcip; nccip->chan = plcip->chan; nccip->datahandle = 0; nccip->next = plcip->ncci_list; plcip->ncci_list = nccip; card->bchans[plcip->chan].nccip = nccip; return nccip;}static inline capidrv_ncci *find_ncci(capidrv_contr * card, __u32 ncci){ capidrv_plci *plcip; capidrv_ncci *p; if ((plcip = find_plci_by_ncci(card, ncci)) == 0) return 0; for (p = plcip->ncci_list; p; p = p->next) if (p->ncci == ncci) return p; return 0;}static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card, __u32 ncci, __u16 msgid){ capidrv_plci *plcip; capidrv_ncci *p; if ((plcip = find_plci_by_ncci(card, ncci)) == 0) return 0; for (p = plcip->ncci_list; p; p = p->next) if (p->msgid == msgid) return p; return 0;}static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip){ struct capidrv_ncci **pp; for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) { if (*pp == nccip) { *pp = (*pp)->next; break; } } card->bchans[nccip->chan].nccip = 0; kfree(nccip);}static int capidrv_add_ack(struct capidrv_ncci *nccip, __u16 datahandle, int len){ struct ncci_datahandle_queue *n, **pp; n = (struct ncci_datahandle_queue *) kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC); if (!n) { printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n"); return -1; } n->next = 0; n->datahandle = datahandle; n->len = len; for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ; *pp = n; return 0;}static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle){ struct ncci_datahandle_queue **pp, *p; int len; for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) { if ((*pp)->datahandle == datahandle) { p = *pp; len = p->len; *pp = (*pp)->next; kfree(p); return len; } } return -1;}/* -------- convert and send capi message ---------------------------- */static void send_message(capidrv_contr * card, _cmsg * cmsg){ struct sk_buff *skb; size_t len; capi_cmsg2message(cmsg, cmsg->buf); len = CAPIMSG_LEN(cmsg->buf); skb = alloc_skb(len, GFP_ATOMIC); memcpy(skb_put(skb, len), cmsg->buf, len); (*capifuncs->capi_put_message) (global.appid, skb); global.nsentctlpkt++;}/* -------- state machine -------------------------------------------- */struct listenstatechange { int actstate; int nextstate; int event;};static struct listenstatechange listentable[] ={ {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ}, {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ}, {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR}, {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR}, {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, {},};static void listen_change_state(capidrv_contr * card, int event){ struct listenstatechange *p = listentable; while (p->event) { if (card->state == p->actstate && p->event == event) { if (debugmode) printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n", card->contrnr, card->state, p->nextstate); card->state = p->nextstate; return; } p++; } printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n", card->contrnr, card->state, event);}/* ------------------------------------------------------------------ */static void p0(capidrv_contr * card, capidrv_plci * plci){ isdn_ctrl cmd; card->bchans[plci->chan].contr = 0; cmd.command = ISDN_STAT_DHUP; cmd.driver = card->myid; cmd.arg = plci->chan; card->interface.statcallb(&cmd); free_plci(card, plci);}/* ------------------------------------------------------------------ */struct plcistatechange { int actstate; int nextstate; int event; void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);};static struct plcistatechange plcitable[] ={ /* P-0 */ {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0}, {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0}, {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0}, {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0}, /* P-0.1 */ {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, /* P-1 */ {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-ACT */ {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0}, {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0}, /* P-2 */ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0}, {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0}, {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0}, /* P-3 */ {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0}, {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-4 */ {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-5 */ {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-6 */ {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0}, /* P-0.Res */ {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0}, {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0}, /* P-RES */ {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0}, /* P-HELD */ {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0}, {},};static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event){ struct plcistatechange *p = plcitable; while (p->event) { if (plci->state == p->actstate && p->event == event) { if (debugmode) printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n", card->contrnr, plci->plci, plci->state, p->nextstate); plci->state = p->nextstate; if (p->changefunc) p->changefunc(card, plci); return; } p++; } printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n", card->contrnr, plci->plci, plci->state, event);}/* ------------------------------------------------------------------ */static _cmsg cmsg;static void n0(capidrv_contr * card, capidrv_ncci * ncci){ isdn_ctrl cmd; capi_fill_DISCONNECT_REQ(&cmsg, global.appid, card->msgid++, ncci->plcip->plci, 0, /* BChannelinformation */ 0, /* Keypadfacility */ 0, /* Useruserdata */ /* $$$$ */ 0 /* Facilitydataarray */ ); send_message(card, &cmsg); plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ); cmd.command = ISDN_STAT_BHUP; cmd.driver = card->myid; cmd.arg = ncci->chan; card->interface.statcallb(&cmd); free_ncci(card, ncci);}/* ------------------------------------------------------------------ */struct nccistatechange { int actstate; int nextstate; int event; void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);};static struct nccistatechange nccitable[] ={ /* N-0 */ {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0}, {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0}, /* N-0.1 */ {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0}, {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0}, /* N-1 */ {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0}, {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0}, {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-2 */ {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0}, {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-ACT */ {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0}, {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-3 */ {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-4 */ {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0}, /* N-5 */ {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0}, {},};static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event){ struct nccistatechange *p = nccitable; while (p->event) { if (ncci->state == p->actstate && p->event == event) { if (debugmode) printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n", card->contrnr, ncci->ncci, ncci->state, p->nextstate); if (p->nextstate == ST_NCCI_PREVIOUS) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -