* each device manager node has now an autogenerated identifier

* added a generic syscall for device_manager
it enables to iterate the device manager tree from userland
* the listdev tool is now using it: it's still incomplete as it only dumps nodes and attributes


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19260 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2006-11-12 15:28:09 +00:00
parent 2177785876
commit bef4e1fc77
11 changed files with 322 additions and 464 deletions
@@ -14,6 +14,7 @@
#include "device_manager_private.h"
#include <kdevice_manager.h>
#include <generic_syscall.h>
#include <KernelExport.h>
#include <string.h>
@@ -166,6 +167,7 @@ device_manager_init(struct kernel_args *args)
#endif
add_debugger_command("dm_tree", &dump_device_nodes, "dump device node tree");
register_generic_syscall(DEVICE_MANAGER_SYSCALLS, device_manager_control, 1, 0);
return B_OK;
}
@@ -176,6 +176,8 @@ status_t dm_get_next_child_node(device_node_info *parent,
device_node_info *dm_get_root(void);
device_node_info *dm_get_parent(device_node_info *node);
status_t device_manager_control(const char *subsystem, uint32 function, void *buffer, size_t bufferSize);
// notifications.c
+166
View File
@@ -24,6 +24,8 @@
#include "device_manager_private.h"
#include "dl_list.h"
#include <kernel.h>
#include <KernelExport.h>
#include <TypeConstants.h>
@@ -41,6 +43,8 @@
benaphore gNodeLock;
uint32 sNodeID; // nodes counter
static void
put_level(int32 level)
@@ -263,6 +267,7 @@ dm_allocate_node(const device_attr *attrs, const io_resource_handle *resources,
node->num_blocked_loads = 0;
node->load_block_count = 0;
node->loading = 0;
node->internal_id = sNodeID++;
TRACE(("dm_allocate_node(): new node %p\n", node));
@@ -432,6 +437,7 @@ dm_dump_node(device_node_info *node, int32 level)
status_t
dm_init_nodes(void)
{
sNodeID = 1;
return benaphore_init(&gNodeLock, "device nodes");
}
@@ -513,3 +519,163 @@ dm_get_next_child_node(device_node_info *parent, device_node_info **_node,
return B_ENTRY_NOT_FOUND;
}
// hold gNodeLock
static device_node_info *
device_manager_find_device(device_node_info *parent, uint32 id)
{
device_node_info *node = NULL;
if (parent->internal_id == id)
return parent;
while ((node = (device_node_info *)list_get_next_item(&parent->children, node)) != NULL) {
device_node_info *child = device_manager_find_device(node, id);
if (child != NULL)
return child;
}
return NULL;
}
status_t
device_manager_control(const char *subsystem, uint32 function, void *buffer, size_t bufferSize)
{
switch (function) {
case DM_GET_ROOT: {
uint32 cookie;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
if (bufferSize < sizeof(uint32))
return B_BAD_VALUE;
cookie = gRootNode->internal_id;
// copy back to user space
if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
case DM_GET_CHILD: {
uint32 cookie;
device_node_info *node;
device_node_info *child;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
if (bufferSize < sizeof(uint32))
return B_BAD_VALUE;
if (user_memcpy(&cookie, buffer, sizeof(uint32)) < B_OK)
return B_BAD_ADDRESS;
benaphore_lock(&gNodeLock);
node = device_manager_find_device(gRootNode, cookie);
if (!node) {
benaphore_unlock(&gNodeLock);
return B_BAD_VALUE;
}
child = (device_node_info *)list_get_next_item(&node->children, NULL);
if (child)
cookie = child->internal_id;
benaphore_unlock(&gNodeLock);
if (!child)
return B_ENTRY_NOT_FOUND;
// copy back to user space
if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
case DM_GET_NEXT_CHILD: {
uint32 cookie;
device_node_info *node;
device_node_info *child;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
if (bufferSize < sizeof(uint32))
return B_BAD_VALUE;
if (user_memcpy(&cookie, buffer, sizeof(uint32)) < B_OK)
return B_BAD_ADDRESS;
benaphore_lock(&gNodeLock);
node = device_manager_find_device(gRootNode, cookie);
if (!node) {
benaphore_unlock(&gNodeLock);
return B_BAD_VALUE;
}
child = (device_node_info *)list_get_next_item(&node->parent->children, node);
if (child)
cookie = child->internal_id;
benaphore_unlock(&gNodeLock);
cookie++;
if (!child)
return B_ENTRY_NOT_FOUND;
// copy back to user space
if (user_memcpy(buffer, &cookie, sizeof(uint32)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
case DM_GET_NEXT_ATTRIBUTE: {
struct dev_attr attr;
device_node_info *node;
uint32 i = 0;
device_attr_info *attr_info;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
if (bufferSize < sizeof(struct dev_attr))
return B_BAD_VALUE;
if (user_memcpy(&attr, buffer, sizeof(struct dev_attr)) < B_OK)
return B_BAD_ADDRESS;
benaphore_lock(&gNodeLock);
node = device_manager_find_device(gRootNode, attr.node_cookie);
if (!node) {
benaphore_unlock(&gNodeLock);
return B_BAD_VALUE;
}
for (attr_info = node->attributes; attr.cookie > i && attr_info != NULL; attr_info = attr_info->next) {
i++;
}
if (!attr_info) {
benaphore_unlock(&gNodeLock);
return B_ENTRY_NOT_FOUND;
}
attr.cookie++;
strlcpy(attr.name, attr_info->attr.name, 254);
attr.type = attr_info->attr.type;
switch (attr_info->attr.type) {
case B_UINT8_TYPE:
attr.value.ui8 = attr_info->attr.value.ui8; break;
case B_UINT16_TYPE:
attr.value.ui16 = attr_info->attr.value.ui16; break;
case B_UINT32_TYPE:
attr.value.ui32 = attr_info->attr.value.ui32; break;
case B_UINT64_TYPE:
attr.value.ui64 = attr_info->attr.value.ui64; break;
case B_STRING_TYPE:
strlcpy(attr.value.string, attr_info->attr.value.string, 254); break;
case B_RAW_TYPE:
if (attr.value.raw.length > attr_info->attr.value.raw.length)
attr.value.raw.length = attr_info->attr.value.raw.length;
memcpy(attr.value.raw.data, attr_info->attr.value.raw.data,
attr.value.raw.length);
break;
}
benaphore_unlock(&gNodeLock);
// copy back to user space
if (user_memcpy(buffer, &attr, sizeof(struct dev_attr)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
};
return B_BAD_HANDLER;
}