static int comxlapb_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 = entry->parent->data; struct lapb_parms_struct parms; unsigned long parm; char *page; if (lapb_getparms(dev->priv, &parms)) { return -ENODEV; } if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } copy_from_user(page, buffer, count); if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } if (strcmp(entry->name, FILENAME_T1) == 0) { parm=simple_strtoul(page,NULL,10); if (parm > 0 && parm < 100) { parms.t1=parm; lapb_setparms(dev->priv, &parms); } } else if (strcmp(entry->name, FILENAME_T2) == 0) { parm=simple_strtoul(page, NULL, 10); if (parm > 0 && parm < 100) { parms.t2=parm; lapb_setparms(dev->priv, &parms); } } else if (strcmp(entry->name, FILENAME_N2) == 0) { parm=simple_strtoul(page, NULL, 10); if (parm > 0 && parm < 100) { parms.n2=parm; lapb_setparms(dev->priv, &parms); } } else if (strcmp(entry->name, FILENAME_WINDOW) == 0) { parms.window = simple_strtoul(page, NULL, 10); lapb_setparms(dev->priv, &parms); } else if (strcmp(entry->name, FILENAME_MODE) == 0) { if (comx_strcasecmp(page, "dte") == 0) { parms.mode &= ~(LAPB_DCE | LAPB_DTE); parms.mode |= LAPB_DTE; } else if (comx_strcasecmp(page, "dce") == 0) { parms.mode &= ~(LAPB_DTE | LAPB_DCE); parms.mode |= LAPB_DCE; } else if (comx_strcasecmp(page, "std") == 0 || comx_strcasecmp(page, "standard") == 0) { parms.mode &= ~LAPB_EXTENDED; parms.mode |= LAPB_STANDARD; } else if (comx_strcasecmp(page, "ext") == 0 || comx_strcasecmp(page, "extended") == 0) { parms.mode &= ~LAPB_STANDARD; parms.mode |= LAPB_EXTENDED; } lapb_setparms(dev->priv, &parms); } else { printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n", entry->name); return -EBADF; } free_page((unsigned long)page); return count; }
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; }