Removed the old driver_settings.c file.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3521 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5d25f8fb7b
commit
7862de2e87
@ -1,551 +0,0 @@
|
||||
/* driver_settings - implements the driver settings API
|
||||
**
|
||||
** Initial version by Axel Dörfler, axeld@pinc-software.de
|
||||
** This file may be used under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <driver_settings.h>
|
||||
|
||||
// this definition is currently missing from the headers above...
|
||||
// just a small to let it compile fine in the OpenBeOS tree
|
||||
#ifndef B_FILE_NAME_LENGTH
|
||||
# define B_FILE_NAME_LENGTH 256
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define SETTINGS_DIRECTORY "/boot/home/config/settings/kernel/drivers/"
|
||||
#define SETTINGS_MAGIC 'DrvS'
|
||||
|
||||
// Those maximum values are independent from the implementation - they
|
||||
// have been chosen to make the code more robust against bad files
|
||||
#define MAX_SETTINGS_SIZE 32768
|
||||
#define MAX_SETTINGS_LEVEL 8
|
||||
|
||||
#define CONTINUE_PARAMETER 1
|
||||
|
||||
struct settings_handle {
|
||||
void *first_buffer;
|
||||
int32 magic;
|
||||
struct driver_settings settings;
|
||||
char *text;
|
||||
};
|
||||
|
||||
// Basic settings file access functions - since the driver settings API
|
||||
// has to be able to load the settings files using the BIOS, before the
|
||||
// kernel is running.
|
||||
// ToDo: there is currently no way to change the settings ops - the
|
||||
// kernel should just call a function at startup.
|
||||
struct settings_ops {
|
||||
int (*open)(const char *name);
|
||||
void (*close)(int handle);
|
||||
off_t (*filesize)(int handle);
|
||||
size_t (*read)(int handle, char *buffer, size_t bufferSize);
|
||||
};
|
||||
|
||||
// The BIOS calls are currently not implemented
|
||||
// We need to have a stripped-down BFS driver for the bootloader;
|
||||
// this one would implement the functionality we need here
|
||||
|
||||
// ToDo: the code currently assumes a working malloc()/free()
|
||||
// for the bootloader code. Most probably this is okay, though
|
||||
|
||||
static int bios_open(const char *name);
|
||||
static void bios_close(int handle);
|
||||
static off_t bios_filesize(int handle);
|
||||
static size_t bios_read(int handle, char *buffer, size_t bufferSize);
|
||||
|
||||
static const struct settings_ops kBiosOps = {
|
||||
bios_open,
|
||||
bios_close,
|
||||
bios_filesize,
|
||||
bios_read,
|
||||
};
|
||||
|
||||
// The kernel calls are used after the kernel has been loaded and
|
||||
// initialized by the bootloader.
|
||||
|
||||
static int kernel_open(const char *name);
|
||||
static void kernel_close(int handle);
|
||||
static off_t kernel_filesize(int handle);
|
||||
static size_t kernel_read(int handle, char *buffer, size_t bufferSize);
|
||||
|
||||
static const struct settings_ops kKernelOps = {
|
||||
kernel_open,
|
||||
kernel_close,
|
||||
kernel_filesize,
|
||||
kernel_read,
|
||||
};
|
||||
|
||||
// ToDo: the BIOS API must be used at first when we have a real bootloader
|
||||
static const struct settings_ops *gSettingsOps = &kKernelOps;
|
||||
|
||||
|
||||
static int
|
||||
bios_open(const char *name)
|
||||
{
|
||||
// not yet implemented
|
||||
// has to use a stripped down BFS driver to get down to the file
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bios_close(int handle)
|
||||
{
|
||||
// not yet implemented
|
||||
}
|
||||
|
||||
|
||||
static off_t
|
||||
bios_filesize(int handle)
|
||||
{
|
||||
// not yet implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
bios_read(int handle, char *buffer, size_t bufferSize)
|
||||
{
|
||||
// not yet implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
kernel_open(const char *name)
|
||||
{
|
||||
char path[B_FILE_NAME_LENGTH + 64];
|
||||
strcpy(path, SETTINGS_DIRECTORY);
|
||||
strlcat(path, name, sizeof(path));
|
||||
|
||||
return open(path, O_RDONLY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kernel_close(int handle)
|
||||
{
|
||||
close(handle);
|
||||
}
|
||||
|
||||
|
||||
static off_t
|
||||
kernel_filesize(int handle)
|
||||
{
|
||||
struct stat stat;
|
||||
if (fstat(handle, &stat) < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
return stat.st_size;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
kernel_read(int handle, char *buffer, size_t bufferSize)
|
||||
{
|
||||
return read(handle, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Functions not part of the public API
|
||||
|
||||
|
||||
static inline bool
|
||||
check_handle(struct settings_handle *handle)
|
||||
{
|
||||
if (handle == NULL
|
||||
|| handle->magic != SETTINGS_MAGIC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static driver_parameter *
|
||||
get_parameter(struct settings_handle *handle, const char *name)
|
||||
{
|
||||
int32 i;
|
||||
for (i = handle->settings.parameter_count; i-- > 0;) {
|
||||
if (!strcmp(handle->settings.parameters[i].name, name))
|
||||
return &handle->settings.parameters[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
get_word(char **_pos, char **_word, bool allowNewLine)
|
||||
{
|
||||
char *pos = *_pos;
|
||||
char quoted = 0;
|
||||
bool newLine = false, end = false;
|
||||
int escaped = 0;
|
||||
bool charEscaped = false;
|
||||
|
||||
// Skip any white space and comments
|
||||
while (pos[0] && ((allowNewLine && (isspace(pos[0]) || pos[0] == '#'))
|
||||
|| (!allowNewLine && (pos[0] == '\t' || pos[0] == ' ')))) {
|
||||
// skip any comment lines
|
||||
if (pos[0] == '#') {
|
||||
while (*pos && *pos != '\n')
|
||||
pos++;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos[0] == '}')
|
||||
return B_NO_ERROR;
|
||||
|
||||
// Read in a word - might contain escaped (\) spaces, or it
|
||||
// might also be quoted (" or ').
|
||||
|
||||
if (pos[0] == '"' || pos[0] == '\'') {
|
||||
quoted = pos[0];
|
||||
pos++;
|
||||
}
|
||||
*_word = pos;
|
||||
|
||||
while (pos[0]) {
|
||||
if (charEscaped)
|
||||
charEscaped = false;
|
||||
else if (pos[0] == '\\') {
|
||||
charEscaped = true;
|
||||
escaped++;
|
||||
} else if ((!quoted && isspace(pos[0])) || (quoted && pos[0] == quoted))
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
|
||||
// "String exceeds line" - missing end quote
|
||||
if (quoted && pos[0] != quoted)
|
||||
return B_BAD_DATA;
|
||||
|
||||
// last character is a backslash
|
||||
if (charEscaped)
|
||||
return B_BAD_DATA;
|
||||
|
||||
end = pos[0] == '\0';
|
||||
newLine = pos[0] == '\n' || end;
|
||||
pos[0] = '\0';
|
||||
|
||||
// Correct name if there were any escaped characters
|
||||
if (escaped) {
|
||||
char *word = *_word;
|
||||
int offset = 0;
|
||||
while (word <= pos) {
|
||||
if (word[0] == '\\') {
|
||||
offset--;
|
||||
word++;
|
||||
}
|
||||
word[offset] = word[0];
|
||||
word++;
|
||||
}
|
||||
}
|
||||
|
||||
if (end) {
|
||||
*_pos = pos;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Scan for next beginning word, open brackets, or comment start
|
||||
|
||||
pos++;
|
||||
while (true) {
|
||||
*_pos = pos;
|
||||
if (!pos[0])
|
||||
return B_NO_ERROR;
|
||||
|
||||
if (pos[0] == '\n') {
|
||||
// an open bracket '{' could follow after the first
|
||||
// newline, but not later
|
||||
if (newLine)
|
||||
return B_NO_ERROR;
|
||||
|
||||
newLine = true;
|
||||
} else if (pos[0] == '{' || pos[0] == '}' || pos[0] == '#')
|
||||
return B_NO_ERROR;
|
||||
else if (!isspace(pos[0]))
|
||||
return newLine ? B_NO_ERROR : CONTINUE_PARAMETER;
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
parse_parameter(struct driver_parameter *parameter, char **_pos, int32 level)
|
||||
{
|
||||
char *pos = *_pos;
|
||||
status_t status;
|
||||
|
||||
// initialize parameter first
|
||||
memset(parameter, 0, sizeof(struct driver_parameter));
|
||||
|
||||
status = get_word(&pos, ¶meter->name, true);
|
||||
if (status == CONTINUE_PARAMETER) {
|
||||
while (status == CONTINUE_PARAMETER) {
|
||||
char **newArray, *value;
|
||||
status = get_word(&pos, &value, false);
|
||||
if (status < B_OK)
|
||||
break;
|
||||
|
||||
// enlarge value array and save the value
|
||||
|
||||
newArray = realloc(parameter->values, (parameter->value_count + 1) * sizeof(char *));
|
||||
if (newArray == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
parameter->values = newArray;
|
||||
parameter->values[parameter->value_count++] = value;
|
||||
}
|
||||
}
|
||||
*_pos = pos;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
parse_parameters(struct driver_parameter **parameters, int *count, char **pos, int32 level)
|
||||
{
|
||||
if (level > MAX_SETTINGS_LEVEL)
|
||||
return B_LINK_LIMIT;
|
||||
|
||||
while (true) {
|
||||
struct driver_parameter *newArray, *parameter;
|
||||
status_t status;
|
||||
newArray = realloc(*parameters, (*count + 1) * sizeof(struct driver_parameter));
|
||||
if (newArray == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
parameter = &newArray[*count];
|
||||
|
||||
status = parse_parameter(parameter, pos, level);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
*parameters = newArray;
|
||||
(*count)++;
|
||||
|
||||
// check for level beginning and end
|
||||
if (**pos == '{') {
|
||||
// if we go a level deeper, just start all over again...
|
||||
(*pos)++;
|
||||
status = parse_parameters(¶meter->parameters, ¶meter->parameter_count, pos, level + 1);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
if ((**pos == '}' && level > 0)
|
||||
|| (**pos == '\0' && level == 0)) {
|
||||
// take the closing bracket from the stack
|
||||
(*pos)++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// obviously, something has gone wrong
|
||||
if (**pos == '}' || **pos == '\0')
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
parse_settings(struct settings_handle *handle)
|
||||
{
|
||||
char *text = handle->text;
|
||||
|
||||
memset(&handle->settings, 0, sizeof(struct driver_settings));
|
||||
return parse_parameters(&handle->settings.parameters, &handle->settings.parameter_count, &text, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_parameter(struct driver_parameter *parameter)
|
||||
{
|
||||
int32 i;
|
||||
for (i = parameter->parameter_count; i-- > 0;)
|
||||
free_parameter(¶meter->parameters[i]);
|
||||
|
||||
free(parameter->parameters);
|
||||
free(parameter->values);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_settings(struct settings_handle *handle)
|
||||
{
|
||||
int32 i;
|
||||
for (i = handle->settings.parameter_count; i-- > 0;)
|
||||
free_parameter(&handle->settings.parameters[i]);
|
||||
|
||||
free(handle->settings.parameters);
|
||||
|
||||
free(handle->text);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
|
||||
// ToDo: the API to add an item to the driver_settings is obviously accessable
|
||||
// to the kernel, so we should provide it, too (in BeOS this is used to add
|
||||
// driver settings at boot time, using the safe boot menu).
|
||||
|
||||
//static status_t
|
||||
//add_driver_parameter(const char *name, )
|
||||
//{
|
||||
//}
|
||||
|
||||
|
||||
// ToDo: make this function available to the kernel
|
||||
|
||||
//static void
|
||||
//driver_settings_kernel_init(void)
|
||||
//{
|
||||
// // switch the disk access functions to use those from the
|
||||
// // kernel rather than those from the BIOS
|
||||
// gSettingsOps = &kKernelOps;
|
||||
//}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// The public API implementation
|
||||
|
||||
|
||||
status_t
|
||||
unload_driver_settings(void *handle)
|
||||
{
|
||||
if (!check_handle(handle))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
free_settings(handle);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
load_driver_settings(const char *driverName)
|
||||
{
|
||||
off_t size;
|
||||
int file;
|
||||
|
||||
if (driverName == NULL)
|
||||
return NULL;
|
||||
|
||||
file = gSettingsOps->open(driverName);
|
||||
if (file < B_OK)
|
||||
return NULL;
|
||||
|
||||
// Allocate a buffer and read the whole file into it.
|
||||
// We will keep this buffer in memory, until the settings
|
||||
// are unloaded.
|
||||
// The driver_parameter::name field will point directly
|
||||
// to this buffer.
|
||||
|
||||
size = gSettingsOps->filesize(file);
|
||||
if (size > B_OK && size < MAX_SETTINGS_SIZE) {
|
||||
char *text = (char *)malloc(size + 1);
|
||||
if (text != NULL && gSettingsOps->read(file, text, size) == size) {
|
||||
struct settings_handle *handle = malloc(sizeof(struct settings_handle));
|
||||
if (handle != NULL) {
|
||||
text[size] = '\0';
|
||||
|
||||
handle->magic = SETTINGS_MAGIC;
|
||||
handle->text = text;
|
||||
|
||||
if (parse_settings(handle) == B_OK) {
|
||||
gSettingsOps->close(file);
|
||||
return handle;
|
||||
}
|
||||
|
||||
free(handle);
|
||||
}
|
||||
}
|
||||
// "text" might be NULL here, but that's allowed
|
||||
free(text);
|
||||
}
|
||||
|
||||
gSettingsOps->close(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
get_driver_boolean_parameter(void *handle, const char *keyName, bool unknownValue, bool noArgValue)
|
||||
{
|
||||
driver_parameter *parameter;
|
||||
char *boolean;
|
||||
|
||||
if (!check_handle(handle))
|
||||
return unknownValue;
|
||||
|
||||
// check for the parameter
|
||||
if ((parameter = get_parameter(handle, keyName)) == NULL)
|
||||
return unknownValue;
|
||||
|
||||
// ToDo: This takes just the first argument/value, and checks that one;
|
||||
// I don't know if they are used to work that way in BeOS, though.
|
||||
// bonefish: Yep, exactly like that.
|
||||
|
||||
// check for the argument
|
||||
if (parameter->value_count <= 0)
|
||||
return noArgValue;
|
||||
|
||||
boolean = parameter->values[0];
|
||||
if (!strcmp(boolean, "1")
|
||||
|| !strcasecmp(boolean, "true")
|
||||
|| !strcasecmp(boolean, "yes")
|
||||
|| !strcasecmp(boolean, "on")
|
||||
|| !strcasecmp(boolean, "enable")
|
||||
|| !strcasecmp(boolean, "enabled"))
|
||||
return true;
|
||||
|
||||
if (!strcmp(boolean, "0")
|
||||
|| !strcasecmp(boolean, "false")
|
||||
|| !strcasecmp(boolean, "no")
|
||||
|| !strcasecmp(boolean, "off")
|
||||
|| !strcasecmp(boolean, "disable")
|
||||
|| !strcasecmp(boolean, "disabled"))
|
||||
return false;
|
||||
|
||||
// if no known keyword is found, "unknownValue" is returned
|
||||
return unknownValue;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
get_driver_parameter(void *handle, const char *keyName, const char *unknownValue, const char *noArgValue)
|
||||
{
|
||||
struct driver_parameter *parameter;
|
||||
|
||||
if (!check_handle(handle))
|
||||
return unknownValue;
|
||||
|
||||
// check for the parameter
|
||||
if ((parameter = get_parameter(handle, keyName)) == NULL)
|
||||
return unknownValue;
|
||||
|
||||
// check for the argument
|
||||
if (parameter->value_count <= 0)
|
||||
return noArgValue;
|
||||
|
||||
return parameter->values[0];
|
||||
}
|
||||
|
||||
|
||||
const driver_settings *
|
||||
get_driver_settings(void *handle)
|
||||
{
|
||||
if (!check_handle(handle))
|
||||
return NULL;
|
||||
|
||||
return &((struct settings_handle *)handle)->settings;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user