* Rewrote how the dynamic drivers are registered, and made it a bit more
flexible; now, a driver type can result in any number of paths to probe. * Also, the "bus" modules (busses/bus_managers) are now always probed - that's only a temporary solution and should be restricted to certain driver types later. * Added a userland buildable version of KPath. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25383 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -8,10 +8,10 @@ UsePrivateHeaders shared ;
|
|||||||
|
|
||||||
SimpleTest device_manager :
|
SimpleTest device_manager :
|
||||||
device_manager.cpp
|
device_manager.cpp
|
||||||
|
KPath.cpp
|
||||||
|
|
||||||
bus.cpp
|
bus.cpp
|
||||||
driver.cpp
|
driver.cpp
|
||||||
|
|
||||||
: be libkernelland_emu.so
|
: be libkernelland_emu.so
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-2006, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** A simple class wrapping a path. Has a fixed-sized buffer. */
|
||||||
|
|
||||||
|
#include <fs/KPath.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
|
||||||
|
// debugging
|
||||||
|
#define TRACE(x) ;
|
||||||
|
//#define TRACE(x) dprintf x
|
||||||
|
|
||||||
|
|
||||||
|
KPath::KPath(size_t bufferSize)
|
||||||
|
:
|
||||||
|
fBuffer(NULL),
|
||||||
|
fBufferSize(0),
|
||||||
|
fPathLength(0),
|
||||||
|
fLocked(false)
|
||||||
|
{
|
||||||
|
SetTo(NULL, false, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPath::KPath(const char* path, bool normalize, size_t bufferSize)
|
||||||
|
:
|
||||||
|
fBuffer(NULL),
|
||||||
|
fBufferSize(0),
|
||||||
|
fPathLength(0),
|
||||||
|
fLocked(false)
|
||||||
|
{
|
||||||
|
SetTo(path, normalize, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPath::KPath(const KPath& other)
|
||||||
|
:
|
||||||
|
fBuffer(NULL),
|
||||||
|
fBufferSize(0),
|
||||||
|
fPathLength(0),
|
||||||
|
fLocked(false)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPath::~KPath()
|
||||||
|
{
|
||||||
|
free(fBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KPath::SetTo(const char* path, bool normalize, size_t bufferSize)
|
||||||
|
{
|
||||||
|
if (bufferSize == 0)
|
||||||
|
bufferSize = B_PATH_NAME_LENGTH;
|
||||||
|
|
||||||
|
// free the previous buffer, if the buffer size differs
|
||||||
|
if (fBuffer && fBufferSize != bufferSize) {
|
||||||
|
free(fBuffer);
|
||||||
|
fBuffer = NULL;
|
||||||
|
fBufferSize = 0;
|
||||||
|
}
|
||||||
|
fPathLength = 0;
|
||||||
|
fLocked = false;
|
||||||
|
|
||||||
|
// allocate buffer
|
||||||
|
if (!fBuffer)
|
||||||
|
fBuffer = (char*)malloc(bufferSize);
|
||||||
|
if (!fBuffer)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (fBuffer) {
|
||||||
|
fBufferSize = bufferSize;
|
||||||
|
fBuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
return SetPath(path, normalize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KPath::Adopt(KPath& other)
|
||||||
|
{
|
||||||
|
free(fBuffer);
|
||||||
|
|
||||||
|
fBuffer = other.fBuffer;
|
||||||
|
fBufferSize = other.fBufferSize;
|
||||||
|
|
||||||
|
other.fBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KPath::InitCheck() const
|
||||||
|
{
|
||||||
|
return fBuffer ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KPath::SetPath(const char *path, bool normalize)
|
||||||
|
{
|
||||||
|
if (!fBuffer)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
if (normalize) {
|
||||||
|
// normalize path
|
||||||
|
BPath normalizedPath;
|
||||||
|
status_t error = normalizedPath.SetTo(path, NULL, true);
|
||||||
|
if (error != B_OK) {
|
||||||
|
SetPath(NULL);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(fBuffer, normalizedPath.Path(), fBufferSize);
|
||||||
|
fPathLength = strlen(fBuffer);
|
||||||
|
} else {
|
||||||
|
// don't normalize path
|
||||||
|
size_t length = strlen(path);
|
||||||
|
if (length >= fBufferSize)
|
||||||
|
return B_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
memcpy(fBuffer, path, length + 1);
|
||||||
|
fPathLength = length;
|
||||||
|
_ChopTrailingSlashes();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fBuffer[0] = '\0';
|
||||||
|
fPathLength = 0;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
KPath::Path() const
|
||||||
|
{
|
||||||
|
return fBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
KPath::LockBuffer()
|
||||||
|
{
|
||||||
|
if (!fBuffer || fLocked)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fLocked = true;
|
||||||
|
return fBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KPath::UnlockBuffer()
|
||||||
|
{
|
||||||
|
if (!fLocked) {
|
||||||
|
TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fLocked = false;
|
||||||
|
fPathLength = strnlen(fBuffer, fBufferSize);
|
||||||
|
if (fPathLength == fBufferSize) {
|
||||||
|
TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
|
||||||
|
fPathLength--;
|
||||||
|
fBuffer[fPathLength] = '\0';
|
||||||
|
}
|
||||||
|
_ChopTrailingSlashes();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
KPath::Leaf() const
|
||||||
|
{
|
||||||
|
if (!fBuffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// only "/" has trailing slashes -- then we have to return the complete
|
||||||
|
// buffer, as we have to do in case there are no slashes at all
|
||||||
|
if (fPathLength != 1 || fBuffer[0] != '/') {
|
||||||
|
for (int32 i = fPathLength - 1; i >= 0; i--) {
|
||||||
|
if (fBuffer[i] == '/')
|
||||||
|
return fBuffer + i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KPath::ReplaceLeaf(const char *newLeaf)
|
||||||
|
{
|
||||||
|
const char *leaf = Leaf();
|
||||||
|
if (!leaf)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
int32 leafIndex = leaf - fBuffer;
|
||||||
|
// chop off the current leaf (don't replace "/", though)
|
||||||
|
if (leafIndex != 0 || fBuffer[leafIndex - 1]) {
|
||||||
|
fBuffer[leafIndex] = '\0';
|
||||||
|
fPathLength = leafIndex;
|
||||||
|
_ChopTrailingSlashes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a leaf was given, append it
|
||||||
|
if (newLeaf)
|
||||||
|
return Append(newLeaf);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
KPath::RemoveLeaf()
|
||||||
|
{
|
||||||
|
// get the leaf -- bail out, if not initialized or only the "/" is left
|
||||||
|
const char *leaf = Leaf();
|
||||||
|
if (!leaf || leaf == fBuffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// chop off the leaf
|
||||||
|
int32 leafIndex = leaf - fBuffer;
|
||||||
|
fBuffer[leafIndex] = '\0';
|
||||||
|
fPathLength = leafIndex;
|
||||||
|
_ChopTrailingSlashes();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KPath::Append(const char *component, bool isComponent)
|
||||||
|
{
|
||||||
|
// check initialization and parameter
|
||||||
|
if (!fBuffer)
|
||||||
|
return B_NO_INIT;
|
||||||
|
if (!component)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (fPathLength == 0)
|
||||||
|
return SetPath(component);
|
||||||
|
|
||||||
|
// get component length
|
||||||
|
size_t componentLength = strlen(component);
|
||||||
|
if (componentLength < 1)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// if our current path is empty, we just copy the supplied one
|
||||||
|
// compute the result path len
|
||||||
|
bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/'
|
||||||
|
&& component[0] != '/';
|
||||||
|
size_t resultPathLength = fPathLength + componentLength + (insertSlash ? 1 : 0);
|
||||||
|
if (resultPathLength >= fBufferSize)
|
||||||
|
return B_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
// compose the result path
|
||||||
|
if (insertSlash)
|
||||||
|
fBuffer[fPathLength++] = '/';
|
||||||
|
memcpy(fBuffer + fPathLength, component, componentLength + 1);
|
||||||
|
fPathLength = resultPathLength;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPath&
|
||||||
|
KPath::operator=(const KPath& other)
|
||||||
|
{
|
||||||
|
SetTo(other.fBuffer, other.fBufferSize);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KPath&
|
||||||
|
KPath::operator=(const char* path)
|
||||||
|
{
|
||||||
|
SetTo(path);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
KPath::operator==(const KPath& other) const
|
||||||
|
{
|
||||||
|
if (!fBuffer)
|
||||||
|
return !other.fBuffer;
|
||||||
|
|
||||||
|
return (other.fBuffer
|
||||||
|
&& fPathLength == other.fPathLength
|
||||||
|
&& strcmp(fBuffer, other.fBuffer) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
KPath::operator==(const char* path) const
|
||||||
|
{
|
||||||
|
if (!fBuffer)
|
||||||
|
return (!path);
|
||||||
|
|
||||||
|
return path && !strcmp(fBuffer, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
KPath::operator!=(const KPath& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
KPath::operator!=(const char* path) const
|
||||||
|
{
|
||||||
|
return !(*this == path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KPath::_ChopTrailingSlashes()
|
||||||
|
{
|
||||||
|
if (fBuffer) {
|
||||||
|
while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/')
|
||||||
|
fBuffer[--fPathLength] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,19 +6,21 @@
|
|||||||
|
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
|
|
||||||
#include <util/AutoLock.h>
|
|
||||||
#include <util/DoublyLinkedList.h>
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
|
||||||
#include <module.h>
|
|
||||||
#include <Locker.h>
|
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <module.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
|
||||||
|
#include <fs/KPath.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/Stack.h>
|
||||||
|
|
||||||
|
|
||||||
#define TRACE(a) dprintf a
|
#define TRACE(a) dprintf a
|
||||||
|
|
||||||
@@ -107,6 +109,13 @@ struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _RegisterFixed(uint32& registered);
|
status_t _RegisterFixed(uint32& registered);
|
||||||
|
status_t _GetNextDriverPath(void*& cookie, KPath& _path);
|
||||||
|
status_t _GetNextDriver(void* list,
|
||||||
|
driver_module_info*& driver);
|
||||||
|
status_t _FindBestDriver(const char* path,
|
||||||
|
driver_module_info*& bestDriver,
|
||||||
|
float& bestSupport);
|
||||||
|
status_t _RegisterPath(const char* path);
|
||||||
status_t _RegisterDynamic();
|
status_t _RegisterDynamic();
|
||||||
bool _IsBus() const;
|
bool _IsBus() const;
|
||||||
|
|
||||||
@@ -123,12 +132,14 @@ private:
|
|||||||
AttributeList fAttributes;
|
AttributeList fAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
device_manager_info *gDeviceManager;
|
device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
static device_node *sRootNode;
|
static device_node *sRootNode;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - device_attr
|
||||||
|
|
||||||
|
|
||||||
device_attr_private::device_attr_private()
|
device_attr_private::device_attr_private()
|
||||||
{
|
{
|
||||||
name = NULL;
|
name = NULL;
|
||||||
@@ -355,7 +366,7 @@ dm_dump_node(device_node* node, int32 level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - device_node
|
||||||
|
|
||||||
|
|
||||||
/*! Allocate device node info structure;
|
/*! Allocate device node info structure;
|
||||||
@@ -550,6 +561,150 @@ device_node::_RegisterFixed(uint32& registered)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
|
||||||
|
{
|
||||||
|
Stack<KPath*>* stack = NULL;
|
||||||
|
|
||||||
|
if (cookie == NULL) {
|
||||||
|
// find all paths and add them
|
||||||
|
stack = new(std::nothrow) Stack<KPath*>();
|
||||||
|
if (stack == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
StackDeleter<KPath*> stackDeleter(stack);
|
||||||
|
|
||||||
|
if (!_IsBus()) {
|
||||||
|
// add driver paths
|
||||||
|
KPath* path = new(std::nothrow) KPath;
|
||||||
|
if (path == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t status = path->SetTo("drivers");
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete path;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this might be more than one path!
|
||||||
|
const char *type;
|
||||||
|
if (dm_get_attr_string(this, B_DRIVER_DEVICE_TYPE, &type, false)
|
||||||
|
== B_OK)
|
||||||
|
path->Append(type);
|
||||||
|
|
||||||
|
stack->Push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add bus paths
|
||||||
|
KPath* path = new(std::nothrow) KPath;
|
||||||
|
if (path == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t status = path->SetTo("bus");
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete path;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->Push(path);
|
||||||
|
stackDeleter.Detach();
|
||||||
|
|
||||||
|
cookie = (void*)stack;
|
||||||
|
} else
|
||||||
|
stack = static_cast<Stack<KPath*>*>(cookie);
|
||||||
|
|
||||||
|
KPath* path;
|
||||||
|
if (stack->Pop(&path)) {
|
||||||
|
_path.Adopt(*path);
|
||||||
|
delete path;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete stack;
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::_GetNextDriver(void* list, driver_module_info*& driver)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
char name[B_FILE_NAME_LENGTH];
|
||||||
|
size_t nameLength = sizeof(name);
|
||||||
|
|
||||||
|
status_t status = read_next_module_name(list, name, &nameLength);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!strcmp(fModuleName, name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (get_module(name, (module_info**)&driver) != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (driver->supports_device == NULL
|
||||||
|
|| driver->register_device == NULL) {
|
||||||
|
put_module(name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::_FindBestDriver(const char* path, driver_module_info*& bestDriver,
|
||||||
|
float& bestSupport)
|
||||||
|
{
|
||||||
|
if (bestDriver == NULL)
|
||||||
|
bestSupport = 0.0f;
|
||||||
|
|
||||||
|
void* list = open_module_list_etc(path, "driver_v1");
|
||||||
|
driver_module_info* driver;
|
||||||
|
while (_GetNextDriver(list, driver) == B_OK) {
|
||||||
|
float support = driver->supports_device(this);
|
||||||
|
if (support > bestSupport) {
|
||||||
|
if (bestDriver != NULL)
|
||||||
|
put_module(bestDriver->info.name);
|
||||||
|
|
||||||
|
bestDriver = driver;
|
||||||
|
bestSupport = support;
|
||||||
|
continue;
|
||||||
|
// keep reference to best module around
|
||||||
|
}
|
||||||
|
|
||||||
|
put_module(driver->info.name);
|
||||||
|
}
|
||||||
|
close_module_list(list);
|
||||||
|
|
||||||
|
return bestDriver != NULL ? B_OK : B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::_RegisterPath(const char* path)
|
||||||
|
{
|
||||||
|
void* list = open_module_list_etc(path, "driver_v1");
|
||||||
|
driver_module_info* driver;
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
while (_GetNextDriver(list, driver) == B_OK) {
|
||||||
|
float support = driver->supports_device(this);
|
||||||
|
if (support > 0.0) {
|
||||||
|
printf(" register module \"%s\", support %f\n", driver->info.name, support);
|
||||||
|
if (driver->register_device(this) == B_OK)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_module(driver->info.name);
|
||||||
|
}
|
||||||
|
close_module_list(list);
|
||||||
|
|
||||||
|
return count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
device_node::_RegisterDynamic()
|
device_node::_RegisterDynamic()
|
||||||
{
|
{
|
||||||
@@ -558,69 +713,30 @@ device_node::_RegisterDynamic()
|
|||||||
!= B_OK)
|
!= B_OK)
|
||||||
findFlags = 0;
|
findFlags = 0;
|
||||||
|
|
||||||
driver_module_info* bestDriver = NULL;
|
KPath path;
|
||||||
float best = 0.0;
|
|
||||||
|
|
||||||
char path[64];
|
|
||||||
if (!_IsBus()) {
|
|
||||||
strlcpy(path, "drivers", sizeof(path));
|
|
||||||
|
|
||||||
const char *type;
|
|
||||||
if (dm_get_attr_string(this, B_DRIVER_DEVICE_TYPE, &type, false)
|
|
||||||
== B_OK) {
|
|
||||||
strlcat(path, "/", sizeof(path));
|
|
||||||
strlcat(path, type, sizeof(path));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO: we might want to allow bus* specifiers as well, ie.
|
|
||||||
// busses/usb
|
|
||||||
strlcpy(path, "bus", sizeof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
void* list = open_module_list_etc(path, "driver_v1");
|
|
||||||
while (true) {
|
|
||||||
char name[B_FILE_NAME_LENGTH];
|
|
||||||
size_t nameLength = sizeof(name);
|
|
||||||
|
|
||||||
if (read_next_module_name(list, name, &nameLength) != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!strcmp(fModuleName, name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
driver_module_info* driver;
|
|
||||||
if (get_module(name, (module_info**)&driver) != B_OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (driver->supports_device != NULL
|
|
||||||
&& driver->register_device != NULL) {
|
|
||||||
float support = driver->supports_device(this);
|
|
||||||
|
|
||||||
if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
|
if ((findFlags & B_FIND_MULTIPLE_CHILDREN) == 0) {
|
||||||
if (support > best) {
|
// find the one driver
|
||||||
if (bestDriver != NULL)
|
driver_module_info* bestDriver = NULL;
|
||||||
put_module(bestDriver->info.name);
|
float bestSupport = 0.0;
|
||||||
|
void* cookie = NULL;
|
||||||
|
|
||||||
bestDriver = driver;
|
while (_GetNextDriverPath(cookie, path) == B_OK) {
|
||||||
best = support;
|
_FindBestDriver(path.Path(), bestDriver, bestSupport);
|
||||||
continue;
|
|
||||||
// keep reference to best module around
|
|
||||||
}
|
}
|
||||||
} else if (support > 0.0) {
|
|
||||||
printf(" register module \"%s\", support %f\n", name, support);
|
|
||||||
driver->register_device(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
put_module(name);
|
|
||||||
}
|
|
||||||
close_module_list(list);
|
|
||||||
|
|
||||||
if (bestDriver != NULL) {
|
if (bestDriver != NULL) {
|
||||||
printf(" register best module \"%s\", support %f\n", bestDriver->info.name, best);
|
printf(" register best module \"%s\", support %f\n", bestDriver->info.name, bestSupport);
|
||||||
bestDriver->register_device(this);
|
bestDriver->register_device(this);
|
||||||
put_module(bestDriver->info.name);
|
put_module(bestDriver->info.name);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// register all drivers that match
|
||||||
|
void* cookie = NULL;
|
||||||
|
while (_GetNextDriverPath(cookie, path) == B_OK) {
|
||||||
|
_RegisterPath(path.Path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user