#include #include #include #include #include int test_wlan_dect_config(char *buffer, size_t *bufferlen) { enum avm_prom_config_type type; size_t room = *bufferlen; char *s = buffer; for (type = 0; type < AVM_PROM_NUM_TYPES; ++type) { const char *name = avm_prom_config_type_name[type]; if (!name || !avm_prom_is_config_available(type)) continue; while (*name) { if (room-- <= sizeof("x\n")) return -EOVERFLOW; *s++ = toupper(*name++); } *s++ = '\n'; } *s = '\0'; *bufferlen = s - buffer; /* Don't count NUL */ return 0; } EXPORT_SYMBOL(test_wlan_dect_config); int copy_wlan_dect_config2user(char *buffer, size_t bufferlen) { enum avm_prom_config_type type; const char *typename, *path; struct file *file; ssize_t len; loff_t pos; void *data; int ret; BUG_ON(!memchr(buffer, 0, bufferlen)); /* * There should be no other users of the buffer, * we can parse destructively. */ buffer = strim(buffer); typename = strsep(&buffer, " \t"); if (!buffer) return -EINVAL; path = skip_spaces(buffer); if (!typename[0]) return -EINVAL; for (type = 0; ; ++type) { if (type == AVM_PROM_NUM_TYPES) { pr_err("ERROR: Unknown type: %s\n", typename); return -EINVAL; } if (!avm_prom_config_type_name[type]) continue; if (!strcasecmp(typename, avm_prom_config_type_name[type])) break; } len = avm_prom_get_config_alloc(type, &data); if (len < 0) { pr_err("Error getting config item \"%s\": %d\n", typename, len); return len; } file = filp_open(path, O_CREAT|O_RDWR|O_TRUNC, 0600); if (IS_ERR(file)) { pr_err("ERROR: Could not open file '%s': %ld\n", path, PTR_ERR(file)); kvfree(data); return PTR_ERR(file); } ret = 0; for (pos = 0; pos < len; ) { ssize_t written; written = kernel_write(file, data + pos, len - pos, &pos); if (written < 0) { pr_err("Error writing config %s to file '%s': %d\n", typename, path, written); ret = written; break; } } filp_close(file, NULL); kvfree(data); return ret; } EXPORT_SYMBOL(copy_wlan_dect_config2user); MODULE_AUTHOR("AVM GmbH"); MODULE_DESCRIPTION("AVM PROM access"); MODULE_LICENSE("GPL");