BeOS drivers are allowed to open files, but there are a few reasons why you don't want to do this to read settings. For one thing, if your driver is loaded before the file system, you can't open your settings file. If the boot volume's disk driver needs information from the settings file before it can access the disk, just opening a file won't work. Also, parsing settings files can be complicated by corrupt files, and a crash in driver code is fatal.
The next BeOS release will have an API for drivers and kernel modules to get settings. The API includes easy access to Boolean and string settings, and is available for all drivers and modules. For complex settings, a call is provided that returns the settings as a tree of parameters and values. The boot loader reads the settings files from the selected boot volume and passes them to the kernel for use by drivers. The boot loader also lets the user append settings at boot time. A line of the form "filename:parameters" in the advanced savemode menu will add "parameters" to the end of the specified settings file. This can be used to change debugging information, and to test different options on hardware where the driver doesn't work. For beta testers, all this should already work in 4.1b3.
The functions are defined as follows:
void *load driver settings(const char *drivername); status t unload driver settings(void *handle); const char *get driver parameter(void *handle, const char *keyname, const char *unknownvalue, const char *noargvalue); bool get driver boolean parameter(void *handle, const char *keyname, bool unknownvalue, bool noargvalue); const driver settings *get driver settings(void *handle);
A driver calls load driver settings with the name of the settings file as the argument (settingshandle = load driver settings(drivername);). This returns a handle that is passed to the other driver settings functions. The driver can look for specific parameters by calling get driver parameter and get driver boolean parameter, or it can get a pointer to the parsed settings from get driver settings. When the settings have been processed, unload driver settings will free the resources.
Let's look a simple example first. A driver "sample1" has one setting, "foo", that can be true or false. To specify the value of "foo", a line of form "foo value" is placed in the settings file. If there is no entry for "foo" in the file, the default is false; if there is an entry "foo" but no value is specified, we assume the value is true. The code for our example looks like this:
void *settingshandle; bool foo; settingshandle = load driver settings("sample1"); foo = get driver boolean parameter(settingshandle, "foo", false, true); unload driver settings(settingshandle);
Now let's look at how this works. If there is no settings file named "sample1" in ~/config/settings/kernel/drivers/, load driver settings will return NULL. Since we pass NULL to get driver boolean parameter it will return the value we specified for no entry: false. "foo" will therefore be false.
If the file exists, but doesn't contain an entry "foo", the result is the same. In this case, we get a valid handle and get driver boolean parameter will look for a "foo" parameter in the file. Since the file doesn't contain "foo", it returns false as requested.
If the file contains one line starting with "foo", the second word in this line is used as the value. If no value is specified, get driver boolean parameter will return the last argument passed. If a value is specified and is one of the strings "1", "true", "yes", "on", "enable", or "enabled", true will be returned. If the value is "0", "false", "no", "off", "disable", or "disabled", false is returned. If the value doesn't match any of these strings it is treated the same as if no entry was found; in this case, false.
If more than one line in the file starts with "foo", the last one is used. This allows the user to override settings from the boot loader.
Another simple case is when a driver has a string setting.
void *settingshandle; const char *string; settingshandle = load driver settings("sample1"); string = get driver parameter(settingshandle, "string", NULL, "default"); unload driver settings(settingshandle);
This works the same way as get driver boolean parameter, except that the string value of string is returned instead of the logical value. If the file doesn't exist, or exists but has no line starting with "string", string will be NULL. If the last line starting with "string" has no values, string will be "default". If string has a value, it is returned as a string. Note that only one value is returned. If more than one value is needed for a key, use get driver settings and search for your key.
For drivers that need complex settings, the get driver settings will return the settings file as a tree. This tree allows a parameter to have multiple values and subparameters.
The following structure holds the root of the tree.
typedef struct driver settings { int parameter count; struct driver parameter *parameters; } driver settings;
Each parameter is of the form:
typedef struct driver parameter { char *name; int value count; char **values; int parameter count; struct driver parameter *parameters; } driver parameter;
The settings file follows these rules:
name [value]* [{ [parameter]* }] ['\n',',']
( [] optional part, []* optional repeated part )
Here's an example that clarifies these points. For the file:
device 0 { attribute1 value attribute2 value } device 1 { attribute1 value }
get driver settings will return a pointer to the following tree:
Copyright ©1999 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com.driver settings = { parameter count = 2 parameters = { { name = "device" value count = 1 values = { "0" } parameter count = 2 parameters = { { name = "attribute1" value count = 1 values = "value" parameter count = 0 parameters = NULL }, { name = "attribute2" value count = 1 values = "value" parameter count = 0 parameters = NULL } } }, { name = "device" value count = 1 values = { "1" } parameter count = 1 parameters = { { name = "attribute1" value count = 1 values = "value" parameter count = 0 parameters = NULL } } } } }