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