xref: /haiku/src/kits/shared/DriverSettingsMessageAdapter.cpp (revision a30a4a41f948ebb03b95dab065a27a584ac0c97a)
1 /*
2  * Copyright 2006-2013, 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 
16 #include <File.h>
17 #include <String.h>
18 
19 
20 DriverSettingsMessageAdapter::DriverSettingsMessageAdapter()
21 {
22 }
23 
24 
25 DriverSettingsMessageAdapter::~DriverSettingsMessageAdapter()
26 {
27 }
28 
29 
30 status_t
31 DriverSettingsMessageAdapter::ConvertFromDriverSettings(
32 	const driver_settings& settings, const settings_template* settingsTemplate,
33 	BMessage& message)
34 {
35 	message.MakeEmpty();
36 
37 	for (int32 i = 0; i < settings.parameter_count; i++) {
38 		status_t status = _ConvertFromDriverParameter(settings.parameters[i],
39 			settingsTemplate, message);
40 		if (status == B_BAD_VALUE) {
41 			// ignore unknown entries
42 			continue;
43 		}
44 		if (status != B_OK)
45 			return status;
46 	}
47 
48 	return B_OK;
49 }
50 
51 
52 status_t
53 DriverSettingsMessageAdapter::ConvertFromDriverSettings(const char* path,
54 	const settings_template* settingsTemplate, BMessage& message)
55 {
56 	void* handle = load_driver_settings(path);
57 	if (handle == NULL)
58 		return B_ENTRY_NOT_FOUND;
59 
60 	const driver_settings* settings = get_driver_settings(handle);
61 	status_t status;
62 	if (settings != NULL) {
63 		status = ConvertFromDriverSettings(*settings, settingsTemplate,
64 			message);
65 	} else
66 		status = B_BAD_DATA;
67 
68 	unload_driver_settings(handle);
69 	return status;
70 }
71 
72 
73 status_t
74 DriverSettingsMessageAdapter::ConvertToDriverSettings(
75 	const settings_template* settingsTemplate, BString& settings,
76 	const BMessage& message)
77 {
78 	int32 index = 0;
79 	char *name = NULL;
80 	type_code type;
81 	int32 count = 0;
82 
83 	while (message.GetInfo(B_ANY_TYPE, index++, &name, &type, &count) == B_OK) {
84 		status_t result = _AppendSettings(settingsTemplate, settings, message,
85 			name, type, count);
86 		if (result != B_OK)
87 			return result;
88 	}
89 
90 	return B_OK;
91 }
92 
93 
94 status_t
95 DriverSettingsMessageAdapter::ConvertToDriverSettings(const char* path,
96 	const settings_template* settingsTemplate, const BMessage& message)
97 {
98 	BString settings;
99 	status_t status = ConvertToDriverSettings(settingsTemplate, settings,
100 		message);
101 	if (status != B_OK)
102 		return status;
103 
104 	settings.RemoveFirst("\n");
105 	BFile settingsFile(path, B_WRITE_ONLY | B_ERASE_FILE | B_CREATE_FILE);
106 
107 	ssize_t written = settingsFile.Write(settings.String(), settings.Length());
108 	if (written < 0)
109 		return written;
110 
111 	return written == settings.Length() ? B_OK : B_ERROR;
112 }
113 
114 
115 // #pragma mark -
116 
117 
118 const settings_template*
119 DriverSettingsMessageAdapter::_FindSettingsTemplate(
120 	const settings_template* settingsTemplate, const char* name)
121 {
122 	while (settingsTemplate->name != NULL) {
123 		if (!strcmp(name, settingsTemplate->name))
124 			return settingsTemplate;
125 
126 		settingsTemplate++;
127 	}
128 
129 	return NULL;
130 }
131 
132 
133 const settings_template*
134 DriverSettingsMessageAdapter::_FindParentValueTemplate(
135 	const settings_template* settingsTemplate)
136 {
137 	settingsTemplate = settingsTemplate->sub_template;
138 	if (settingsTemplate == NULL)
139 		return NULL;
140 
141 	while (settingsTemplate->name != NULL) {
142 		if (settingsTemplate->parent_value)
143 			return settingsTemplate;
144 
145 		settingsTemplate++;
146 	}
147 
148 	return NULL;
149 }
150 
151 
152 status_t
153 DriverSettingsMessageAdapter::_AddParameter(const driver_parameter& parameter,
154 	const char* name, uint32 type, BMessage& message)
155 {
156 	for (int32 i = 0; i < parameter.value_count; i++) {
157 		switch (type) {
158 			case B_STRING_TYPE:
159 				message.AddString(name, parameter.values[i]);
160 				break;
161 			case B_INT32_TYPE:
162 				message.AddInt32(name, atoi(parameter.values[i]));
163 				break;
164 			case B_BOOL_TYPE:
165 				if (!strcasecmp(parameter.values[i], "true")
166 					|| !strcasecmp(parameter.values[i], "on")
167 					|| !strcasecmp(parameter.values[i], "enabled")
168 					|| !strcasecmp(parameter.values[i], "1"))
169 					message.AddBool(name, true);
170 				else
171 					message.AddBool(name, false);
172 				break;
173 		}
174 	}
175 	if (type == B_BOOL_TYPE && parameter.value_count == 0) {
176 		// boolean parameters are always true
177 		message.AddBool(name, true);
178 	}
179 
180 	return B_OK;
181 }
182 
183 
184 status_t
185 DriverSettingsMessageAdapter::_ConvertFromDriverParameter(
186 	const driver_parameter& parameter,
187 	const settings_template* settingsTemplate, BMessage& message)
188 {
189 	settingsTemplate = _FindSettingsTemplate(settingsTemplate, parameter.name);
190 	if (settingsTemplate == NULL) {
191 		fprintf(stderr, "unknown parameter %s\n", parameter.name);
192 		return B_BAD_VALUE;
193 	}
194 
195 	_AddParameter(parameter, parameter.name, settingsTemplate->type, message);
196 
197 	if (settingsTemplate->type == B_MESSAGE_TYPE
198 		&& parameter.parameter_count > 0) {
199 		status_t status = B_OK;
200 		BMessage subMessage;
201 		for (int32 j = 0; j < parameter.parameter_count; j++) {
202 			status = _ConvertFromDriverParameter(parameter.parameters[j],
203 				settingsTemplate->sub_template, subMessage);
204 			if (status != B_OK)
205 				break;
206 
207 			const settings_template* parentValueTemplate
208 				= _FindParentValueTemplate(settingsTemplate);
209 			if (parentValueTemplate != NULL) {
210 				_AddParameter(parameter, parentValueTemplate->name,
211 					parentValueTemplate->type, subMessage);
212 			}
213 		}
214 		if (status == B_OK)
215 			message.AddMessage(parameter.name, &subMessage);
216 	}
217 
218 	return B_OK;
219 }
220 
221 
222 status_t
223 DriverSettingsMessageAdapter::_AppendSettings(
224 	const settings_template* settingsTemplate, BString& settings,
225 	const BMessage& message, const char* name, type_code type, int32 count,
226 	const char* settingName)
227 {
228 	const settings_template* valueTemplate
229 		= _FindSettingsTemplate(settingsTemplate, name);
230 	if (valueTemplate == NULL) {
231 		fprintf(stderr, "unknown field %s\n", name);
232 		return B_BAD_VALUE;
233 	}
234 
235 	if (valueTemplate->type != type) {
236 		fprintf(stderr, "field type mismatch %s\n", name);
237 		return B_BAD_VALUE;
238 	}
239 
240 	if (settingName == NULL)
241 		settingName = name;
242 
243 	if (type != B_MESSAGE_TYPE) {
244 		settings.Append("\n");
245 		settings.Append(settingName);
246 		settings.Append("\t");
247 	}
248 
249 	for (int32 valueIndex = 0; valueIndex < count; valueIndex++) {
250 		if (valueIndex > 0 && type != B_MESSAGE_TYPE)
251 			settings.Append(" ");
252 
253 		switch (type) {
254 			case B_BOOL_TYPE:
255 			{
256 				bool value;
257 				status_t result = message.FindBool(name, valueIndex, &value);
258 				if (result != B_OK)
259 					return result;
260 
261 				settings.Append(value ? "true" : "false");
262 				break;
263 			}
264 
265 			case B_STRING_TYPE:
266 			{
267 				const char* value = NULL;
268 				status_t result = message.FindString(name, valueIndex, &value);
269 				if (result != B_OK)
270 					return result;
271 
272 				settings.Append(value);
273 				break;
274 			}
275 
276 			case B_INT32_TYPE:
277 			{
278 				int32 value;
279 				status_t result = message.FindInt32(name, valueIndex, &value);
280 				if (result != B_OK)
281 					return result;
282 
283 				char buffer[100];
284 				snprintf(buffer, sizeof(buffer), "%" B_PRId32, value);
285 				settings.Append(buffer, sizeof(buffer));
286 				break;
287 			}
288 
289 			case B_MESSAGE_TYPE:
290 			{
291 				BMessage subMessage;
292 				status_t result = message.FindMessage(name, valueIndex,
293 					&subMessage);
294 				if (result != B_OK)
295 					return result;
296 
297 				const settings_template* parentValueTemplate
298 					= _FindParentValueTemplate(valueTemplate);
299 				if (parentValueTemplate != NULL) {
300 					_AppendSettings(valueTemplate->sub_template, settings,
301 						subMessage, parentValueTemplate->name,
302 						parentValueTemplate->type, 1, name);
303 					subMessage.RemoveName(parentValueTemplate->name);
304 				}
305 
306 				BString subSettings;
307 				ConvertToDriverSettings(valueTemplate->sub_template,
308 					subSettings, subMessage);
309 				subSettings.ReplaceAll("\n", "\n\t");
310 				subSettings.RemoveFirst("\n");
311 
312 				settings.Append(" {\n");
313 				settings.Append(subSettings);
314 				settings.Append("\n}");
315 			}
316 		}
317 	}
318 
319 	return B_OK;
320 }
321