📄 drv.c
字号:
if ((len = capi_disc_req(*(ushort*)(skb->data), &skb2, CAUSE_NOCHAN)) > 0) pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb2, len); break; } cbdata.data.setup.CalledPN = NULL; cbdata.data.setup.CallingPN = NULL; capi_decode_conn_ind(chan, skb, &cbdata); cbdata.type = EV_NET_SETUP; pcbit_fsm_event(dev, chan, EV_NET_SETUP, NULL); if (pcbit_check_msn(dev, cbdata.data.setup.CallingPN)) pcbit_fsm_event(dev, chan, EV_USR_PROCED_REQ, &cbdata); else pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); kfree(cbdata.data.setup.CalledPN); kfree(cbdata.data.setup.CallingPN); break; case MSG_CONN_CONF: /* * We should be able to find the channel by the message * reference number. The current version of the firmware * doesn't sent the ref number correctly. */#ifdef DEBUG printk(KERN_DEBUG "refnum=%04x b1=%04x b2=%04x\n", refnum, dev->b1->s_refnum, dev->b2->s_refnum);#endif /* We just try to find a channel in the right state */ if (dev->b1->fsm_state == ST_CALL_INIT) chan = dev->b1; else { if (dev->b2->s_refnum == ST_CALL_INIT) chan = dev->b2; else { chan = NULL; printk(KERN_WARNING "Connection Confirm - no channel in Call Init state\n"); break; } } if (capi_decode_conn_conf(chan, skb, &complete)) { printk(KERN_DEBUG "conn_conf indicates error\n"); pcbit_fsm_event(dev, chan, EV_ERROR, NULL); } else if (complete) pcbit_fsm_event(dev, chan, EV_NET_CALL_PROC, NULL); else pcbit_fsm_event(dev, chan, EV_NET_SETUP_ACK, NULL); break; case MSG_CONN_ACTV_IND: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (capi_decode_conn_actv_ind(chan, skb)) { printk("error in capi_decode_conn_actv_ind\n"); /* pcbit_fsm_event(dev, chan, EV_ERROR, NULL); */ break; } chan->r_refnum = refnum; pcbit_fsm_event(dev, chan, EV_NET_CONN, NULL); break; case MSG_CONN_ACTV_CONF: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (capi_decode_conn_actv_conf(chan, skb) == 0) pcbit_fsm_event(dev, chan, EV_NET_CONN_ACK, NULL); else printk(KERN_DEBUG "decode_conn_actv_conf failed\n"); break; case MSG_SELP_CONF: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (!(err = capi_decode_sel_proto_conf(chan, skb))) pcbit_fsm_event(dev, chan, EV_NET_SELP_RESP, NULL); else { /* Error */ printk("error %d - capi_decode_sel_proto_conf\n", err); } break; case MSG_ACT_TRANSP_CONF: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (!capi_decode_actv_trans_conf(chan, skb)) pcbit_fsm_event(dev, chan, EV_NET_ACTV_RESP, NULL); break; case MSG_DISC_IND: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (!capi_decode_disc_ind(chan, skb)) pcbit_fsm_event(dev, chan, EV_NET_DISC, NULL); else printk(KERN_WARNING "capi_decode_disc_ind - error\n"); break; case MSG_DISC_CONF: if (!(chan = capi_channel(dev, skb))) { printk(KERN_WARNING "CAPI header: unknown channel id\n"); break; } if (!capi_decode_disc_ind(chan, skb)) pcbit_fsm_event(dev, chan, EV_NET_RELEASE, NULL); else printk(KERN_WARNING "capi_decode_disc_conf - error\n"); break; case MSG_INFO_IND:#ifdef DEBUG printk(KERN_DEBUG "received Info Indication - discarded\n");#endif break;#ifdef DEBUG case MSG_DEBUG_188: capi_decode_debug_188(skb->data, skb->len); break; default: printk(KERN_DEBUG "pcbit_l3_receive: unknown message %08lx\n", msg); break;#endif } kfree_skb(skb);}/* * Single statbuf * should be a statbuf per device */static char statbuf[STATBUF_LEN];static int stat_st = 0;static int stat_end = 0;static int pcbit_stat(u_char __user *buf, int len, int driver, int channel){ int stat_count; stat_count = stat_end - stat_st; if (stat_count < 0) stat_count = STATBUF_LEN - stat_st + stat_end; /* FIXME: should we sleep and wait for more cookies ? */ if (len > stat_count) len = stat_count; if (stat_st < stat_end) { copy_to_user(buf, statbuf + stat_st, len); stat_st += len; } else { if (len > STATBUF_LEN - stat_st) { copy_to_user(buf, statbuf + stat_st, STATBUF_LEN - stat_st); copy_to_user(buf, statbuf, len - (STATBUF_LEN - stat_st)); stat_st = len - (STATBUF_LEN - stat_st); } else { copy_to_user(buf, statbuf + stat_st, len); stat_st += len; if (stat_st == STATBUF_LEN) stat_st = 0; } } if (stat_st == stat_end) stat_st = stat_end = 0; return len;}static void pcbit_logstat(struct pcbit_dev *dev, char *str){ int i; isdn_ctrl ictl; for (i=stat_end; i<strlen(str); i++) { statbuf[i]=str[i]; stat_end = (stat_end + 1) % STATBUF_LEN; if (stat_end == stat_st) stat_st = (stat_st + 1) % STATBUF_LEN; } ictl.command=ISDN_STAT_STAVAIL; ictl.driver=dev->id; ictl.arg=strlen(str); dev->dev_if->statcallb(&ictl);} extern char * isdn_state_table[];extern char * strisdnevent(unsigned short);void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, unsigned short i, unsigned short ev, unsigned short f){ char buf[256]; sprintf(buf, "change on device: %d channel:%d\n%s -> %s -> %s\n", dev->id, chan->id, isdn_state_table[i], strisdnevent(ev), isdn_state_table[f] );#ifdef DEBUG printk("%s", buf);#endif pcbit_logstat(dev, buf);}static void set_running_timeout(unsigned long ptr){ struct pcbit_dev * dev;#ifdef DEBUG printk(KERN_DEBUG "set_running_timeout\n");#endif dev = (struct pcbit_dev *) ptr; wake_up_interruptible(&dev->set_running_wq);}static int set_protocol_running(struct pcbit_dev * dev){ isdn_ctrl ctl; init_timer(&dev->set_running_timer); dev->set_running_timer.function = &set_running_timeout; dev->set_running_timer.data = (ulong) dev; dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; /* kick it */ dev->l2_state = L2_STARTING; writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), dev->sh_mem + BANK4); add_timer(&dev->set_running_timer); interruptible_sleep_on(&dev->set_running_wq); del_timer(&dev->set_running_timer); if (dev->l2_state == L2_RUNNING) { printk(KERN_DEBUG "pcbit: running\n"); dev->unack_seq = dev->send_seq; dev->writeptr = dev->sh_mem; dev->readptr = dev->sh_mem + BANK2; /* tell the good news to the upper layer */ ctl.driver = dev->id; ctl.command = ISDN_STAT_RUN; dev->dev_if->statcallb(&ctl); } else { printk(KERN_DEBUG "pcbit: initialization failed\n"); printk(KERN_DEBUG "pcbit: firmware not loaded\n"); dev->l2_state = L2_DOWN;#ifdef DEBUG printk(KERN_DEBUG "Bank3 = %02x\n", readb(dev->sh_mem + BANK3));#endif writeb(0x40, dev->sh_mem + BANK4); /* warn the upper layer */ ctl.driver = dev->id; ctl.command = ISDN_STAT_STOP; dev->dev_if->statcallb(&ctl); return -EL2HLT; /* Level 2 halted */ } return 0;}static int pcbit_ioctl(isdn_ctrl* ctl){ struct pcbit_dev * dev; struct pcbit_ioctl *cmd; dev = finddev(ctl->driver); if (!dev) { printk(KERN_DEBUG "pcbit_ioctl: unknown device\n"); return -ENODEV; } cmd = (struct pcbit_ioctl *) ctl->parm.num; switch(ctl->arg) { case PCBIT_IOCTL_GETSTAT: cmd->info.l2_status = dev->l2_state; break; case PCBIT_IOCTL_STRLOAD: if (dev->l2_state == L2_RUNNING) return -EBUSY; dev->unack_seq = dev->send_seq = dev->rcv_seq = 0; dev->writeptr = dev->sh_mem; dev->readptr = dev->sh_mem + BANK2; dev->l2_state = L2_LOADING; break; case PCBIT_IOCTL_LWMODE: if (dev->l2_state != L2_LOADING) return -EINVAL; dev->l2_state = L2_LWMODE; break; case PCBIT_IOCTL_FWMODE: if (dev->l2_state == L2_RUNNING) return -EBUSY; dev->loadptr = LOAD_ZONE_START; dev->l2_state = L2_FWMODE; break; case PCBIT_IOCTL_ENDLOAD: if (dev->l2_state == L2_RUNNING) return -EBUSY; dev->l2_state = L2_DOWN; break; case PCBIT_IOCTL_SETBYTE: if (dev->l2_state == L2_RUNNING) return -EBUSY; /* check addr */ if (cmd->info.rdp_byte.addr > BANK4) return -EFAULT; writeb(cmd->info.rdp_byte.value, dev->sh_mem + cmd->info.rdp_byte.addr); break; case PCBIT_IOCTL_GETBYTE: if (dev->l2_state == L2_RUNNING) return -EBUSY; /* check addr */ if (cmd->info.rdp_byte.addr > BANK4) { printk("getbyte: invalid addr %04x\n", cmd->info.rdp_byte.addr); return -EFAULT; } cmd->info.rdp_byte.value = readb(dev->sh_mem + cmd->info.rdp_byte.addr); break; case PCBIT_IOCTL_RUNNING: if (dev->l2_state == L2_RUNNING) return -EBUSY; return set_protocol_running(dev); break; case PCBIT_IOCTL_WATCH188: if (dev->l2_state != L2_LOADING) return -EINVAL; pcbit_l2_write(dev, MSG_WATCH188, 0x0001, NULL, 0); break; case PCBIT_IOCTL_PING188: if (dev->l2_state != L2_LOADING) return -EINVAL; pcbit_l2_write(dev, MSG_PING188_REQ, 0x0001, NULL, 0); break; case PCBIT_IOCTL_APION: if (dev->l2_state != L2_LOADING) return -EINVAL; pcbit_l2_write(dev, MSG_API_ON, 0x0001, NULL, 0); break; case PCBIT_IOCTL_STOP: dev->l2_state = L2_DOWN; writeb(0x40, dev->sh_mem + BANK4); dev->rcv_seq = 0; dev->send_seq = 0; dev->unack_seq = 0; break; default: printk("error: unknown ioctl\n"); break; }; return 0;}/* * MSN list handling * * if null reject all calls * if first entry has null MSN accept all calls */static void pcbit_clear_msn(struct pcbit_dev *dev){ struct msn_entry *ptr, *back; for (ptr=dev->msn_list; ptr; ) { back = ptr->next; kfree(ptr); ptr = back; } dev->msn_list = NULL; }static void pcbit_set_msn(struct pcbit_dev *dev, char *list){ struct msn_entry *ptr; struct msn_entry *back = NULL; char *cp, *sp; int len; if (strlen(list) == 0) { ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); if (!ptr) { printk(KERN_WARNING "kmalloc failed\n"); return; } ptr->msn = NULL; ptr->next = dev->msn_list; dev->msn_list = ptr; return; } if (dev->msn_list) for (back=dev->msn_list; back->next; back=back->next); sp = list; do { cp=strchr(sp, ','); if (cp) len = cp - sp; else len = strlen(sp); ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); if (!ptr) { printk(KERN_WARNING "kmalloc failed\n"); return; } ptr->next = NULL; ptr->msn = kmalloc(len, GFP_ATOMIC); if (!ptr->msn) { printk(KERN_WARNING "kmalloc failed\n"); kfree(ptr); return; } memcpy(ptr->msn, sp, len - 1); ptr->msn[len] = 0;#ifdef DEBUG printk(KERN_DEBUG "msn: %s\n", ptr->msn);#endif if (dev->msn_list == NULL) dev->msn_list = ptr; else back->next = ptr; back = ptr; sp += len; } while(cp);}/* * check if we do signal or reject an incoming call */static int pcbit_check_msn(struct pcbit_dev *dev, char *msn){ struct msn_entry *ptr; for (ptr=dev->msn_list; ptr; ptr=ptr->next) { if (ptr->msn == NULL) return 1; if (strcmp(ptr->msn, msn) == 0) return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -