⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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;}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;}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;}void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old){#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_set_termios\n");#endif}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;}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);	}}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;	}}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);	}}void capinc_tty_hangup(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_hangup\n");#endif}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}void capinc_tty_flush_buffer(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_flush_buffer\n");#endif}void capinc_tty_set_ldisc(struct tty_struct *tty){#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_set_ldisc\n");#endif}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}int capinc_tty_read_proc(char *page, char **start, off_t off,			  int count, int *eof, void *data){	return 0;}int capinc_write_proc(struct file *file, const char *buffer,			  unsigned long count, void *data){	return 0;}#define CAPINC_NR_PORTS 256static struct tty_driver capinc_tty_driver;static int capinc_tty_refcount;static struct tty_struct *capinc_tty_table[CAPINC_NR_PORTS];static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];int capinc_tty_init(void){	struct tty_driver *drv = &capinc_tty_driver;	/* Initialize the tty_driver structure */		memset(drv, 0, sizeof(struct tty_driver));	drv->magic = TTY_DRIVER_MAGIC;#if (LINUX_VERSION_CODE > 0x20100)	drv->driver_name = "capi_nc";#endif	drv->name = "capi/%d";	drv->major = capi_ttymajor;	drv->minor_start = 0;	drv->num = CAPINC_NR_PORTS;	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;	drv->refcount = &capinc_tty_refcount;	drv->table = capinc_tty_table;	drv->termios = capinc_tty_termios;	drv->termios_locked = capinc_tty_termios_locked;	drv->open = capinc_tty_open;	drv->close = capinc_tty_close;	drv->write = capinc_tty_write;	drv->put_char = capinc_tty_put_char;	drv->flush_chars = capinc_tty_flush_chars;	drv->write_room = capinc_tty_write_room;	drv->chars_in_buffer = capinc_tty_chars_in_buffer;	drv->ioctl = capinc_tty_ioctl;	drv->set_termios = capinc_tty_set_termios;	drv->throttle = capinc_tty_throttle;	drv->unthrottle = capinc_tty_unthrottle;	drv->stop = capinc_tty_stop;	drv->start = capinc_tty_start;	drv->hangup = capinc_tty_hangup;#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */	drv->break_ctl = capinc_tty_break_ctl;#endif	drv->flush_buffer = capinc_tty_flush_buffer;	drv->set_ldisc = capinc_tty_set_ldisc;#if (LINUX_VERSION_CODE >= 131343)	drv->send_xchar = capinc_tty_send_xchar;	drv->read_proc = capinc_tty_read_proc;#endif	if (tty_register_driver(drv)) {		printk(KERN_ERR "Couldn't register capi_nc driver\n");		return -1;	}	return 0;}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);}#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;	int len = 0;	for (cdev=capidev_openlist; cdev; cdev = cdev->next) {		len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n",			cdev->minor,			cdev->applid,			cdev->nrecvctlpkt,			cdev->nrecvdatapkt,			cdev->nsentctlpkt,			cdev->nsentdatapkt);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	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;	int len = 0;	for (cdev=capidev_openlist; cdev; cdev = cdev->next) {		for (np=cdev->nccis; np; np = np->next) {			len += sprintf(page+len, "%d 0x%x%s\n",				cdev->applid,				np->ncci,#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE				"");#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */				np->minorp && np->minorp->file ? " open" : "");#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */			if (len <= off) {				off -= len;				len = 0;			} else {				if (len-off > count)					goto endloop;			}		}	}endloop:	*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, 0);	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, 0);	   p->procent = 0;	}    }}/* -------- init function and module interface ---------------------- */static void __exit alloc_exit(void){	if (capidev_cachep) {		(void)kmem_cache_destroy(capidev_cachep);		capidev_cachep = 0;	}	if (capincci_cachep) {		(void)kmem_cache_destroy(capincci_cachep);		capincci_cachep = 0;	}#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	if (capidh_cachep) {		(void)kmem_cache_destroy(capidh_cachep);		capidh_cachep = 0;	}	if (capiminor_cachep) {		(void)kmem_cache_destroy(capiminor_cachep);		capiminor_cachep = 0;	}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */}static int __init alloc_init(void){	capidev_cachep = kmem_cache_create("capi20_dev",					 sizeof(struct capidev),					 0,					 SLAB_HWCACHE_ALIGN,					 NULL, NULL);	if (!capidev_cachep) {		alloc_exit();		return -ENOMEM;	}	capincci_cachep = kmem_cache_create("capi20_ncci",					 sizeof(struct capincci),					 0,					 SLAB_HWCACHE_ALIGN,					 NULL, NULL);	if (!capincci_cachep) {		alloc_exit();		return -ENOMEM;	}#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	capidh_cachep = kmem_cache_create("capi20_dh",					 sizeof(struct datahandle_queue),					 0,					 SLAB_HWCACHE_ALIGN,					 NULL, NULL);	if (!capidh_cachep) {		alloc_exit();		return -ENOMEM;	}	capiminor_cachep = kmem_cache_create("capi20_minor",					 sizeof(struct capiminor),					 0,					 SLAB_HWCACHE_ALIGN,					 NULL, NULL);	if (!capiminor_cachep) {		alloc_exit();		return -ENOMEM;	}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	return 0;}static void lower_callback(unsigned int cmd, __u32 contr, void *data){	struct capi_ncciinfo *np;	struct capidev *cdev;	switch (cmd) {	case KCI_CONTRUP:		printk(KERN_INFO "capi: controller %hu up\n", contr);		break;	case KCI_CONTRDOWN:		printk(KERN_INFO "capi: controller %hu down\n", contr);		break;	case KCI_NCCIUP:		np = (struct capi_ncciinfo *)data;		if ((cdev = capidev_find(np->applid)) == 0)			return;		(void)capincci_alloc(cdev, np->ncci);		break;	case KCI_NCCIDOWN:		np = (struct capi_ncciinfo *)data;		if ((cdev = capidev_find(np->applid)) == 0)			return;		(void)capincci_free(cdev, np->ncci);		break;	}}static struct capi_interface_user cuser = {	name: "capi20",	callback: lower_callback,};static char rev[10];static int __init capi_init(void){	char *p;	MOD_INC_USE_COUNT;	if ((p = strchr(revision, ':'))) {		strcpy(rev, p + 2);		p = strchr(rev, '$');		*(p-1) = 0;	} else		strcpy(rev, "???");	if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) {		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);		MOD_DEC_USE_COUNT;		return -EIO;	}#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	if (devfs_register_chrdev(capi_rawmajor, "capi/r%d", &capinc_raw_fops)) {		devfs_unregister_chrdev(capi_major, "capi20");		printk(KERN_ERR "capi20: unable to get major %d\n", capi_rawmajor);		MOD_DEC_USE_COUNT;		return -EIO;	}        devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS,			      DEVFS_FL_DEFAULT,                              capi_rawmajor, 0,                              S_IFCHR | S_IRUSR | S_IWUSR,                              &capinc_raw_fops, NULL);#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,			capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,			&capi_fops, NULL);	printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);	if ((capifuncs = attach_capi_interface(&cuser)) == 0) {		MOD_DEC_USE_COUNT;		devfs_unregister_chrdev(capi_major, "capi20");#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE		devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */		devfs_unregister(devfs_find_handle(NULL, "capi20",						   capi_major, 0,						   DEVFS_SPECIAL_CHR, 0));		return -EIO;	}#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	if (capinc_tty_init() < 0) {		(void) detach_capi_interface(&cuser);		devfs_unregister_chrdev(capi_major, "capi20");		devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");		MOD_DEC_USE_COUNT;		return -ENOMEM;	}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	if (alloc_init() < 0) {#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE		unsigned int j;		devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");		for (j = 0; j < CAPINC_NR_PORTS; j++) {			char devname[32];			sprintf(devname, "capi/r%u", j);			devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));		}		capinc_tty_exit();#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */		(void) detach_capi_interface(&cuser);		devfs_unregister_chrdev(capi_major, "capi20");		devfs_unregister(devfs_find_handle(NULL, "capi20",						   capi_major, 0,						   DEVFS_SPECIAL_CHR, 0));		MOD_DEC_USE_COUNT;		return -ENOMEM;	}	(void)proc_init();	printk(KERN_NOTICE "capi20: Rev%s: started up with major %d\n",				rev, capi_major);	MOD_DEC_USE_COUNT;	return 0;}static void __exit capi_exit(void){#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	unsigned int j;#endif	alloc_exit();	(void)proc_exit();	devfs_unregister_chrdev(capi_major, "capi20");	devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	capinc_tty_exit();	devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");	for (j = 0; j < CAPINC_NR_PORTS; j++) {		char devname[32];		sprintf(devname, "capi/r%u", j);		devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));	}#endif	(void) detach_capi_interface(&cuser);	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 + -