/* * 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 */ #include "DriverSettingsMessageAdapter.h" #include #include #include #include #include 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; } // #pragma mark - 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) { // ignore unknown entries 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; } // #pragma mark - 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: // Is handled outside of this method 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) { // Empty boolean parameters are always true 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) { // We almost silently ignore this kind of issues 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; }