xref: /haiku/src/kits/shared/DriverSettingsMessageAdapter.cpp (revision c2751c41b7404c4e7b0b6ed723b92505a6cf332b)
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