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
DriverSettingsConverter()21 DriverSettingsConverter::DriverSettingsConverter()
22 {
23 }
24
25
~DriverSettingsConverter()26 DriverSettingsConverter::~DriverSettingsConverter()
27 {
28 }
29
30
31 status_t
ConvertFromDriverSettings(const driver_parameter & parameter,const char * name,int32 index,uint32 type,BMessage & target)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
ConvertEmptyFromDriverSettings(const driver_parameter & parameter,const char * name,uint32 type,BMessage & target)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
ConvertToDriverSettings(const BMessage & source,const char * name,int32 index,uint32 type,BString & value)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
DriverSettingsMessageAdapter()60 DriverSettingsMessageAdapter::DriverSettingsMessageAdapter()
61 {
62 }
63
64
~DriverSettingsMessageAdapter()65 DriverSettingsMessageAdapter::~DriverSettingsMessageAdapter()
66 {
67 }
68
69
70 status_t
ConvertFromDriverSettings(const driver_settings & settings,const settings_template * settingsTemplate,BMessage & message)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
ConvertFromDriverSettings(const char * path,const settings_template * settingsTemplate,BMessage & message)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
ConvertToDriverSettings(const settings_template * settingsTemplate,BString & settings,const BMessage & message)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
ConvertToDriverSettings(const char * path,const settings_template * settingsTemplate,const BMessage & message)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*
_FindSettingsTemplate(const settings_template * settingsTemplate,const char * name)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*
_FindParentValueTemplate(const settings_template * settingsTemplate)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
_AddParameter(const driver_parameter & parameter,const settings_template & settingsTemplate,BMessage & message)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
_ConvertFromDriverParameter(const driver_parameter & parameter,const settings_template * settingsTemplate,BMessage & message)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
_AppendSettings(const settings_template * settingsTemplate,BString & settings,const BMessage & message,const char * name,type_code type,int32 count,const char * settingName)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