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:
Jérôme Duval 2006-11-08 20:16:55 +00:00
parent e3c14348aa
commit b12912bead
7 changed files with 473 additions and 0 deletions

View File

@ -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 ;

View File

@ -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
;

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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, &params, 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, &params, 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, &params, 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, &params, 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, &params, sizeof(params));
}

View File

@ -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

View File

@ -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;
}