* 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:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user