1 /* 2 * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Michael Lotz <mmlr@mlotz.ch> 8 */ 9 10 11 #include "DriverSettingsMessageAdapter.h" 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <strings.h> 16 17 #include <File.h> 18 #include <String.h> 19 20 21 DriverSettingsConverter::DriverSettingsConverter() 22 { 23 } 24 25 26 DriverSettingsConverter::~DriverSettingsConverter() 27 { 28 } 29 30 31 // #pragma mark - 32 33 34 DriverSettingsMessageAdapter::DriverSettingsMessageAdapter() 35 { 36 } 37 38 39 DriverSettingsMessageAdapter::~DriverSettingsMessageAdapter() 40 { 41 } 42 43 44 status_t 45 DriverSettingsMessageAdapter::ConvertFromDriverSettings( 46 const driver_settings& settings, const settings_template* settingsTemplate, 47 BMessage& message) 48 { 49 message.MakeEmpty(); 50 51 for (int32 i = 0; i < settings.parameter_count; i++) { 52 status_t status = _ConvertFromDriverParameter(settings.parameters[i], 53 settingsTemplate, message); 54 if (status == B_BAD_VALUE) { 55 // ignore unknown entries 56 continue; 57 } 58 if (status != B_OK) 59 return status; 60 } 61 62 return B_OK; 63 } 64 65 66 status_t 67 DriverSettingsMessageAdapter::ConvertFromDriverSettings(const char* path, 68 const settings_template* settingsTemplate, BMessage& message) 69 { 70 void* handle = load_driver_settings(path); 71 if (handle == NULL) 72 return B_ENTRY_NOT_FOUND; 73 74 const driver_settings* settings = get_driver_settings(handle); 75 status_t status; 76 if (settings != NULL) { 77 status = ConvertFromDriverSettings(*settings, settingsTemplate, 78 message); 79 } else 80 status = B_BAD_DATA; 81 82 unload_driver_settings(handle); 83 return status; 84 } 85 86 87 status_t 88 DriverSettingsMessageAdapter::ConvertToDriverSettings( 89 const settings_template* settingsTemplate, BString& settings, 90 const BMessage& message) 91 { 92 int32 index = 0; 93 char *name = NULL; 94 type_code type; 95 int32 count = 0; 96 97 while (message.GetInfo(B_ANY_TYPE, index++, &name, &type, &count) == B_OK) { 98 status_t result = _AppendSettings(settingsTemplate, settings, message, 99 name, type, count); 100 if (result != B_OK) 101 return result; 102 } 103 104 return B_OK; 105 } 106 107 108 status_t 109 DriverSettingsMessageAdapter::ConvertToDriverSettings(const char* path, 110 const settings_template* settingsTemplate, const BMessage& message) 111 { 112 BString settings; 113 status_t status = ConvertToDriverSettings(settingsTemplate, settings, 114 message); 115 if (status != B_OK) 116 return status; 117 118 settings.RemoveFirst("\n"); 119 BFile settingsFile(path, B_WRITE_ONLY | B_ERASE_FILE | B_CREATE_FILE); 120 121 ssize_t written = settingsFile.Write(settings.String(), settings.Length()); 122 if (written < 0) 123 return written; 124 125 return written == settings.Length() ? B_OK : B_ERROR; 126 } 127 128 129 // #pragma mark - 130 131 132 const settings_template* 133 DriverSettingsMessageAdapter::_FindSettingsTemplate( 134 const settings_template* settingsTemplate, const char* name) 135 { 136 while (settingsTemplate->name != NULL) { 137 if (!strcmp(name, settingsTemplate->name)) 138 return settingsTemplate; 139 140 settingsTemplate++; 141 } 142 143 return NULL; 144 } 145 146 147 const settings_template* 148 DriverSettingsMessageAdapter::_FindParentValueTemplate( 149 const settings_template* settingsTemplate) 150 { 151 settingsTemplate = settingsTemplate->sub_template; 152 if (settingsTemplate == NULL) 153 return NULL; 154 155 while (settingsTemplate->name != NULL) { 156 if (settingsTemplate->parent_value) 157 return settingsTemplate; 158 159 settingsTemplate++; 160 } 161 162 return NULL; 163 } 164 165 166 status_t 167 DriverSettingsMessageAdapter::_AddParameter(const driver_parameter& parameter, 168 const settings_template& settingsTemplate, BMessage& message) 169 { 170 for (int32 i = 0; i < parameter.value_count; i++) { 171 if (settingsTemplate.converter != NULL) { 172 status_t status 173 = settingsTemplate.converter->ConvertFromDriverSettings( 174 parameter, settingsTemplate.name, i, settingsTemplate.type, 175 message); 176 if (status == B_OK) 177 continue; 178 if (status != B_NOT_SUPPORTED) 179 return status; 180 } 181 182 status_t status = B_OK; 183 184 switch (settingsTemplate.type) { 185 case B_STRING_TYPE: 186 status = message.AddString(settingsTemplate.name, 187 parameter.values[i]); 188 break; 189 case B_INT32_TYPE: 190 status = message.AddInt32(settingsTemplate.name, 191 atoi(parameter.values[i])); 192 break; 193 case B_BOOL_TYPE: 194 { 195 bool value=!strcasecmp(parameter.values[i], "true") 196 || !strcasecmp(parameter.values[i], "on") 197 || !strcasecmp(parameter.values[i], "yes") 198 || !strcasecmp(parameter.values[i], "enabled") 199 || !strcasecmp(parameter.values[i], "1"); 200 status = message.AddBool(settingsTemplate.name, value); 201 break; 202 } 203 case B_MESSAGE_TYPE: 204 // Is handled outside of this method 205 break; 206 207 default: 208 return B_BAD_VALUE; 209 } 210 if (status != B_OK) 211 return status; 212 } 213 if (settingsTemplate.type == B_BOOL_TYPE && parameter.value_count == 0) { 214 // Empty boolean parameters are always true 215 return message.AddBool(settingsTemplate.name, true); 216 } 217 218 return B_OK; 219 } 220 221 222 status_t 223 DriverSettingsMessageAdapter::_ConvertFromDriverParameter( 224 const driver_parameter& parameter, 225 const settings_template* settingsTemplate, BMessage& message) 226 { 227 settingsTemplate = _FindSettingsTemplate(settingsTemplate, parameter.name); 228 if (settingsTemplate == NULL) { 229 // We almost silently ignore this kind of issues 230 fprintf(stderr, "unknown parameter %s\n", parameter.name); 231 return B_OK; 232 } 233 234 status_t status = _AddParameter(parameter, *settingsTemplate, message); 235 if (status != B_OK) 236 return status; 237 238 if (settingsTemplate->type == B_MESSAGE_TYPE) { 239 BMessage subMessage; 240 for (int32 j = 0; j < parameter.parameter_count; j++) { 241 status = _ConvertFromDriverParameter(parameter.parameters[j], 242 settingsTemplate->sub_template, subMessage); 243 if (status != B_OK) 244 return status; 245 } 246 247 const settings_template* parentValueTemplate 248 = _FindParentValueTemplate(settingsTemplate); 249 if (parentValueTemplate != NULL) 250 status = _AddParameter(parameter, *parentValueTemplate, subMessage); 251 if (status == B_OK) 252 status = message.AddMessage(parameter.name, &subMessage); 253 } 254 255 return status; 256 } 257 258 259 status_t 260 DriverSettingsMessageAdapter::_AppendSettings( 261 const settings_template* settingsTemplate, BString& settings, 262 const BMessage& message, const char* name, type_code type, int32 count, 263 const char* settingName) 264 { 265 const settings_template* valueTemplate 266 = _FindSettingsTemplate(settingsTemplate, name); 267 if (valueTemplate == NULL) { 268 fprintf(stderr, "unknown field %s\n", name); 269 return B_BAD_VALUE; 270 } 271 272 if (valueTemplate->type != type) { 273 fprintf(stderr, "field type mismatch %s\n", name); 274 return B_BAD_VALUE; 275 } 276 277 if (settingName == NULL) 278 settingName = name; 279 280 if (type != B_MESSAGE_TYPE) { 281 settings.Append("\n"); 282 settings.Append(settingName); 283 settings.Append("\t"); 284 } 285 286 for (int32 valueIndex = 0; valueIndex < count; valueIndex++) { 287 if (valueIndex > 0 && type != B_MESSAGE_TYPE) 288 settings.Append(" "); 289 290 if (valueTemplate->converter != NULL) { 291 status_t status = valueTemplate->converter->ConvertToDriverSettings( 292 message, name, type, valueIndex, settings); 293 if (status == B_OK) 294 continue; 295 if (status != B_NOT_SUPPORTED) 296 return status; 297 } 298 299 switch (type) { 300 case B_BOOL_TYPE: 301 { 302 bool value; 303 status_t result = message.FindBool(name, valueIndex, &value); 304 if (result != B_OK) 305 return result; 306 307 settings.Append(value ? "true" : "false"); 308 break; 309 } 310 311 case B_STRING_TYPE: 312 { 313 const char* value = NULL; 314 status_t result = message.FindString(name, valueIndex, &value); 315 if (result != B_OK) 316 return result; 317 318 settings.Append(value); 319 break; 320 } 321 322 case B_INT32_TYPE: 323 { 324 int32 value; 325 status_t result = message.FindInt32(name, valueIndex, &value); 326 if (result != B_OK) 327 return result; 328 329 char buffer[100]; 330 snprintf(buffer, sizeof(buffer), "%" B_PRId32, value); 331 settings.Append(buffer, sizeof(buffer)); 332 break; 333 } 334 335 case B_MESSAGE_TYPE: 336 { 337 BMessage subMessage; 338 status_t result = message.FindMessage(name, valueIndex, 339 &subMessage); 340 if (result != B_OK) 341 return result; 342 343 const settings_template* parentValueTemplate 344 = _FindParentValueTemplate(valueTemplate); 345 if (parentValueTemplate != NULL) { 346 _AppendSettings(valueTemplate->sub_template, settings, 347 subMessage, parentValueTemplate->name, 348 parentValueTemplate->type, 1, name); 349 subMessage.RemoveName(parentValueTemplate->name); 350 } 351 352 BString subSettings; 353 ConvertToDriverSettings(valueTemplate->sub_template, 354 subSettings, subMessage); 355 subSettings.ReplaceAll("\n", "\n\t"); 356 subSettings.RemoveFirst("\n"); 357 358 if (!subSettings.IsEmpty()) { 359 settings.Append(" {\n"); 360 settings.Append(subSettings); 361 settings.Append("\n}"); 362 } 363 } 364 } 365 } 366 367 return B_OK; 368 } 369