From b12912bead367137ee3d458fb18be8b39714fb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 8 Nov 2006 20:16:55 +0000 Subject: [PATCH] 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 --- src/tests/system/kernel/Jamfile | 1 + .../system/kernel/device_manager/Jamfile | 11 + .../system/kernel/device_manager/config.c | 235 ++++++++++++++++++ .../kernel/device_manager/config_driver.h | 39 +++ .../system/kernel/device_manager/dm_wrapper.c | 78 ++++++ .../system/kernel/device_manager/dm_wrapper.h | 13 + .../system/kernel/device_manager/listdev.c | 96 +++++++ 7 files changed, 473 insertions(+) create mode 100644 src/tests/system/kernel/device_manager/Jamfile create mode 100644 src/tests/system/kernel/device_manager/config.c create mode 100644 src/tests/system/kernel/device_manager/config_driver.h create mode 100644 src/tests/system/kernel/device_manager/dm_wrapper.c create mode 100644 src/tests/system/kernel/device_manager/dm_wrapper.h create mode 100644 src/tests/system/kernel/device_manager/listdev.c diff --git a/src/tests/system/kernel/Jamfile b/src/tests/system/kernel/Jamfile index b6472bf292..cbadae3cee 100644 --- a/src/tests/system/kernel/Jamfile +++ b/src/tests/system/kernel/Jamfile @@ -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 ; diff --git a/src/tests/system/kernel/device_manager/Jamfile b/src/tests/system/kernel/device_manager/Jamfile new file mode 100644 index 0000000000..acb495193f --- /dev/null +++ b/src/tests/system/kernel/device_manager/Jamfile @@ -0,0 +1,11 @@ +SubDir HAIKU_TOP src tests system kernel device_manager ; + +BinCommand listdev : + dm_wrapper.c + listdev.c +; + +KernelAddon config : + config.c + ; + diff --git a/src/tests/system/kernel/device_manager/config.c b/src/tests/system/kernel/device_manager/config.c new file mode 100644 index 0000000000..acd67a2ed8 --- /dev/null +++ b/src/tests/system/kernel/device_manager/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 +#include +#include +#include + +#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); +} + diff --git a/src/tests/system/kernel/device_manager/config_driver.h b/src/tests/system/kernel/device_manager/config_driver.h new file mode 100644 index 0000000000..d7daf920e4 --- /dev/null +++ b/src/tests/system/kernel/device_manager/config_driver.h @@ -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_ */ diff --git a/src/tests/system/kernel/device_manager/dm_wrapper.c b/src/tests/system/kernel/device_manager/dm_wrapper.c new file mode 100644 index 0000000000..a435c305e8 --- /dev/null +++ b/src/tests/system/kernel/device_manager/dm_wrapper.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include + +#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)); +} + diff --git a/src/tests/system/kernel/device_manager/dm_wrapper.h b/src/tests/system/kernel/device_manager/dm_wrapper.h new file mode 100644 index 0000000000..3b72e796be --- /dev/null +++ b/src/tests/system/kernel/device_manager/dm_wrapper.h @@ -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 diff --git a/src/tests/system/kernel/device_manager/listdev.c b/src/tests/system/kernel/device_manager/listdev.c new file mode 100644 index 0000000000..82f175997f --- /dev/null +++ b/src/tests/system/kernel/device_manager/listdev.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +#include +#include +#include + +#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; +}