1// DriverSettings.cpp
2
3#include <new>
4#include <stdlib.h>
5#include <string.h>
6
7#include <driver_settings.h>
8
9#include <Referenceable.h>
10
11#include "DriverSettings.h"
12#include "String.h"
13
14// The parameter values that shall be evaluated to true.
15static const char* kTrueValueStrings[]
16	= { "1", "true", "yes", "on", "enable", "enabled" };
17static const int32 kTrueValueStringCount
18	= sizeof(kTrueValueStrings) / sizeof(const char*);
19
20
21// #pragma mark -
22// #pragma mark ----- DriverParameterIterator -----
23
24// Delegate
25class DriverParameterIterator::Delegate : public BReferenceable {
26public:
27								Delegate() : BReferenceable() {}
28	virtual						~Delegate() {}
29
30	virtual	Delegate*			Clone() const = 0;
31
32	virtual	bool				HasNext() const = 0;
33	virtual	bool				GetNext(DriverParameter* parameter) = 0;
34};
35
36// constructor
37DriverParameterIterator::DriverParameterIterator()
38	: fDelegate(NULL)
39{
40}
41
42// constructor
43DriverParameterIterator::DriverParameterIterator(Delegate* delegate)
44	: fDelegate(delegate)
45{
46}
47
48// copy constructor
49DriverParameterIterator::DriverParameterIterator(
50	const DriverParameterIterator& other)
51	: fDelegate(NULL)
52{
53	_SetTo(other.fDelegate, true);
54}
55
56// destructor
57DriverParameterIterator::~DriverParameterIterator()
58{
59	_SetTo(NULL, false);
60}
61
62// HasNext
63bool
64DriverParameterIterator::HasNext() const
65{
66	return (fDelegate ? fDelegate->HasNext() : false);
67}
68
69// GetNext
70bool
71DriverParameterIterator::GetNext(DriverParameter* parameter)
72{
73	if (!fDelegate)
74		return false;
75	if (fDelegate->CountReferences() > 1) {
76		Delegate* clone = fDelegate->Clone();
77		if (!clone)
78			return false;
79		_SetTo(clone, false);
80	}
81	return fDelegate->GetNext(parameter);
82}
83
84// =
85DriverParameterIterator&
86DriverParameterIterator::operator=(const DriverParameterIterator& other)
87{
88	_SetTo(other.fDelegate, true);
89	return *this;
90}
91
92// _SetTo
93void
94DriverParameterIterator::_SetTo(Delegate* delegate, bool addReference)
95{
96	if (fDelegate)
97		fDelegate->ReleaseReference();
98	fDelegate = delegate;
99	if (fDelegate && addReference)
100		fDelegate->AcquireReference();
101}
102
103
104// #pragma mark -
105// #pragma mark ----- DriverParameterContainer -----
106
107// Iterator
108class DriverParameterContainer::Iterator
109	: public DriverParameterIterator::Delegate {
110public:
111	Iterator(const driver_parameter* parameters, int32 count)
112		: Delegate(),
113		  fParameters(parameters),
114		  fCount(count)
115	{
116	}
117
118	virtual ~Iterator()
119	{
120	}
121
122	virtual Delegate* Clone() const
123	{
124		return new(std::nothrow) Iterator(fParameters, fCount);
125	}
126
127	virtual bool HasNext() const
128	{
129		return (fParameters && fCount > 0);
130	}
131
132	virtual bool GetNext(DriverParameter* parameter)
133	{
134		if (fParameters && fCount > 0) {
135			if (parameter)
136				parameter->SetTo(fParameters);
137			fParameters++;
138			fCount--;
139			return true;
140		}
141		return false;
142	}
143
144private:
145	const driver_parameter*	fParameters;
146	int32					fCount;
147};
148
149// NameIterator
150class DriverParameterContainer::NameIterator
151	: public DriverParameterIterator::Delegate {
152public:
153	NameIterator(const driver_parameter* parameters, int32 count,
154		const char* name)
155		: Delegate(),
156		  fParameters(parameters),
157		  fCount(count),
158		  fName(name)
159	{
160		_FindNext(false);
161	}
162
163	virtual ~NameIterator()
164	{
165	}
166
167	virtual Delegate* Clone() const
168	{
169		return new(std::nothrow) NameIterator(fParameters, fCount,
170			fName.GetString());
171	}
172
173	virtual bool HasNext() const
174	{
175		return (fParameters && fCount > 0);
176	}
177
178	virtual bool GetNext(DriverParameter* parameter)
179	{
180		if (fParameters && fCount > 0) {
181			if (parameter)
182				parameter->SetTo(fParameters);
183			_FindNext(true);
184			return true;
185		}
186		return false;
187	}
188
189private:
190	void _FindNext(bool skipCurrent)
191	{
192		if (!fParameters || fCount < 1)
193			return;
194		if (skipCurrent) {
195			fParameters++;
196			fCount--;
197		}
198		while (fCount > 0 && fName != fParameters->name) {
199			fParameters++;
200			fCount--;
201		}
202	}
203
204private:
205	const driver_parameter*	fParameters;
206	int32					fCount;
207	String					fName;
208};
209
210// constructor
211DriverParameterContainer::DriverParameterContainer()
212{
213}
214
215// destructor
216DriverParameterContainer::~DriverParameterContainer()
217{
218}
219
220// CountParameters
221int32
222DriverParameterContainer::CountParameters() const
223{
224	int32 count;
225	return (GetParametersAndCount(&count) ? count : 0);
226
227}
228
229// GetParameters
230const driver_parameter*
231DriverParameterContainer::GetParameters() const
232{
233	int32 count;
234	return GetParametersAndCount(&count);
235}
236
237// GetParameterAt
238bool
239DriverParameterContainer::GetParameterAt(int32 index,
240	DriverParameter* parameter) const
241{
242	int32 count;
243	if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
244		if (index >= 0 && index < count) {
245			if (parameter)
246				parameter->SetTo(parameters + index);
247			return true;
248		}
249	}
250	return false;
251}
252
253// FindParameter
254bool
255DriverParameterContainer::FindParameter(const char* name,
256	DriverParameter* parameter) const
257{
258	if (!name)
259		return false;
260	int32 count;
261	if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
262		for (int32 i = 0; i < count; i++) {
263			if (strcmp(name, parameters[i].name) == 0) {
264				if (parameter)
265					parameter->SetTo(parameters + i);
266				return true;
267			}
268		}
269	}
270	return false;
271}
272
273// GetParameterIterator
274DriverParameterIterator
275DriverParameterContainer::GetParameterIterator() const
276{
277	int32 count;
278	if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
279		if (Iterator* iterator = new(std::nothrow) Iterator(parameters, count))
280			return DriverParameterIterator(iterator);
281	}
282	return DriverParameterIterator();
283}
284
285// GetParameterIterator
286DriverParameterIterator
287DriverParameterContainer::GetParameterIterator(const char* name) const
288{
289	int32 count;
290	if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
291		NameIterator* iterator = new(std::nothrow) NameIterator(parameters, count,
292			name);
293		if (iterator)
294			return DriverParameterIterator(iterator);
295	}
296	return DriverParameterIterator();
297}
298
299// GetParameterValue
300const char*
301DriverParameterContainer::GetParameterValue(const char* name,
302	const char* unknownValue, const char* noValue) const
303{
304	DriverParameter parameter;
305	if (!FindParameter(name, &parameter))
306		return unknownValue;
307	return parameter.ValueAt(0, noValue);
308}
309
310// GetBoolParameterValue
311bool
312DriverParameterContainer::GetBoolParameterValue(const char* name,
313	bool unknownValue, bool noValue) const
314{
315	DriverParameter parameter;
316	if (!FindParameter(name, &parameter))
317		return unknownValue;
318	return parameter.BoolValueAt(0, noValue);
319}
320
321// GetInt32ParameterValue
322int32
323DriverParameterContainer::GetInt32ParameterValue(const char* name,
324	int32 unknownValue, int32 noValue) const
325{
326	DriverParameter parameter;
327	if (!FindParameter(name, &parameter))
328		return unknownValue;
329	return parameter.Int32ValueAt(0, noValue);
330}
331
332// GetInt64ParameterValue
333int64
334DriverParameterContainer::GetInt64ParameterValue(const char* name,
335	int64 unknownValue, int64 noValue) const
336{
337	DriverParameter parameter;
338	if (!FindParameter(name, &parameter))
339		return unknownValue;
340	return parameter.Int64ValueAt(0, noValue);
341}
342
343
344// #pragma mark -
345// #pragma mark ----- DriverSettings -----
346
347// constructor
348DriverSettings::DriverSettings()
349	: DriverParameterContainer(),
350	  fSettingsHandle(NULL),
351	  fSettings(NULL)
352{
353}
354
355// destructor
356DriverSettings::~DriverSettings()
357{
358	Unset();
359}
360
361// Load
362status_t
363DriverSettings::Load(const char* driverName)
364{
365	Unset();
366	fSettingsHandle = load_driver_settings(driverName);
367	if (!fSettingsHandle)
368		return B_ENTRY_NOT_FOUND;
369	fSettings = get_driver_settings(fSettingsHandle);
370	if (!fSettings) {
371		Unset();
372		return B_ERROR;
373	}
374	return B_OK;
375}
376
377// Unset
378void
379DriverSettings::Unset()
380{
381	if (fSettingsHandle)
382		unload_driver_settings(fSettingsHandle);
383	fSettingsHandle = NULL;
384	fSettings = NULL;
385}
386
387// GetParametersAndCount
388const driver_parameter*
389DriverSettings::GetParametersAndCount(int32* count) const
390{
391	if (!fSettings)
392		return NULL;
393	*count = fSettings->parameter_count;
394	return fSettings->parameters;
395}
396
397
398// #pragma mark -
399// #pragma mark ----- DriverParameter -----
400
401// constructor
402DriverParameter::DriverParameter()
403	: DriverParameterContainer(),
404	  fParameter(NULL)
405{
406}
407
408// destructor
409DriverParameter::~DriverParameter()
410{
411}
412
413// SetTo
414void
415DriverParameter::SetTo(const driver_parameter* parameter)
416{
417	fParameter = parameter;
418}
419
420// GetName
421const char*
422DriverParameter::GetName() const
423{
424	return (fParameter ? fParameter->name : NULL);
425}
426
427// CountValues
428int32
429DriverParameter::CountValues() const
430{
431	return (fParameter ? fParameter->value_count : 0);
432}
433
434// GetValues
435const char* const*
436DriverParameter::GetValues() const
437{
438	return (fParameter ? fParameter->values : 0);
439}
440
441// ValueAt
442const char*
443DriverParameter::ValueAt(int32 index, const char* noValue) const
444{
445	if (!fParameter || index < 0 || index >= fParameter->value_count)
446		return noValue;
447	return fParameter->values[index];
448}
449
450// BoolValueAt
451bool
452DriverParameter::BoolValueAt(int32 index, bool noValue) const
453{
454	const char* value = ValueAt(index, NULL);
455	if (!value)
456		return noValue;
457	for (int32 i = 0; i < kTrueValueStringCount; i++) {
458		if (strcmp(value, kTrueValueStrings[i]) == 0)
459			return true;
460	}
461	return false;
462}
463
464// Int32ValueAt
465int32
466DriverParameter::Int32ValueAt(int32 index, int32 noValue) const
467{
468	const char* value = ValueAt(index, NULL);
469	if (!value)
470		return noValue;
471	return atol(value);
472}
473
474// Int64ValueAt
475int64
476DriverParameter::Int64ValueAt(int32 index, int64 noValue) const
477{
478	const char* value = ValueAt(index, NULL);
479	if (!value)
480		return noValue;
481	return strtoll(value, NULL, 10);
482}
483
484// GetParametersAndCount
485const driver_parameter*
486DriverParameter::GetParametersAndCount(int32* count) const
487{
488	if (!fParameter)
489		return NULL;
490	*count = fParameter->parameter_count;
491	return fParameter->parameters;
492}
493
494