* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "DriverSettingsMessageAdapter.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <File.h>
#include <String.h>
DriverSettingsConverter::DriverSettingsConverter()
{
}
DriverSettingsConverter::~DriverSettingsConverter()
{
}
status_t
DriverSettingsConverter::ConvertFromDriverSettings(
const driver_parameter& parameter, const char* name, int32 index,
uint32 type, BMessage& target)
{
return B_NOT_SUPPORTED;
}
status_t
DriverSettingsConverter::ConvertEmptyFromDriverSettings(
const driver_parameter& parameter, const char* name, uint32 type,
BMessage& target)
{
return B_NOT_SUPPORTED;
}
status_t
DriverSettingsConverter::ConvertToDriverSettings(const BMessage& source,
const char* name, int32 index, uint32 type, BString& value)
{
return B_NOT_SUPPORTED;
}
DriverSettingsMessageAdapter::DriverSettingsMessageAdapter()
{
}
DriverSettingsMessageAdapter::~DriverSettingsMessageAdapter()
{
}
status_t
DriverSettingsMessageAdapter::ConvertFromDriverSettings(
const driver_settings& settings, const settings_template* settingsTemplate,
BMessage& message)
{
message.MakeEmpty();
for (int32 i = 0; i < settings.parameter_count; i++) {
status_t status = _ConvertFromDriverParameter(settings.parameters[i],
settingsTemplate, message);
if (status == B_BAD_VALUE) {
continue;
}
if (status != B_OK)
return status;
}
return B_OK;
}
status_t
DriverSettingsMessageAdapter::ConvertFromDriverSettings(const char* path,
const settings_template* settingsTemplate, BMessage& message)
{
void* handle = load_driver_settings(path);
if (handle == NULL)
return B_ENTRY_NOT_FOUND;
const driver_settings* settings = get_driver_settings(handle);
status_t status;
if (settings != NULL) {
status = ConvertFromDriverSettings(*settings, settingsTemplate,
message);
} else
status = B_BAD_DATA;
unload_driver_settings(handle);
return status;
}
status_t
DriverSettingsMessageAdapter::ConvertToDriverSettings(
const settings_template* settingsTemplate, BString& settings,
const BMessage& message)
{
int32 index = 0;
char *name = NULL;
type_code type;
int32 count = 0;
while (message.GetInfo(B_ANY_TYPE, index++, &name, &type, &count) == B_OK) {
status_t result = _AppendSettings(settingsTemplate, settings, message,
name, type, count);
if (result != B_OK)
return result;
}
return B_OK;
}
status_t
DriverSettingsMessageAdapter::ConvertToDriverSettings(const char* path,
const settings_template* settingsTemplate, const BMessage& message)
{
BString settings;
status_t status = ConvertToDriverSettings(settingsTemplate, settings,
message);
if (status != B_OK)
return status;
settings.RemoveFirst("\n");
BFile settingsFile(path, B_WRITE_ONLY | B_ERASE_FILE | B_CREATE_FILE);
ssize_t written = settingsFile.Write(settings.String(), settings.Length());
if (written < 0)
return written;
return written == settings.Length() ? B_OK : B_ERROR;
}
const settings_template*
DriverSettingsMessageAdapter::_FindSettingsTemplate(
const settings_template* settingsTemplate, const char* name)
{
const settings_template* wildcardTemplate = NULL;
while (settingsTemplate->type != 0) {
if (settingsTemplate->name != NULL
&& !strcmp(name, settingsTemplate->name))
return settingsTemplate;
if (settingsTemplate->name == NULL)
wildcardTemplate = settingsTemplate;
settingsTemplate++;
}
return wildcardTemplate;
}
const settings_template*
DriverSettingsMessageAdapter::_FindParentValueTemplate(
const settings_template* settingsTemplate)
{
settingsTemplate = settingsTemplate->sub_template;
if (settingsTemplate == NULL)
return NULL;
while (settingsTemplate->type != 0) {
if (settingsTemplate->parent_value)
return settingsTemplate;
settingsTemplate++;
}
return NULL;
}
status_t
DriverSettingsMessageAdapter::_AddParameter(const driver_parameter& parameter,
const settings_template& settingsTemplate, BMessage& message)
{
const char* name = settingsTemplate.name;
if (name == NULL)
name = parameter.name;
for (int32 i = 0; i < parameter.value_count; i++) {
if (settingsTemplate.converter != NULL) {
status_t status
= settingsTemplate.converter->ConvertFromDriverSettings(
parameter, name, i, settingsTemplate.type, message);
if (status == B_OK)
continue;
if (status != B_NOT_SUPPORTED)
return status;
}
status_t status = B_OK;
switch (settingsTemplate.type) {
case B_STRING_TYPE:
status = message.AddString(name, parameter.values[i]);
break;
case B_INT32_TYPE:
status = message.AddInt32(name, atoi(parameter.values[i]));
break;
case B_BOOL_TYPE:
{
bool value=!strcasecmp(parameter.values[i], "true")
|| !strcasecmp(parameter.values[i], "on")
|| !strcasecmp(parameter.values[i], "yes")
|| !strcasecmp(parameter.values[i], "enabled")
|| !strcasecmp(parameter.values[i], "1");
status = message.AddBool(name, value);
break;
}
case B_MESSAGE_TYPE:
break;
default:
return B_BAD_VALUE;
}
if (status != B_OK)
return status;
}
if (parameter.value_count == 0) {
if (settingsTemplate.converter != NULL) {
status_t status
= settingsTemplate.converter->ConvertEmptyFromDriverSettings(
parameter, name, settingsTemplate.type, message);
if (status == B_NOT_SUPPORTED)
return B_OK;
} else if (settingsTemplate.type == B_BOOL_TYPE) {
return message.AddBool(name, true);
}
}
return B_OK;
}
status_t
DriverSettingsMessageAdapter::_ConvertFromDriverParameter(
const driver_parameter& parameter,
const settings_template* settingsTemplate, BMessage& message)
{
settingsTemplate = _FindSettingsTemplate(settingsTemplate, parameter.name);
if (settingsTemplate == NULL) {
fprintf(stderr, "unknown parameter %s\n", parameter.name);
return B_OK;
}
status_t status = _AddParameter(parameter, *settingsTemplate, message);
if (status != B_OK)
return status;
if (settingsTemplate->type == B_MESSAGE_TYPE) {
BMessage subMessage;
for (int32 j = 0; j < parameter.parameter_count; j++) {
status = _ConvertFromDriverParameter(parameter.parameters[j],
settingsTemplate->sub_template, subMessage);
if (status != B_OK)
return status;
}
const settings_template* parentValueTemplate
= _FindParentValueTemplate(settingsTemplate);
if (parentValueTemplate != NULL)
status = _AddParameter(parameter, *parentValueTemplate, subMessage);
if (status == B_OK)
status = message.AddMessage(parameter.name, &subMessage);
}
return status;
}
status_t
DriverSettingsMessageAdapter::_AppendSettings(
const settings_template* settingsTemplate, BString& settings,
const BMessage& message, const char* name, type_code type, int32 count,
const char* settingName)
{
const settings_template* valueTemplate
= _FindSettingsTemplate(settingsTemplate, name);
if (valueTemplate == NULL) {
fprintf(stderr, "unknown field %s\n", name);
return B_BAD_VALUE;
}
if (valueTemplate->type != type) {
fprintf(stderr, "field type mismatch %s\n", name);
return B_BAD_VALUE;
}
if (settingName == NULL)
settingName = name;
if (type != B_MESSAGE_TYPE) {
settings.Append("\n");
settings.Append(settingName);
settings.Append("\t");
}
for (int32 valueIndex = 0; valueIndex < count; valueIndex++) {
if (valueIndex > 0 && type != B_MESSAGE_TYPE)
settings.Append(" ");
if (valueTemplate->converter != NULL) {
status_t status = valueTemplate->converter->ConvertToDriverSettings(
message, name, type, valueIndex, settings);
if (status == B_OK)
continue;
if (status != B_NOT_SUPPORTED)
return status;
}
switch (type) {
case B_BOOL_TYPE:
{
bool value;
status_t result = message.FindBool(name, valueIndex, &value);
if (result != B_OK)
return result;
settings.Append(value ? "true" : "false");
break;
}
case B_STRING_TYPE:
{
const char* value = NULL;
status_t result = message.FindString(name, valueIndex, &value);
if (result != B_OK)
return result;
settings.Append(value);
break;
}
case B_INT32_TYPE:
{
int32 value;
status_t result = message.FindInt32(name, valueIndex, &value);
if (result != B_OK)
return result;
char buffer[100];
snprintf(buffer, sizeof(buffer), "%" B_PRId32, value);
settings.Append(buffer, sizeof(buffer));
break;
}
case B_MESSAGE_TYPE:
{
BMessage subMessage;
status_t result = message.FindMessage(name, valueIndex,
&subMessage);
if (result != B_OK)
return result;
const settings_template* parentValueTemplate
= _FindParentValueTemplate(valueTemplate);
if (parentValueTemplate != NULL) {
_AppendSettings(valueTemplate->sub_template, settings,
subMessage, parentValueTemplate->name,
parentValueTemplate->type, 1, name);
subMessage.RemoveName(parentValueTemplate->name);
}
BString subSettings;
ConvertToDriverSettings(valueTemplate->sub_template,
subSettings, subMessage);
subSettings.ReplaceAll("\n", "\n\t");
subSettings.RemoveFirst("\n");
if (!subSettings.IsEmpty()) {
settings.Append(" {\n");
settings.Append(subSettings);
settings.Append("\n}");
}
}
}
}
return B_OK;
}