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

📄 comx.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct comx_protocol *line;	int len = 0;	if (strcmp(file->name, FILENAME_HARDWARELIST) == 0) {		for(hw=comx_channels;hw;hw=hw->next) 			len+=sprintf(page+len, "%s\n", hw->name);	} else if (strcmp(file->name, FILENAME_PROTOCOLLIST) == 0) {		for(line=comx_lines;line;line=line->next)			len+=sprintf(page+len, "%s\n", line->name);	}	if (off >= len) {		*eof = 1;		return 0;	}	*start = page + off;	if (count >= len - off) {		*eof = 1;	}	return min_t(int, count, len - off);}static int comx_write_proc(struct file *file, const char *buffer, u_long count,	void *data){	struct proc_dir_entry *entry = (struct proc_dir_entry *)data;	struct net_device *dev = (struct net_device *)entry->parent->data;	struct comx_channel *ch=(struct comx_channel *)dev->priv;	char *page;	struct comx_hardware *hw = comx_channels;	struct comx_protocol *line = comx_lines;	char str[30];	int ret=0;	if (count > PAGE_SIZE) {		printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);		return -ENOSPC;	}	if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;	if(copy_from_user(page, buffer, count))	{		count = -EFAULT;		goto out;	}	if (page[count-1] == '\n')		page[count-1] = '\0';	else if (count < PAGE_SIZE)		page[count] = '\0';	else if (page[count]) {		count = -EINVAL;		goto out;	}	if (strcmp(entry->name, FILENAME_DEBUG) == 0) {		int i;		int ret = 0;		if ((i = simple_strtoul(page, NULL, 10)) != 0) {			unsigned long flags;			save_flags(flags); cli();			if (ch->debug_area) kfree(ch->debug_area);			if ((ch->debug_area = kmalloc(ch->debug_size = i, 				GFP_KERNEL)) == NULL) {				ret = -ENOMEM;			}			ch->debug_start = ch->debug_end = 0;			restore_flags(flags);			free_page((unsigned long)page);			return ret ? ret : count;		}				if (*page != '+' && *page != '-') {			free_page((unsigned long)page);			return -EINVAL;		}		while (comx_debugflags[i].value && 			strncmp(comx_debugflags[i].name, page + 1, 			strlen(comx_debugflags[i].name))) {			i++;		}			if (comx_debugflags[i].value == 0) {			printk(KERN_ERR "Invalid debug option\n");			free_page((unsigned long)page);			return -EINVAL;		}		if (*page == '+') {			ch->debug_flags |= comx_debugflags[i].value;		} else {			ch->debug_flags &= ~comx_debugflags[i].value;		}	} else if (strcmp(entry->name, FILENAME_HARDWARE) == 0) {		if(strlen(page)>10) {			free_page((unsigned long)page);			return -EINVAL;		}		while (hw) { 			if (strcmp(hw->name, page) == 0) {				break;			} else {				hw = hw->next;			}		}#ifdef CONFIG_KMOD		if(!hw && comx_strcasecmp(HWNAME_NONE,page) != 0){			sprintf(str,"comx-hw-%s",page);			request_module(str);		}				hw=comx_channels;		while (hw) {			if (comx_strcasecmp(hw->name, page) == 0) {				break;			} else {				hw = hw->next;			}		}#endif		if (comx_strcasecmp(HWNAME_NONE, page) != 0 && !hw)  {			free_page((unsigned long)page);			return -ENODEV;		}		if (ch->init_status & HW_OPEN) {			free_page((unsigned long)page);			return -EBUSY;		}		if (ch->hardware && ch->hardware->hw_exit && 		   (ret=ch->hardware->hw_exit(dev))) {			free_page((unsigned long)page);			return ret;		}		ch->hardware = hw;		entry->size = strlen(page) + 1;		if (hw && hw->hw_init) hw->hw_init(dev);	} else if (strcmp(entry->name, FILENAME_PROTOCOL) == 0) {		if(strlen(page)>10) {			free_page((unsigned long)page);			return -EINVAL;		}		while (line) {			if (comx_strcasecmp(line->name, page) == 0) {				break;			} else {				line = line->next;			}		}#ifdef CONFIG_KMOD		if(!line && comx_strcasecmp(PROTONAME_NONE, page) != 0) {			sprintf(str,"comx-proto-%s",page);			request_module(str);		}				line=comx_lines;		while (line) {			if (comx_strcasecmp(line->name, page) == 0) {				break;			} else {				line = line->next;			}		}#endif				if (comx_strcasecmp(PROTONAME_NONE, page) != 0 && !line) {			free_page((unsigned long)page);			return -ENODEV;		}				if (ch->init_status & LINE_OPEN) {			free_page((unsigned long)page);			return -EBUSY;		}				if (ch->protocol && ch->protocol->line_exit && 		    (ret=ch->protocol->line_exit(dev))) {			free_page((unsigned long)page);			return ret;		}		ch->protocol = line;		entry->size = strlen(page) + 1;		comx_reset_dev(dev);		if (line && line->line_init) line->line_init(dev);	} else if (strcmp(entry->name, FILENAME_LINEUPDELAY) == 0) {		int i;		if ((i = simple_strtoul(page, NULL, 10)) != 0) {			if (i >=0 && i < 10) { 				ch->lineup_delay = i; 			} else {				printk(KERN_ERR "comx: invalid lineup_delay value\n");			}		}	}out:	free_page((unsigned long)page);	return count;}static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode){	struct proc_dir_entry *new_dir, *debug_file;	struct net_device *dev;	struct comx_channel *ch;	int ret = -EIO;	if ((dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) {		return -ENOMEM;	}	memset(dev, 0, sizeof(struct net_device));	if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR, 		comx_root_dir)) == NULL) {		goto cleanup_dev;	}	new_dir->nlink = 2;	new_dir->data = NULL; // ide jon majd a struct dev	/* Ezek kellenek */	if (!create_comx_proc_entry(FILENAME_HARDWARE, 0644, 	    strlen(HWNAME_NONE) + 1, new_dir)) {		goto cleanup_new_dir;	}	if (!create_comx_proc_entry(FILENAME_PROTOCOL, 0644, 	    strlen(PROTONAME_NONE) + 1, new_dir)) {		goto cleanup_filename_hardware;	}	if (!create_comx_proc_entry(FILENAME_STATUS, 0444, 0, new_dir)) {		goto cleanup_filename_protocol;	}	if (!create_comx_proc_entry(FILENAME_LINEUPDELAY, 0644, 2, new_dir)) {		goto cleanup_filename_status;	}	if ((debug_file = create_proc_entry(FILENAME_DEBUG, 	    S_IFREG | 0644, new_dir)) == NULL) {		goto cleanup_filename_lineupdelay;	}	debug_file->data = (void *)debug_file; 	debug_file->read_proc = NULL; // see below	debug_file->write_proc = &comx_write_proc;	debug_file->nlink = 1;	strcpy(dev->name, (char *)new_dir->name);	dev->init = comx_init_dev;	if (register_netdevice(dev)) {		goto cleanup_filename_debug;	}	ch=dev->priv;	if((ch->if_ptr = (void *)kmalloc(sizeof(struct ppp_device), 				 GFP_KERNEL)) == NULL) {		goto cleanup_register;	}	memset(ch->if_ptr, 0, sizeof(struct ppp_device));	ch->debug_file = debug_file; 	ch->procdir = new_dir;	new_dir->data = dev;	ch->debug_start = ch->debug_end = 0;	if ((ch->debug_area = kmalloc(ch->debug_size = DEFAULT_DEBUG_SIZE, 	    GFP_KERNEL)) == NULL) {		ret = -ENOMEM;		goto cleanup_if_ptr;	}	ch->lineup_delay = DEFAULT_LINEUP_DELAY;	MOD_INC_USE_COUNT;	return 0;cleanup_if_ptr:	kfree(ch->if_ptr);cleanup_register:	unregister_netdevice(dev);cleanup_filename_debug:	remove_proc_entry(FILENAME_DEBUG, new_dir);cleanup_filename_lineupdelay:	remove_proc_entry(FILENAME_LINEUPDELAY, new_dir);cleanup_filename_status:	remove_proc_entry(FILENAME_STATUS, new_dir);cleanup_filename_protocol:	remove_proc_entry(FILENAME_PROTOCOL, new_dir);cleanup_filename_hardware:	remove_proc_entry(FILENAME_HARDWARE, new_dir);cleanup_new_dir:	remove_proc_entry(dentry->d_name.name, comx_root_dir);cleanup_dev:	kfree(dev);	return ret;}static int comx_rmdir(struct inode *dir, struct dentry *dentry){	struct proc_dir_entry *entry = dentry->d_inode->u.generic_ip;	struct net_device *dev = entry->data;	struct comx_channel *ch = dev->priv;	int ret;	if (dev->flags & IFF_UP) {		printk(KERN_ERR "%s: down interface before removing it\n", dev->name);		return -EBUSY;	}	if (ch->protocol && ch->protocol->line_exit && 	    (ret=ch->protocol->line_exit(dev))) {		return ret;	}	if (ch->hardware && ch->hardware->hw_exit && 	   (ret=ch->hardware->hw_exit(dev))) { 		if(ch->protocol && ch->protocol->line_init) {			ch->protocol->line_init(dev);		}		return ret;	}	ch->protocol = NULL;	ch->hardware = NULL;	del_timer(&ch->loadavg_timer);	kfree(ch->avg_bytes);	unregister_netdev(dev);	if (ch->debug_area) {		kfree(ch->debug_area);	}	if (dev->priv) {		kfree(dev->priv);	}	kfree(dev);	remove_proc_entry(FILENAME_DEBUG, entry);	remove_proc_entry(FILENAME_LINEUPDELAY, entry);	remove_proc_entry(FILENAME_STATUS, entry);	remove_proc_entry(FILENAME_HARDWARE, entry);	remove_proc_entry(FILENAME_PROTOCOL, entry);	remove_proc_entry(dentry->d_name.name, comx_root_dir);	MOD_DEC_USE_COUNT;	return 0;}static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry){	struct proc_dir_entry *de;	struct inode *inode = NULL;	if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) {		for (de = de->subdir ; de ; de = de->next) {			if ((de && de->low_ino) && 			    (de->namelen == dentry->d_name.len) &&			    (memcmp(dentry->d_name.name, de->name, 			    de->namelen) == 0))	{			 	if ((inode = proc_get_inode(dir->i_sb, 			 	    de->low_ino, de)) == NULL) { 			 		printk(KERN_ERR "COMX: lookup error\n"); 			 		return ERR_PTR(-EINVAL); 			 	}				break;			}		}	}	dentry->d_op = &comx_dentry_operations;	d_add(dentry, inode);	return NULL;}int comx_strcasecmp(const char *cs, const char *ct){	register signed char __res;	while (1) {		if ((__res = toupper(*cs) - toupper(*ct++)) != 0 || !*cs++) {			break;		}	}	return __res;}static int comx_delete_dentry(struct dentry *dentry){	return 1;}static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,	int size, struct proc_dir_entry *dir){	struct proc_dir_entry *new_file;	if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) {		new_file->data = (void *)new_file;		new_file->read_proc = &comx_read_proc;		new_file->write_proc = &comx_write_proc;		new_file->size = size;		new_file->nlink = 1;	}	return(new_file);}int comx_register_hardware(struct comx_hardware *comx_hw){	struct comx_hardware *hw = comx_channels;	if (!hw) {		comx_channels = comx_hw;	} else {		while (hw->next != NULL && strcmp(comx_hw->name, hw->name) != 0) {			hw = hw->next;		}		if (strcmp(comx_hw->name, hw->name) == 0) {			return -1;		}		hw->next = comx_hw;	}	printk(KERN_INFO "COMX: driver for hardware type %s, version %s\n", comx_hw->name, comx_hw->version);	return 0;}int comx_unregister_hardware(char *name){	struct comx_hardware *hw = comx_channels;	if (!hw) {		return -1;	}	if (strcmp(hw->name, name) == 0) {		comx_channels = comx_channels->next;		return 0;	}	while (hw->next != NULL && strcmp(hw->next->name,name) != 0) {		hw = hw->next;	}	if (hw->next != NULL && strcmp(hw->next->name, name) == 0) {		hw->next = hw->next->next;		return 0;	}	return -1;}int comx_register_protocol(struct comx_protocol *comx_line){	struct comx_protocol *pr = comx_lines;	if (!pr) {		comx_lines = comx_line;	} else {		while (pr->next != NULL && strcmp(comx_line->name, pr->name) !=0) {			pr = pr->next;		}		if (strcmp(comx_line->name, pr->name) == 0) {			return -1;		}		pr->next = comx_line;	}	printk(KERN_INFO "COMX: driver for protocol type %s, version %s\n", comx_line->name, comx_line->version);	return 0;}int comx_unregister_protocol(char *name){	struct comx_protocol *pr = comx_lines;	if (!pr) {		return -1;	}	if (strcmp(pr->name, name) == 0) {		comx_lines = comx_lines->next;		return 0;	}	while (pr->next != NULL && strcmp(pr->next->name,name) != 0) {		pr = pr->next;	}	if (pr->next != NULL && strcmp(pr->next->name, name) == 0) {		pr->next = pr->next->next;		return 0;	}	return -1;}#ifdef MODULE#define comx_init init_module#endifint __init comx_init(void){	struct proc_dir_entry *new_file;	comx_root_dir = create_proc_entry("comx", 		S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root);	if (!comx_root_dir)		return -ENOMEM;	comx_root_dir->proc_iops = &comx_root_inode_ops;	if ((new_file = create_proc_entry(FILENAME_HARDWARELIST, 	   S_IFREG | 0444, comx_root_dir)) == NULL) {		return -ENOMEM;	}		new_file->data = new_file;	new_file->read_proc = &comx_root_read_proc;	new_file->write_proc = NULL;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_PROTOCOLLIST, 	   S_IFREG | 0444, comx_root_dir)) == NULL) {		return -ENOMEM;	}		new_file->data = new_file;	new_file->read_proc = &comx_root_read_proc;	new_file->write_proc = NULL;	new_file->nlink = 1;	printk(KERN_INFO "COMX: driver version %s (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>\n", 		VERSION);#ifndef MODULE#ifdef CONFIG_COMX_HW_COMX	comx_hw_comx_init();#endif#ifdef CONFIG_COMX_HW_LOCOMX	comx_hw_locomx_init();#endif#ifdef CONFIG_COMX_HW_MIXCOM	comx_hw_mixcom_init();#endif#ifdef CONFIG_COMX_PROTO_HDLC	comx_proto_hdlc_init();#endif#ifdef CONFIG_COMX_PROTO_PPP	comx_proto_ppp_init();#endif#ifdef CONFIG_COMX_PROTO_LAPB	comx_proto_lapb_init();#endif#ifdef CONFIG_COMX_PROTO_FR	comx_proto_fr_init();#endif#endif	return 0;}#ifdef MODULEvoid cleanup_module(void){	remove_proc_entry(FILENAME_HARDWARELIST, comx_root_dir);	remove_proc_entry(FILENAME_PROTOCOLLIST, comx_root_dir);	remove_proc_entry(comx_root_dir->name, &proc_root);}#endifEXPORT_SYMBOL(comx_register_hardware);EXPORT_SYMBOL(comx_unregister_hardware);EXPORT_SYMBOL(comx_register_protocol);EXPORT_SYMBOL(comx_unregister_protocol);EXPORT_SYMBOL(comx_debug_skb);EXPORT_SYMBOL(comx_debug_bytes);EXPORT_SYMBOL(comx_debug);EXPORT_SYMBOL(comx_lineup_func);EXPORT_SYMBOL(comx_status);EXPORT_SYMBOL(comx_rx);EXPORT_SYMBOL(comx_strcasecmp);EXPORT_SYMBOL(comx_root_dir);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -