📄 capi.c
字号:
if (mp->nccip == 0) capiminor_free(mp); }#ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close\n");#endif}static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count){ struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);#endif if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n");#endif return 0; } skb = mp->ttyskb; if (skb) { mp->ttyskb = NULL; skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; } skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); if (!skb) { printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); return -ENOMEM; } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); memcpy(skb_put(skb, count), buf, count); skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; (void)handle_minor_send(mp); (void)handle_minor_recv(mp); return count;}static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch){ struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);#endif if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");#endif return; } skb = mp->ttyskb; if (skb) { if (skb_tailroom(skb) > 0) { *(skb_put(skb, 1)) = ch; return; } mp->ttyskb = NULL; skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; (void)handle_minor_send(mp); } skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); if (skb) { skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); *(skb_put(skb, 1)) = ch; mp->ttyskb = skb; } else { printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); }}static void capinc_tty_flush_chars(struct tty_struct *tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars\n");#endif if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n");#endif return; } skb = mp->ttyskb; if (skb) { mp->ttyskb = NULL; skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; (void)handle_minor_send(mp); } (void)handle_minor_recv(mp);}static int capinc_tty_write_room(struct tty_struct *tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data; int room; if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n");#endif return 0; } room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); room *= CAPI_MAX_BLKSIZE;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room);#endif return room;}static int capinc_tty_chars_in_buffer(struct tty_struct *tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data; if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n");#endif return 0; }#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", mp->outbytes, mp->nack, skb_queue_len(&mp->outqueue), skb_queue_len(&mp->inqueue));#endif return mp->outbytes;}static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg){ int error = 0; switch (cmd) { default: error = n_tty_ioctl (tty, file, cmd, arg); break; } return error;}static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_set_termios\n");#endif}static void capinc_tty_throttle(struct tty_struct * tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_throttle\n");#endif if (mp) mp->ttyinstop = 1;}static void capinc_tty_unthrottle(struct tty_struct * tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_unthrottle\n");#endif if (mp) { mp->ttyinstop = 0; handle_minor_recv(mp); }}static void capinc_tty_stop(struct tty_struct *tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_stop\n");#endif if (mp) { mp->ttyoutstop = 1; }}static void capinc_tty_start(struct tty_struct *tty){ struct capiminor *mp = (struct capiminor *)tty->driver_data;#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_start\n");#endif if (mp) { mp->ttyoutstop = 0; (void)handle_minor_send(mp); }}static void capinc_tty_hangup(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_hangup\n");#endif}static void capinc_tty_break_ctl(struct tty_struct *tty, int state){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);#endif}static void capinc_tty_flush_buffer(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_buffer\n");#endif}static void capinc_tty_set_ldisc(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_set_ldisc\n");#endif}static void capinc_tty_send_xchar(struct tty_struct *tty, char ch){#ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);#endif}static int capinc_tty_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ return 0;}static struct tty_driver *capinc_tty_driver;static struct tty_operations capinc_ops = { .open = capinc_tty_open, .close = capinc_tty_close, .write = capinc_tty_write, .put_char = capinc_tty_put_char, .flush_chars = capinc_tty_flush_chars, .write_room = capinc_tty_write_room, .chars_in_buffer = capinc_tty_chars_in_buffer, .ioctl = capinc_tty_ioctl, .set_termios = capinc_tty_set_termios, .throttle = capinc_tty_throttle, .unthrottle = capinc_tty_unthrottle, .stop = capinc_tty_stop, .start = capinc_tty_start, .hangup = capinc_tty_hangup, .break_ctl = capinc_tty_break_ctl, .flush_buffer = capinc_tty_flush_buffer, .set_ldisc = capinc_tty_set_ldisc, .send_xchar = capinc_tty_send_xchar, .read_proc = capinc_tty_read_proc,};static int capinc_tty_init(void){ struct tty_driver *drv; if (capi_ttyminors > CAPINC_MAX_PORTS) capi_ttyminors = CAPINC_MAX_PORTS; if (capi_ttyminors <= 0) capi_ttyminors = CAPINC_NR_PORTS; drv = alloc_tty_driver(capi_ttyminors); if (!drv) return -ENOMEM; drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->devfs_name = "capi/"; drv->name = "capi"; drv->major = capi_ttymajor; drv->minor_start = 0; drv->type = TTY_DRIVER_TYPE_SERIAL; drv->subtype = SERIAL_TYPE_NORMAL; drv->init_termios = tty_std_termios; drv->init_termios.c_iflag = ICRNL; drv->init_termios.c_oflag = OPOST | ONLCR; drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; drv->init_termios.c_lflag = 0; drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; tty_set_operations(drv, &capinc_ops); if (tty_register_driver(drv)) { put_tty_driver(drv); printk(KERN_ERR "Couldn't register capi_nc driver\n"); return -1; } capinc_tty_driver = drv; return 0;}static void capinc_tty_exit(void){ struct tty_driver *drv = capinc_tty_driver; int retval; if ((retval = tty_unregister_driver(drv))) printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); put_tty_driver(drv);}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE *//* -------- /proc functions ----------------------------------------- *//* * /proc/capi/capi20: * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */static int proc_capidev_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct capidev *cdev; struct list_head *l; int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n", cdev->ap.applid, cdev->ap.nrecvctlpkt, cdev->ap.nrecvdatapkt, cdev->ap.nsentctlpkt, cdev->ap.nsentdatapkt); if (len <= off) { off -= len; len = 0; } else { if (len-off > count) goto endloop; } }endloop: read_unlock(&capidev_list_lock); if (len < count) *eof = 1; if (len > count) len = count; if (len < 0) len = 0; return len;}/* * /proc/capi/capi20ncci: * applid ncci */static int proc_capincci_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct capidev *cdev; struct capincci *np; struct list_head *l; int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); for (np=cdev->nccis; np; np = np->next) { len += sprintf(page+len, "%d 0x%x\n", cdev->ap.applid, np->ncci); if (len <= off) { off -= len; len = 0; } else { if (len-off > count) goto endloop; } } }endloop: read_unlock(&capidev_list_lock); *start = page+off; if (len < count) *eof = 1; if (len>count) len = count; if (len<0) len = 0; return len;}static struct procfsentries { char *name; mode_t mode; int (*read_proc)(char *page, char **start, off_t off, int count, int *eof, void *data); struct proc_dir_entry *procent;} procfsentries[] = { /* { "capi", S_IFDIR, 0 }, */ { "capi/capi20", 0 , proc_capidev_read_proc }, { "capi/capi20ncci", 0 , proc_capincci_read_proc },};static void __init proc_init(void){ int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; for (i=0; i < nelem; i++) { struct procfsentries *p = procfsentries + i; p->procent = create_proc_entry(p->name, p->mode, NULL); if (p->procent) p->procent->read_proc = p->read_proc; }}static void __exit proc_exit(void){ int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; for (i=nelem-1; i >= 0; i--) { struct procfsentries *p = procfsentries + i; if (p->procent) { remove_proc_entry(p->name, NULL); p->procent = NULL; } }}/* -------- init function and module interface ---------------------- */static char rev[32];static int __init capi_init(void){ char *p; char *compileinfo; if ((p = strchr(revision, ':')) != 0 && p[1]) { strlcpy(rev, p + 2, sizeof(rev)); if ((p = strchr(rev, '$')) != 0 && p > rev) *(p-1) = 0; } else strcpy(rev, "1.0"); if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); return -EIO; } capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); return PTR_ERR(capi_class); } class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, "isdn/capi20");#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { class_device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); return -ENOMEM; }#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ proc_init();#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) compileinfo = " (middleware+capifs)";#else compileinfo = " (no capifs)";#endif#else compileinfo = " (no middleware)";#endif printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", rev, capi_major, compileinfo); return 0;}static void __exit capi_exit(void){ proc_exit(); class_device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); devfs_remove("isdn/capi20");#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit();#endif printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev);}module_init(capi_init);module_exit(capi_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -