* Started playground for the new device manager. This will eventually evolve
into the full thing, and will then be adapted to the kernel. * Doesn't do a lot at this point - it can be built as a test app under BeOS and Haiku. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24973 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6fd31accd3
commit
2d8e02e435
@ -9,3 +9,4 @@ KernelAddon <test_driver>config :
|
|||||||
config.c
|
config.c
|
||||||
;
|
;
|
||||||
|
|
||||||
|
SubInclude HAIKU_TOP src tests system kernel device_manager playground ;
|
||||||
|
17
src/tests/system/kernel/device_manager/playground/Jamfile
Normal file
17
src/tests/system/kernel/device_manager/playground/Jamfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
SubDir HAIKU_TOP src tests system kernel device_manager playground ;
|
||||||
|
|
||||||
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(HAIKU_TOP) src tests add-ons kernel file_systems fs_shell ] ;
|
||||||
|
UseHeaders $(HAIKU_PRIVATE_KERNEL_HEADERS) : true ;
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
|
SimpleTest device_manager :
|
||||||
|
device_manager.cpp
|
||||||
|
|
||||||
|
bus.cpp
|
||||||
|
driver.cpp
|
||||||
|
|
||||||
|
: be libkernelland_emu.so
|
||||||
|
;
|
||||||
|
|
141
src/tests/system/kernel/device_manager/playground/bus.cpp
Normal file
141
src/tests/system/kernel/device_manager/playground/bus.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BUS_MODULE_NAME "bus_managers/sample_bus/driver_v1"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - bus
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
supports_device(device_node *parent)
|
||||||
|
{
|
||||||
|
const char* bus;
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false)
|
||||||
|
!= B_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (bus != NULL && !strcmp(bus, "root"))
|
||||||
|
return 1.0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node *parent)
|
||||||
|
{
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{B_DRIVER_PRETTY_NAME, B_STRING_TYPE, {string: "My Bus"}},
|
||||||
|
{B_DRIVER_BUS, B_STRING_TYPE, {string: BUS_NAME}},
|
||||||
|
{B_DRIVER_IS_BUS, B_INT8_TYPE, {ui8: true}},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_device(parent, BUS_MODULE_NAME, attrs, NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_driver(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_driver(device_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_child_devices(device_node *node)
|
||||||
|
{
|
||||||
|
const struct device_info {
|
||||||
|
uint16 vendor;
|
||||||
|
uint16 device;
|
||||||
|
const char *type;
|
||||||
|
} kDevices[] = {
|
||||||
|
{0x1000, 0x0001, B_DISK_DRIVER_TYPE},
|
||||||
|
{0x1001, 0x0001, B_NETWORK_DRIVER_TYPE},
|
||||||
|
{0x1002, 0x0001, B_AUDIO_DRIVER_TYPE},
|
||||||
|
{0x1002, 0x0002, B_BUS_DRIVER_TYPE},
|
||||||
|
};
|
||||||
|
const size_t kNumDevices = sizeof(kDevices) / sizeof(kDevices[0]);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < kNumDevices; i++) {
|
||||||
|
device_attr attrs[] = {
|
||||||
|
// info about the device
|
||||||
|
{ "bus/vendor", B_UINT16_TYPE, { ui16: kDevices[i].vendor }},
|
||||||
|
{ "bus/device", B_UINT16_TYPE, { ui16: kDevices[i].device }},
|
||||||
|
|
||||||
|
{ B_DRIVER_BUS, B_STRING_TYPE, { string: "pci" }},
|
||||||
|
{ B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: kDevices[i].type}},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
gDeviceManager->register_device(node, BUS_DEVICE_NAME, attrs, NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
rescan_child_devices(device_node *node)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
device_removed(device_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
struct driver_module_info gBusModuleInfo = {
|
||||||
|
{
|
||||||
|
BUS_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
supports_device,
|
||||||
|
register_device,
|
||||||
|
|
||||||
|
init_driver,
|
||||||
|
uninit_driver,
|
||||||
|
register_child_devices,
|
||||||
|
rescan_child_devices,
|
||||||
|
device_removed,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct driver_module_info gBusDriverModuleInfo = {
|
||||||
|
{
|
||||||
|
BUS_DEVICE_NAME,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
26
src/tests/system/kernel/device_manager/playground/bus.h
Normal file
26
src/tests/system/kernel/device_manager/playground/bus.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef BUS_H
|
||||||
|
#define BUS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "device_manager.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct bus_info {
|
||||||
|
uint16 vendor_id;
|
||||||
|
uint16 device_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bus_device_module_info {
|
||||||
|
driver_module_info info;
|
||||||
|
|
||||||
|
status_t (*get_bus_info)(void* cookie, bus_info* info);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BUS_DEVICE_NAME "bus_managers/sample_bus/device/driver_v1"
|
||||||
|
#define BUS_NAME "mybus"
|
||||||
|
|
||||||
|
#endif // BUS_H
|
@ -0,0 +1,851 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "device_manager.h"
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <module.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <set>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE(a) dprintf a
|
||||||
|
|
||||||
|
#define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
|
||||||
|
|
||||||
|
extern struct device_module_info gDeviceModuleInfo;
|
||||||
|
extern struct driver_module_info gDriverModuleInfo;
|
||||||
|
extern struct driver_module_info gBusModuleInfo;
|
||||||
|
extern struct driver_module_info gBusDriverModuleInfo;
|
||||||
|
|
||||||
|
extern "C" status_t _add_builtin_module(module_info *info);
|
||||||
|
extern "C" status_t _get_builtin_dependencies(void);
|
||||||
|
extern bool gDebugOutputEnabled;
|
||||||
|
// from libkernelland_emu.so
|
||||||
|
|
||||||
|
status_t dm_get_attr_uint32(device_node* node, const char* name, uint32* _value,
|
||||||
|
bool recursive);
|
||||||
|
|
||||||
|
device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
|
struct device_attr_private : device_attr,
|
||||||
|
DoublyLinkedListLinkImpl<device_attr_private> {
|
||||||
|
device_attr_private();
|
||||||
|
device_attr_private(const device_attr& attr);
|
||||||
|
~device_attr_private();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
status_t CopyFrom(const device_attr& attr);
|
||||||
|
|
||||||
|
static int Compare(const device_attr* attrA,
|
||||||
|
const device_attr *attrB);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Unset();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<device_attr_private> AttributeList;
|
||||||
|
|
||||||
|
|
||||||
|
// I/O resource
|
||||||
|
typedef struct io_resource_info {
|
||||||
|
struct io_resource_info *prev, *next;
|
||||||
|
device_node* owner; // associated node; NULL for temporary allocation
|
||||||
|
io_resource resource; // info about actual resource
|
||||||
|
} io_resource_info;
|
||||||
|
|
||||||
|
|
||||||
|
// a structure to put nodes into lists
|
||||||
|
struct node_entry {
|
||||||
|
struct list_link link;
|
||||||
|
device_node* node;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<device_node> NodeList;
|
||||||
|
|
||||||
|
struct device_node : DoublyLinkedListLinkImpl<device_node> {
|
||||||
|
device_node(const char *moduleName,
|
||||||
|
const device_attr *attrs,
|
||||||
|
const io_resource *resources);
|
||||||
|
~device_node();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
|
||||||
|
const char* ModuleName() const { return fModuleName; }
|
||||||
|
device_node* Parent() const { return fParent; }
|
||||||
|
AttributeList& Attributes() { return fAttributes; }
|
||||||
|
|
||||||
|
status_t InitDriver();
|
||||||
|
void UninitDriver();
|
||||||
|
|
||||||
|
// The following two are only valid, if the node's driver is
|
||||||
|
// initialized
|
||||||
|
driver_module_info* DriverModule() const { return fDriver; }
|
||||||
|
void* DriverData() const { return fDriverData; }
|
||||||
|
|
||||||
|
void AddChild(device_node *node);
|
||||||
|
|
||||||
|
status_t Register();
|
||||||
|
bool IsRegistered() const { return fRegistered; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _RegisterFixed(uint32& registered);
|
||||||
|
status_t _RegisterDynamic();
|
||||||
|
|
||||||
|
device_node* fParent;
|
||||||
|
NodeList fChildren;
|
||||||
|
int32 fRefCount;
|
||||||
|
int32 fInitialized;
|
||||||
|
bool fRegistered;
|
||||||
|
|
||||||
|
const char* fModuleName;
|
||||||
|
driver_module_info* fDriver;
|
||||||
|
void* fDriverData;
|
||||||
|
|
||||||
|
AttributeList fAttributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static device_node *sRootNode;
|
||||||
|
|
||||||
|
|
||||||
|
device_attr_private::device_attr_private()
|
||||||
|
{
|
||||||
|
name = NULL;
|
||||||
|
type = 0;
|
||||||
|
value.raw.data = NULL;
|
||||||
|
value.raw.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_attr_private::device_attr_private(const device_attr& attr)
|
||||||
|
{
|
||||||
|
CopyFrom(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_attr_private::~device_attr_private()
|
||||||
|
{
|
||||||
|
_Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_attr_private::InitCheck()
|
||||||
|
{
|
||||||
|
return name != NULL ? B_OK : B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_attr_private::CopyFrom(const device_attr& attr)
|
||||||
|
{
|
||||||
|
name = strdup(attr.name);
|
||||||
|
if (name == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
type = attr.type;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case B_UINT8_TYPE:
|
||||||
|
case B_UINT16_TYPE:
|
||||||
|
case B_UINT32_TYPE:
|
||||||
|
case B_UINT64_TYPE:
|
||||||
|
value.ui64 = attr.value.ui64;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_STRING_TYPE:
|
||||||
|
if (attr.value.string != NULL) {
|
||||||
|
value.string = strdup(attr.value.string);
|
||||||
|
if (value.string == NULL) {
|
||||||
|
_Unset();
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
value.string = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_RAW_TYPE:
|
||||||
|
value.raw.data = malloc(attr.value.raw.length);
|
||||||
|
if (value.raw.data == NULL) {
|
||||||
|
_Unset();
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.raw.length = attr.value.raw.length;
|
||||||
|
memcpy((void*)value.raw.data, attr.value.raw.data,
|
||||||
|
attr.value.raw.length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
device_attr_private::_Unset()
|
||||||
|
{
|
||||||
|
if (type == B_STRING_TYPE)
|
||||||
|
free((char*)value.string);
|
||||||
|
else if (type == B_RAW_TYPE)
|
||||||
|
free((void*)value.raw.data);
|
||||||
|
|
||||||
|
free((char*)name);
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
value.raw.data = NULL;
|
||||||
|
value.raw.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ int
|
||||||
|
device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
|
||||||
|
{
|
||||||
|
if (attrA->type != attrB->type)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (attrA->type) {
|
||||||
|
case B_UINT8_TYPE:
|
||||||
|
return (int)attrA->value.ui8 - (int)attrB->value.ui8;
|
||||||
|
|
||||||
|
case B_UINT16_TYPE:
|
||||||
|
return (int)attrA->value.ui16 - (int)attrB->value.ui16;
|
||||||
|
|
||||||
|
case B_UINT32_TYPE:
|
||||||
|
if (attrA->value.ui32 > attrB->value.ui32)
|
||||||
|
return 1;
|
||||||
|
if (attrA->value.ui32 < attrB->value.ui32)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case B_UINT64_TYPE:
|
||||||
|
if (attrA->value.ui64 > attrB->value.ui64)
|
||||||
|
return 1;
|
||||||
|
if (attrA->value.ui64 < attrB->value.ui64)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case B_STRING_TYPE:
|
||||||
|
return strcmp(attrA->value.string, attrB->value.string);
|
||||||
|
|
||||||
|
case B_RAW_TYPE:
|
||||||
|
if (attrA->value.raw.length != attrB->value.raw.length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return memcmp(attrA->value.raw.data, attrB->value.raw.data,
|
||||||
|
attrA->value.raw.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
device_attr_private*
|
||||||
|
dm_find_attr(device_node* node, const char* name, bool recursive,
|
||||||
|
type_code type)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
AttributeList::Iterator iterator = node->Attributes().GetIterator();
|
||||||
|
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
device_attr_private* attr = iterator.Next();
|
||||||
|
|
||||||
|
if (type != B_ANY_TYPE && attr->type != type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strcmp(attr->name, name))
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->Parent();
|
||||||
|
} while (node != NULL && recursive);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
/*! Allocate device node info structure;
|
||||||
|
initially, ref_count is one to make sure node won't get destroyed by mistake
|
||||||
|
*/
|
||||||
|
device_node::device_node(const char *moduleName, const device_attr *attrs,
|
||||||
|
const io_resource *resources)
|
||||||
|
{
|
||||||
|
fModuleName = strdup(moduleName);
|
||||||
|
if (fModuleName == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fParent = NULL;
|
||||||
|
fRefCount = 1;
|
||||||
|
fInitialized = 0;
|
||||||
|
fRegistered = false;
|
||||||
|
fDriver = NULL;
|
||||||
|
fDriverData = NULL;
|
||||||
|
|
||||||
|
// copy attributes
|
||||||
|
|
||||||
|
while (attrs != NULL && attrs->name != NULL) {
|
||||||
|
device_attr_private* attr
|
||||||
|
= new(std::nothrow) device_attr_private(*attrs);
|
||||||
|
if (attr == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fAttributes.Add(attr);
|
||||||
|
attrs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_node::~device_node()
|
||||||
|
{
|
||||||
|
AttributeList::Iterator iterator = fAttributes.GetIterator();
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
device_attr_private* attr = iterator.Next();
|
||||||
|
iterator.Remove();
|
||||||
|
delete attr;
|
||||||
|
}
|
||||||
|
free((char*)fModuleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::InitCheck()
|
||||||
|
{
|
||||||
|
return fModuleName != NULL ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::InitDriver()
|
||||||
|
{
|
||||||
|
if (fInitialized++ > 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
status_t status = get_module(ModuleName(), (module_info**)&fDriver);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fInitialized--;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fDriver->init_driver != NULL)
|
||||||
|
status = fDriver->init_driver(this, &fDriverData);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fInitialized--;
|
||||||
|
put_module(ModuleName());
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
device_node::UninitDriver()
|
||||||
|
{
|
||||||
|
if (fInitialized-- > 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fDriver->uninit_driver != NULL)
|
||||||
|
fDriver->uninit_driver(this);
|
||||||
|
fDriverData = NULL;
|
||||||
|
|
||||||
|
put_module(ModuleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
device_node::AddChild(device_node *node)
|
||||||
|
{
|
||||||
|
// we must not be destroyed as long as we have children
|
||||||
|
fRefCount++;
|
||||||
|
node->fParent = this;
|
||||||
|
fChildren.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::Register()
|
||||||
|
{
|
||||||
|
uint32 registered;
|
||||||
|
status_t status = _RegisterFixed(registered);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
if (registered > 0) {
|
||||||
|
fRegistered = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the children the driver wants
|
||||||
|
|
||||||
|
if (DriverModule()->register_child_devices != NULL)
|
||||||
|
DriverModule()->register_child_devices(this);
|
||||||
|
|
||||||
|
// Register all possible child device nodes
|
||||||
|
|
||||||
|
uint32 findFlags;
|
||||||
|
if (dm_get_attr_uint32(this, B_DRIVER_FIND_CHILD_FLAGS, &findFlags, false) != B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ((findFlags & B_FIND_CHILD_ON_DEMAND) != 0)
|
||||||
|
return B_OK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _RegisterDynamic();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Registers any children that are identified via the B_DRIVER_FIXED_CHILD
|
||||||
|
attribute.
|
||||||
|
If any of these children cannot be registered, this call will fail (we
|
||||||
|
don't remove already registered children in this case).
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
device_node::_RegisterFixed(uint32& registered)
|
||||||
|
{
|
||||||
|
AttributeList::Iterator iterator = fAttributes.GetIterator();
|
||||||
|
registered = 0;
|
||||||
|
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
device_attr_private* attr = iterator.Next();
|
||||||
|
if (strcmp(attr->name, B_DRIVER_FIXED_CHILD))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
driver_module_info* driver;
|
||||||
|
status_t status = get_module(attr->value.string,
|
||||||
|
(module_info**)&driver);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (driver->supports_device != NULL
|
||||||
|
&& driver->register_device != NULL) {
|
||||||
|
float support = driver->supports_device(this);
|
||||||
|
if (support <= 0.0)
|
||||||
|
status = B_ERROR;
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = driver->register_device(this);
|
||||||
|
if (status == B_OK)
|
||||||
|
registered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_module(attr->value.string);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
device_node::_RegisterDynamic()
|
||||||
|
{
|
||||||
|
uint32 findFlags;
|
||||||
|
if (dm_get_attr_uint32(this, B_DRIVER_FIND_CHILD_FLAGS, &findFlags, false)
|
||||||
|
!= B_OK)
|
||||||
|
findFlags = 0;
|
||||||
|
|
||||||
|
driver_module_info* bestDriver = NULL;
|
||||||
|
float best = 0.0;
|
||||||
|
|
||||||
|
void* list = open_module_list_etc("bus", "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 (support > best) {
|
||||||
|
if (bestDriver != NULL)
|
||||||
|
put_module(bestDriver->info.name);
|
||||||
|
|
||||||
|
bestDriver = driver;
|
||||||
|
best = support;
|
||||||
|
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) {
|
||||||
|
printf(" register best module \"%s\", support %f\n", bestDriver->info.name, best);
|
||||||
|
bestDriver->register_device(this);
|
||||||
|
put_module(bestDriver->info.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Device Manager module API
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
rescan_device(device_node *node)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node *parent, const char *moduleName,
|
||||||
|
const device_attr *attrs, const io_resource *ioResources,
|
||||||
|
device_node **_node)
|
||||||
|
{
|
||||||
|
if ((parent == NULL && sRootNode != NULL) || moduleName == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
TRACE(("register device \"%s\", parent %p\n", moduleName, parent));
|
||||||
|
// TODO: handle I/O resources!
|
||||||
|
|
||||||
|
device_node *newNode = new(std::nothrow) device_node(moduleName, attrs,
|
||||||
|
ioResources);
|
||||||
|
if (newNode == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t status = newNode->InitCheck();
|
||||||
|
if (status != B_OK)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
status = newNode->InitDriver();
|
||||||
|
if (status != B_OK)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
// make it public
|
||||||
|
if (parent != NULL)
|
||||||
|
parent->AddChild(newNode);
|
||||||
|
else
|
||||||
|
sRootNode = newNode;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// The following is done to reduce the stack usage of deeply nested
|
||||||
|
// child device nodes.
|
||||||
|
// There is no other need to delay the complete registration process
|
||||||
|
// the way done here. This approach is also slightly different as
|
||||||
|
// the registration might fail later than it used in case of errors.
|
||||||
|
|
||||||
|
if (!parent->IsRegistered()) {
|
||||||
|
// The parent has not been registered completely yet - child
|
||||||
|
// registration is deferred to the parent registration
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
status = newNode->Register();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (_node)
|
||||||
|
*_node = newNode;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err1:
|
||||||
|
delete newNode;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
unregister_device(device_node *node)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static driver_module_info*
|
||||||
|
driver_module(device_node *node)
|
||||||
|
{
|
||||||
|
return node->DriverModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void*
|
||||||
|
driver_data(device_node *node)
|
||||||
|
{
|
||||||
|
return node->DriverData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static device_node *
|
||||||
|
device_root(void)
|
||||||
|
{
|
||||||
|
return sRootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
get_next_child_device(device_node *parent, device_node *_node,
|
||||||
|
const device_attr *attrs)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static device_node *
|
||||||
|
get_parent(device_node *node)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
put_device_node(device_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_uint8(device_node* node, const char* name, uint8* _value,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || _value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive,
|
||||||
|
B_UINT8_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
*_value = attr->value.ui8;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_uint16(device_node* node, const char* name, uint16* _value,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || _value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive,
|
||||||
|
B_UINT16_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
*_value = attr->value.ui16;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_uint32(device_node* node, const char* name, uint32* _value,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || _value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive,
|
||||||
|
B_UINT32_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
*_value = attr->value.ui32;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_uint64(device_node* node, const char* name,
|
||||||
|
uint64* _value, bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || _value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive,
|
||||||
|
B_UINT64_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
*_value = attr->value.ui64;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_string(device_node* node, const char* name, const char** _value,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || _value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive,
|
||||||
|
B_STRING_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
*_value = attr->value.string;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_attr_raw(device_node* node, const char* name, const void** _data,
|
||||||
|
size_t* _length, bool recursive)
|
||||||
|
{
|
||||||
|
if (name == NULL || (_data == NULL && _length == NULL))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device_attr_private* attr = dm_find_attr(node, name, recursive, B_RAW_TYPE);
|
||||||
|
if (attr == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
if (_data != NULL)
|
||||||
|
*_data = attr->value.raw.data;
|
||||||
|
if (_length != NULL)
|
||||||
|
*_length = attr->value.raw.length;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dm_get_next_attr(device_node* node, device_attr** _attr)
|
||||||
|
{
|
||||||
|
device_attr_private* next;
|
||||||
|
device_attr_private* attr = *(device_attr_private**)_attr;
|
||||||
|
|
||||||
|
if (attr != NULL) {
|
||||||
|
// next attribute
|
||||||
|
next = attr->GetDoublyLinkedListLink()->next;
|
||||||
|
} else {
|
||||||
|
// first attribute
|
||||||
|
next = node->Attributes().First();
|
||||||
|
}
|
||||||
|
|
||||||
|
*_attr = next;
|
||||||
|
|
||||||
|
return next ? B_OK : B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct device_manager_info sDeviceManagerModule = {
|
||||||
|
{
|
||||||
|
B_DEVICE_MANAGER_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
|
||||||
|
// device nodes
|
||||||
|
rescan_device,
|
||||||
|
register_device,
|
||||||
|
unregister_device,
|
||||||
|
driver_module,
|
||||||
|
driver_data,
|
||||||
|
device_root,
|
||||||
|
get_next_child_device,
|
||||||
|
get_parent,
|
||||||
|
put_device_node,
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
dm_get_attr_uint8,
|
||||||
|
dm_get_attr_uint16,
|
||||||
|
dm_get_attr_uint32,
|
||||||
|
dm_get_attr_uint64,
|
||||||
|
dm_get_attr_string,
|
||||||
|
dm_get_attr_raw,
|
||||||
|
dm_get_next_attr,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - root node
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
dm_init_root_node(void)
|
||||||
|
{
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{B_DRIVER_PRETTY_NAME, B_STRING_TYPE, {string: "Devices Root"}},
|
||||||
|
{B_DRIVER_BUS, B_STRING_TYPE, {string: "root"}},
|
||||||
|
{B_DRIVER_FIND_CHILD_FLAGS, B_UINT32_TYPE,
|
||||||
|
{ui32: B_FIND_MULTIPLE_CHILDREN}},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (register_device(NULL, DEVICE_MANAGER_ROOT_NAME, attrs, NULL, NULL)
|
||||||
|
!= B_OK) {
|
||||||
|
dprintf("Cannot register Devices Root Node\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static driver_module_info sDeviceRootModule = {
|
||||||
|
{
|
||||||
|
DEVICE_MANAGER_ROOT_NAME,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
_add_builtin_module((module_info *)&sDeviceManagerModule);
|
||||||
|
_add_builtin_module((module_info *)&sDeviceRootModule);
|
||||||
|
_add_builtin_module((module_info *)&gDeviceModuleInfo);
|
||||||
|
_add_builtin_module((module_info *)&gDriverModuleInfo);
|
||||||
|
_add_builtin_module((module_info *)&gBusModuleInfo);
|
||||||
|
_add_builtin_module((module_info *)&gBusDriverModuleInfo);
|
||||||
|
|
||||||
|
gDeviceManager = &sDeviceManagerModule;
|
||||||
|
|
||||||
|
status_t status = _get_builtin_dependencies();
|
||||||
|
if (status < B_OK) {
|
||||||
|
fprintf(stderr, "device_manager: Could not initialize modules: %s\n",
|
||||||
|
strerror(status));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_init_root_node();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-2008, Haiku Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef _DEVICE_MANAGER_H
|
||||||
|
#define _DEVICE_MANAGER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <module.h>
|
||||||
|
|
||||||
|
|
||||||
|
// type of I/O resource
|
||||||
|
enum {
|
||||||
|
IO_MEM = 1,
|
||||||
|
IO_PORT = 2,
|
||||||
|
ISA_DMA_CHANNEL = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// I/O resource description
|
||||||
|
typedef struct {
|
||||||
|
uint32 type;
|
||||||
|
// type of I/O resource
|
||||||
|
|
||||||
|
uint32 base;
|
||||||
|
// I/O memory: first physical address (32 bit)
|
||||||
|
// I/O port: first port address (16 bit)
|
||||||
|
// ISA DMA channel: channel number (0-7)
|
||||||
|
|
||||||
|
uint32 length;
|
||||||
|
// I/O memory: size of address range (32 bit)
|
||||||
|
// I/O port: size of port range (16 bit)
|
||||||
|
// ISA DMA channel: must be 1
|
||||||
|
} io_resource;
|
||||||
|
|
||||||
|
// attribute of a device node
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
type_code type; // for supported types, see value
|
||||||
|
union {
|
||||||
|
uint8 ui8; // B_UINT8_TYPE
|
||||||
|
uint16 ui16; // B_UINT16_TYPE
|
||||||
|
uint32 ui32; // B_UINT32_TYPE
|
||||||
|
uint64 ui64; // B_UINT64_TYPE
|
||||||
|
const char *string; // B_STRING_TYPE
|
||||||
|
struct { // B_RAW_TYPE
|
||||||
|
const void *data;
|
||||||
|
size_t length;
|
||||||
|
} raw;
|
||||||
|
} value;
|
||||||
|
} device_attr;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct device_node device_node;
|
||||||
|
typedef struct driver_module_info driver_module_info;
|
||||||
|
|
||||||
|
|
||||||
|
// interface of the device manager
|
||||||
|
|
||||||
|
typedef struct device_manager_info {
|
||||||
|
module_info info;
|
||||||
|
|
||||||
|
status_t (*rescan)(device_node *node);
|
||||||
|
|
||||||
|
status_t (*register_device)(device_node *parent, const char *moduleName,
|
||||||
|
const device_attr *attrs, const io_resource *ioResources,
|
||||||
|
device_node **_node);
|
||||||
|
status_t (*unregister_device)(device_node *node);
|
||||||
|
|
||||||
|
driver_module_info *(*driver_module)(device_node *node);
|
||||||
|
void *(*driver_data)(device_node *node);
|
||||||
|
|
||||||
|
device_node *(*root_device)();
|
||||||
|
status_t (*get_next_child_device)(device_node *parent, device_node *node,
|
||||||
|
const device_attr *attrs);
|
||||||
|
device_node *(*get_parent)(device_node *node);
|
||||||
|
void (*put_device_node)(device_node *node);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
status_t (*acquire_io_resources)(io_resource *resources);
|
||||||
|
status_t (*release_io_resources)(const io_resource *resources);
|
||||||
|
|
||||||
|
int32 (*create_id)(const char *generator);
|
||||||
|
status_t (*free_id)(const char *generator, uint32 id);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
status_t (*get_attr_uint8)(device_node *node, const char *name,
|
||||||
|
uint8 *value, bool recursive);
|
||||||
|
status_t (*get_attr_uint16)(device_node *node, const char *name,
|
||||||
|
uint16 *value, bool recursive);
|
||||||
|
status_t (*get_attr_uint32)(device_node *node, const char *name,
|
||||||
|
uint32 *value, bool recursive);
|
||||||
|
status_t (*get_attr_uint64)(device_node *node, const char *name,
|
||||||
|
uint64 *value, bool recursive);
|
||||||
|
status_t (*get_attr_string)(device_node *node, const char *name,
|
||||||
|
const char **_value, bool recursive);
|
||||||
|
status_t (*get_attr_raw)(device_node *node, const char *name,
|
||||||
|
const void **_data, size_t *_size, bool recursive);
|
||||||
|
|
||||||
|
status_t (*get_next_attr)(device_node *node, device_attr **_attr);
|
||||||
|
} device_manager_info;
|
||||||
|
|
||||||
|
|
||||||
|
#define B_DEVICE_MANAGER_MODULE_NAME "system/device_manager/v1"
|
||||||
|
|
||||||
|
|
||||||
|
// interface of device driver
|
||||||
|
|
||||||
|
struct driver_module_info {
|
||||||
|
module_info info;
|
||||||
|
|
||||||
|
float (*supports_device)(device_node *parent);
|
||||||
|
status_t (*register_device)(device_node *parent);
|
||||||
|
|
||||||
|
status_t (*init_driver)(device_node *node, void **_driverData);
|
||||||
|
void (*uninit_driver)(device_node *node);
|
||||||
|
status_t (*register_child_devices)(device_node *node);
|
||||||
|
status_t (*rescan_child_devices)(device_node *node);
|
||||||
|
void (*device_removed)(device_node *node);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// standard device node attributes
|
||||||
|
|
||||||
|
#define B_DRIVER_PRETTY_NAME "driver/pretty name" // string
|
||||||
|
#define B_DRIVER_MAPPING "driver/mapping" // string
|
||||||
|
#define B_DRIVER_IS_BUS "driver/is_bus" // uint8
|
||||||
|
#define B_DRIVER_BUS "driver/bus" // string
|
||||||
|
#define B_DRIVER_FIXED_CHILD "fixed child" // string
|
||||||
|
#define B_DRIVER_FIND_CHILD_FLAGS "find child flags" // uint32
|
||||||
|
#define B_DRIVER_UNIQUE_DEVICE_ID "unique id" // string
|
||||||
|
#define B_DRIVER_DEVICE_TYPE "device type" // string
|
||||||
|
|
||||||
|
// find child flags
|
||||||
|
#define B_FIND_CHILD_ON_DEMAND 0x01
|
||||||
|
#define B_FIND_MULTIPLE_CHILDREN 0x02
|
||||||
|
|
||||||
|
// driver types
|
||||||
|
#define B_AUDIO_DRIVER_TYPE "audio"
|
||||||
|
#define B_BUS_DRIVER_TYPE "bus"
|
||||||
|
#define B_DISK_DRIVER_TYPE "disk"
|
||||||
|
#define B_GRAPHICS_DRIVER_TYPE "graphics"
|
||||||
|
#define B_INPUT_DRIVER_TYPE "input"
|
||||||
|
#define B_MISC_DRIVER_TYPE "misc"
|
||||||
|
#define B_NETWORK_DRIVER_TYPE "net"
|
||||||
|
#define B_VIDEO_DRIVER_TYPE "video"
|
||||||
|
#define B_INTERRUPT_CONTROLLER_DRIVER_TYPE "interrupt controller"
|
||||||
|
|
||||||
|
|
||||||
|
// interface of device
|
||||||
|
|
||||||
|
typedef struct io_request io_request;
|
||||||
|
|
||||||
|
struct device_module_info {
|
||||||
|
module_info info;
|
||||||
|
|
||||||
|
status_t (*init_device)(void *cookie);
|
||||||
|
void (*uninit_device)(void *cookie);
|
||||||
|
|
||||||
|
status_t (*device_open)(void *deviceCookie, int openMode, void **_cookie);
|
||||||
|
status_t (*device_close)(void *cookie);
|
||||||
|
status_t (*device_free)(void *cookie);
|
||||||
|
status_t (*device_read)(void *cookie, off_t pos, void *buffer,
|
||||||
|
size_t *_length);
|
||||||
|
status_t (*device_write)(void *cookie, off_t pos, const void *buffer,
|
||||||
|
size_t *_length);
|
||||||
|
status_t (*device_ioctl)(void *cookie, int32 op, void *buffer,
|
||||||
|
size_t length);
|
||||||
|
status_t (*device_io)(void *cookie, io_request *request);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
|
#endif /* _DEVICE_MANAGER_H */
|
178
src/tests/system/kernel/device_manager/playground/driver.cpp
Normal file
178
src/tests/system/kernel/device_manager/playground/driver.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - driver
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
supports_device(device_node *parent)
|
||||||
|
{
|
||||||
|
const char* bus;
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false)
|
||||||
|
!= B_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (bus == NULL || strcmp(bus, BUS_NAME))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bus_device_module_info* module
|
||||||
|
= (bus_device_module_info*)gDeviceManager->driver_module(parent);
|
||||||
|
void* data = gDeviceManager->driver_data(parent);
|
||||||
|
|
||||||
|
bus_info info;
|
||||||
|
if (module->get_bus_info(data, &info) == B_OK
|
||||||
|
&& info.vendor_id == 0x1001
|
||||||
|
&& info.device_id == 0x0001)
|
||||||
|
return 1.0;
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node *parent)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_driver(device_node *node, void **_cookie)
|
||||||
|
{
|
||||||
|
// also publishes any devices/nodes with dedicated calls
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_driver(device_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_child_devices(device_node *node)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
device_removed(device_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - device
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_device(void *deviceCookie)
|
||||||
|
{
|
||||||
|
// called once before one or several open() calls
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_device(void *deviceCookie)
|
||||||
|
{
|
||||||
|
// supposed to free deviceCookie, called when the last reference to
|
||||||
|
// the device is closed
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_open(void *deviceCookie, int openMode, void **_cookie)
|
||||||
|
{
|
||||||
|
// deviceCookie is an object attached to the published device
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_close(void *cookie)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_free(void *cookie)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_ioctl(void *cookie, int32 op, void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
device_io(void *cookie, io_request *request)
|
||||||
|
{
|
||||||
|
// new function to deal with I/O requests directly.
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
struct driver_module_info gDriverModuleInfo = {
|
||||||
|
{
|
||||||
|
"sample_driver/driver_v1",
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
supports_device,
|
||||||
|
register_device,
|
||||||
|
init_driver,
|
||||||
|
uninit_driver,
|
||||||
|
register_child_devices,
|
||||||
|
NULL,
|
||||||
|
device_removed,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_module_info gDeviceModuleInfo = {
|
||||||
|
{
|
||||||
|
"sample_driver/device_v1",
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
init_device,
|
||||||
|
uninit_device,
|
||||||
|
|
||||||
|
device_open,
|
||||||
|
device_close,
|
||||||
|
device_free,
|
||||||
|
device_read,
|
||||||
|
device_write,
|
||||||
|
device_ioctl,
|
||||||
|
device_io,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user