added a 'dm_tree' like test tool, ioctl based.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19235 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e3c14348aa
commit
b12912bead
|
@ -70,4 +70,5 @@ SimpleTest lock_node_test :
|
|||
|
||||
SubInclude HAIKU_TOP src tests system kernel cache ;
|
||||
#SubInclude HAIKU_TOP src tests system kernel disk_device_manager ;
|
||||
SubInclude HAIKU_TOP src tests system kernel device_manager ;
|
||||
SubInclude HAIKU_TOP src tests system kernel util ;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
SubDir HAIKU_TOP src tests system kernel device_manager ;
|
||||
|
||||
BinCommand <test>listdev :
|
||||
dm_wrapper.c
|
||||
listdev.c
|
||||
;
|
||||
|
||||
KernelAddon <test_driver>config :
|
||||
config.c
|
||||
;
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/* config driver
|
||||
* provides userland access to the device manager
|
||||
*
|
||||
* Copyright 2002-2004, Axel Doerfler. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors : Axel Doerfler, Jerome Duval
|
||||
*/
|
||||
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <drivers/device_manager.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config_driver.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACE(x...) dprintf(x)
|
||||
#else
|
||||
#define TRACE(x...)
|
||||
#endif
|
||||
|
||||
#define DEVICE_NAME "misc/config"
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
device_manager_info *gDeviceManager;
|
||||
|
||||
typedef struct _driver_cookie {
|
||||
device_node_handle parent;
|
||||
device_node_handle child;
|
||||
device_attr_handle attr;
|
||||
} driver_cookie;
|
||||
|
||||
// Device interface
|
||||
|
||||
|
||||
static status_t
|
||||
config_open(const char *name, uint32 flags, void **_cookie)
|
||||
{
|
||||
driver_cookie *cookie = malloc(sizeof(driver_cookie));
|
||||
if (cookie == NULL)
|
||||
return B_ERROR;
|
||||
*_cookie = cookie;
|
||||
cookie->child = gDeviceManager->get_root();
|
||||
cookie->parent = NULL;
|
||||
cookie->attr = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
config_close(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
config_free_cookie(void *cookie)
|
||||
{
|
||||
driver_cookie *cook = (driver_cookie *)cookie;
|
||||
gDeviceManager->put_device_node(cook->child);
|
||||
if (cook->parent)
|
||||
gDeviceManager->put_device_node(cook->parent);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
config_ioctl(void *cookie, uint32 op, void *buffer, size_t len)
|
||||
{
|
||||
driver_cookie *cook = (driver_cookie *)cookie;
|
||||
device_node_handle child = NULL;
|
||||
const device_attr *attr = NULL;
|
||||
|
||||
struct dm_ioctl_data *params = (struct dm_ioctl_data *)buffer;
|
||||
status_t err = B_OK;
|
||||
|
||||
// simple check for validity of the argument
|
||||
if (params == NULL || params->magic != op)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
switch (op) {
|
||||
case DM_GET_CHILD:
|
||||
TRACE("DM_GET_CHILD parent %p child %p\n", cook->parent, cook->child);
|
||||
if (cook->attr) {
|
||||
gDeviceManager->release_attr(cook->child, cook->attr);
|
||||
cook->attr = NULL;
|
||||
}
|
||||
err = gDeviceManager->get_next_child_device(cook->child, &child, NULL);
|
||||
if (err == B_OK) {
|
||||
if (cook->parent)
|
||||
gDeviceManager->put_device_node(cook->parent);
|
||||
cook->parent = cook->child;
|
||||
cook->child = child;
|
||||
}
|
||||
return err;
|
||||
case DM_GET_NEXT_CHILD:
|
||||
TRACE("DM_GET_NEXT_CHILD parent %p child %p\n", cook->parent, cook->child);
|
||||
if (!cook->parent)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
if (cook->attr) {
|
||||
gDeviceManager->release_attr(cook->child, cook->attr);
|
||||
cook->attr = NULL;
|
||||
}
|
||||
return gDeviceManager->get_next_child_device(cook->parent, &cook->child, NULL);
|
||||
case DM_GET_PARENT:
|
||||
TRACE("DM_GET_PARENT parent %p child %p\n", cook->parent, cook->child);
|
||||
if (!cook->parent)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
if (cook->attr) {
|
||||
gDeviceManager->release_attr(cook->child, cook->attr);
|
||||
cook->attr = NULL;
|
||||
}
|
||||
if (cook->child)
|
||||
gDeviceManager->put_device_node(cook->child);
|
||||
cook->child = cook->parent;
|
||||
cook->parent = gDeviceManager->get_parent(cook->child);
|
||||
return B_OK;
|
||||
case DM_GET_NEXT_ATTRIBUTE:
|
||||
TRACE("DM_NEXT_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr);
|
||||
return gDeviceManager->get_next_attr(cook->child, &cook->attr);
|
||||
case DM_RETRIEVE_ATTRIBUTE:
|
||||
TRACE("DM_RETRIEVE_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr);
|
||||
err = gDeviceManager->retrieve_attr(cook->attr, &attr);
|
||||
if (err == B_OK) {
|
||||
strlcpy(params->attr->name, attr->name, 254);
|
||||
params->attr->type = attr->type;
|
||||
switch (attr->type) {
|
||||
case B_UINT8_TYPE:
|
||||
params->attr->value.ui8 = attr->value.ui8; break;
|
||||
case B_UINT16_TYPE:
|
||||
params->attr->value.ui16 = attr->value.ui16; break;
|
||||
case B_UINT32_TYPE:
|
||||
params->attr->value.ui32 = attr->value.ui32; break;
|
||||
case B_UINT64_TYPE:
|
||||
params->attr->value.ui64 = attr->value.ui64; break;
|
||||
case B_STRING_TYPE:
|
||||
strlcpy(params->attr->value.string, attr->value.string, 254); break;
|
||||
case B_RAW_TYPE:
|
||||
if (params->attr->value.raw.length > attr->value.raw.length)
|
||||
params->attr->value.raw.length = attr->value.raw.length;
|
||||
memcpy(params->attr->value.raw.data, attr->value.raw.data,
|
||||
params->attr->value.raw.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
config_read(void * cookie, off_t pos, void *buf, size_t *_length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
config_write(void * cookie, off_t pos, const void *buf, size_t *_length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Driver interface
|
||||
|
||||
|
||||
status_t
|
||||
init_hardware()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
const char **
|
||||
publish_devices(void)
|
||||
{
|
||||
static const char *devices[] = {
|
||||
DEVICE_NAME,
|
||||
NULL
|
||||
};
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
|
||||
device_hooks *
|
||||
find_device(const char *name)
|
||||
{
|
||||
static device_hooks hooks = {
|
||||
&config_open,
|
||||
&config_close,
|
||||
&config_free_cookie,
|
||||
&config_ioctl,
|
||||
&config_read,
|
||||
&config_write,
|
||||
/* Leave select/deselect/readv/writev undefined. The kernel will
|
||||
* use its own default implementation. The basic hooks above this
|
||||
* line MUST be defined, however. */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (!strcmp(name, DEVICE_NAME))
|
||||
return &hooks;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
init_driver()
|
||||
{
|
||||
return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver()
|
||||
{
|
||||
if (gDeviceManager != NULL)
|
||||
put_module(B_DEVICE_MANAGER_MODULE_NAME);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _CONFIG_DRIVER_H_
|
||||
#define _CONFIG_DRIVER_H_
|
||||
|
||||
/* definitions for the /dev/misc/config driver which provides access
|
||||
* to the device_manager via calls to ioctl().
|
||||
*/
|
||||
|
||||
/* the magic is the ioctl */
|
||||
|
||||
#define DM_GET_CHILD 'GCHI'
|
||||
#define DM_GET_NEXT_CHILD 'GNCH'
|
||||
#define DM_GET_PARENT 'GPAR'
|
||||
#define DM_GET_NEXT_ATTRIBUTE 'GNAT'
|
||||
#define DM_RETRIEVE_ATTRIBUTE 'RATT'
|
||||
|
||||
struct dev_attr {
|
||||
char name[255];
|
||||
type_code type;
|
||||
union {
|
||||
uint8 ui8;
|
||||
uint16 ui16;
|
||||
uint32 ui32;
|
||||
uint64 ui64;
|
||||
char string[255];
|
||||
struct {
|
||||
void *data;
|
||||
size_t length;
|
||||
} raw;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct dm_ioctl_data {
|
||||
uint32 magic;
|
||||
struct dev_attr *attr;
|
||||
};
|
||||
|
||||
#define DM_DEVICE_NAME "misc/config"
|
||||
|
||||
#endif /* _CONFIG_DRIVER_H_ */
|
|
@ -0,0 +1,78 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drivers/device_manager.h>
|
||||
|
||||
#include "config_driver.h"
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
static int fd;
|
||||
|
||||
status_t init_dm_wrapper(void)
|
||||
{
|
||||
static const char device[] = "/dev/" DM_DEVICE_NAME;
|
||||
|
||||
fd = open(device, 0);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t uninit_dm_wrapper(void)
|
||||
{
|
||||
close(fd);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t get_child(void)
|
||||
{
|
||||
struct dm_ioctl_data params;
|
||||
|
||||
params.magic = DM_GET_CHILD;
|
||||
params.attr = NULL;
|
||||
|
||||
return ioctl(fd, params.magic, ¶ms, sizeof(params));
|
||||
}
|
||||
|
||||
status_t get_next_child(void)
|
||||
{
|
||||
struct dm_ioctl_data params;
|
||||
|
||||
params.magic = DM_GET_NEXT_CHILD;
|
||||
params.attr = NULL;
|
||||
|
||||
return ioctl(fd, params.magic, ¶ms, sizeof(params));
|
||||
}
|
||||
|
||||
status_t get_parent(void)
|
||||
{
|
||||
struct dm_ioctl_data params;
|
||||
|
||||
params.magic = DM_GET_PARENT;
|
||||
params.attr = NULL;
|
||||
|
||||
return ioctl(fd, params.magic, ¶ms, sizeof(params));
|
||||
}
|
||||
|
||||
status_t dm_get_next_attr(void)
|
||||
{
|
||||
struct dm_ioctl_data params;
|
||||
|
||||
params.magic = DM_GET_NEXT_ATTRIBUTE;
|
||||
params.attr = NULL;
|
||||
|
||||
return ioctl(fd, params.magic, ¶ms, sizeof(params));
|
||||
}
|
||||
|
||||
status_t dm_retrieve_attr(struct dev_attr *attr)
|
||||
{
|
||||
struct dm_ioctl_data params;
|
||||
|
||||
params.magic = DM_RETRIEVE_ATTRIBUTE;
|
||||
params.attr = attr;
|
||||
|
||||
return ioctl(fd, params.magic, ¶ms, sizeof(params));
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _DM_WRAPPER_H_
|
||||
#define _DM_WRAPPER_H_
|
||||
|
||||
status_t init_dm_wrapper(void);
|
||||
status_t uninit_dm_wrapper(void);
|
||||
|
||||
status_t get_child(void);
|
||||
status_t get_next_child(void);
|
||||
status_t get_parent(void);
|
||||
status_t dm_get_next_attr(void);
|
||||
status_t dm_retrieve_attr(struct dev_attr *attr);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,96 @@
|
|||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drivers/device_manager.h>
|
||||
#include <drivers/module.h>
|
||||
#include <drivers/PCI.h>
|
||||
|
||||
#include "config_driver.h"
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
static void
|
||||
put_level(int32 level)
|
||||
{
|
||||
while (level-- > 0)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_attribute(struct dev_attr *attr, int32 level)
|
||||
{
|
||||
if (attr == NULL)
|
||||
return;
|
||||
|
||||
put_level(level);
|
||||
printf("\"%s\" : ", attr->name);
|
||||
switch (attr->type) {
|
||||
case B_STRING_TYPE:
|
||||
printf("string : \"%s\"", attr->value.string);
|
||||
break;
|
||||
case B_UINT8_TYPE:
|
||||
printf("uint8 : %u (%#x)", attr->value.ui8, attr->value.ui8);
|
||||
break;
|
||||
case B_UINT16_TYPE:
|
||||
printf("uint16 : %u (%#x)", attr->value.ui16, attr->value.ui16);
|
||||
break;
|
||||
case B_UINT32_TYPE:
|
||||
printf("uint32 : %lu (%#lx)", attr->value.ui32, attr->value.ui32);
|
||||
break;
|
||||
case B_UINT64_TYPE:
|
||||
printf("uint64 : %Lu (%#Lx)", attr->value.ui64, attr->value.ui64);
|
||||
break;
|
||||
default:
|
||||
printf("raw data");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_device(uint8 level)
|
||||
{
|
||||
char data[256];
|
||||
|
||||
while (dm_get_next_attr() == B_OK) {
|
||||
struct dev_attr attr;
|
||||
attr.value.raw.data = data;
|
||||
attr.value.raw.length = sizeof(data);
|
||||
dm_retrieve_attr(&attr);
|
||||
dump_attribute(&attr, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_nodes(uint8 level)
|
||||
{
|
||||
status_t err;
|
||||
dump_device(level);
|
||||
|
||||
if (get_child() != B_OK)
|
||||
return;
|
||||
|
||||
do {
|
||||
dump_nodes(level+1);
|
||||
} while ((err = get_next_child()) == B_OK);
|
||||
|
||||
get_parent();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
status_t error;
|
||||
|
||||
if ((error = init_dm_wrapper()) < 0) {
|
||||
printf("Error initializing device manager (%s)\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
dump_nodes(0);
|
||||
|
||||
uninit_dm_wrapper();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue