📄 comx.c
字号:
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 + -