From bef4e1fc776e6282d04556fc6f5ca592b3cfe75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 12 Nov 2006 15:28:09 +0000 Subject: [PATCH] * 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 --- headers/private/kernel/kdevice_manager.h | 27 ++ src/bin/listdev/Jamfile | 6 +- src/bin/listdev/cm_wrapper.c | 143 -------- src/bin/listdev/cm_wrapper.h | 25 -- src/bin/listdev/config_driver.h | 29 -- src/bin/listdev/dm_wrapper.c | 48 +++ src/bin/listdev/dm_wrapper.h | 14 + src/bin/listdev/listdev.c | 324 ++++-------------- .../kernel/device_manager/device_manager.c | 2 + .../device_manager/device_manager_private.h | 2 + src/system/kernel/device_manager/nodes.c | 166 +++++++++ 11 files changed, 322 insertions(+), 464 deletions(-) delete mode 100644 src/bin/listdev/cm_wrapper.c delete mode 100644 src/bin/listdev/cm_wrapper.h delete mode 100644 src/bin/listdev/config_driver.h create mode 100644 src/bin/listdev/dm_wrapper.c create mode 100644 src/bin/listdev/dm_wrapper.h diff --git a/headers/private/kernel/kdevice_manager.h b/headers/private/kernel/kdevice_manager.h index e3e560bd57..81ae60cdd6 100644 --- a/headers/private/kernel/kdevice_manager.h +++ b/headers/private/kernel/kdevice_manager.h @@ -38,6 +38,7 @@ struct device_node_info { uint32 num_io_resources; // number of I/O resources io_resource_handle *io_resources; // array of I/O resource (NULL-terminated) bool automatically_loaded; // loaded automatically because PNP_DRIVER_ALWAYS_LOADED + uint32 internal_id; // internal identifier }; @@ -50,6 +51,32 @@ extern "C" { extern status_t probe_for_device_type(const char *type); extern status_t device_manager_init(struct kernel_args *args); +// temporary/optional device manager syscall API +#define DEVICE_MANAGER_SYSCALLS "device_manager" + +#define DM_GET_ROOT 1 +#define DM_GET_CHILD 2 +#define DM_GET_NEXT_CHILD 3 +#define DM_GET_NEXT_ATTRIBUTE 4 + +struct dev_attr { + uint32 node_cookie; + uint32 cookie; + 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; +}; + #ifdef __cplusplus } #endif diff --git a/src/bin/listdev/Jamfile b/src/bin/listdev/Jamfile index 2950387611..f6a96e74ab 100644 --- a/src/bin/listdev/Jamfile +++ b/src/bin/listdev/Jamfile @@ -1,7 +1,11 @@ SubDir HAIKU_TOP src bin listdev ; +UsePrivateHeaders kernel ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; + BinCommand listdev : - cm_wrapper.c + dm_wrapper.c listdev.c ; diff --git a/src/bin/listdev/cm_wrapper.c b/src/bin/listdev/cm_wrapper.c deleted file mode 100644 index 1d36b81152..0000000000 --- a/src/bin/listdev/cm_wrapper.c +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "cm_wrapper.h" -#include "config_driver.h" - -static int fd; - -status_t init_cm_wrapper(void) -{ - static const char device[] = "/dev/" CM_DEVICE_NAME; - - fd = open(device, 0); - if (fd < 0) - return errno; - return B_OK; -} - -status_t uninit_cm_wrapper(void) -{ - close(fd); - return B_OK; -} - -status_t get_next_device_info(bus_type bus, uint64 *cookie, - struct device_info *info, uint32 size) -{ - status_t result; - struct cm_ioctl_data params; - - params.magic = CM_GET_NEXT_DEVICE_INFO; - params.bus = bus; - params.cookie = *cookie; - params.data = (void *)info; - params.data_len = size; - - result = ioctl(fd, params.magic, ¶ms, sizeof(params)); - - if (result == B_OK) *cookie = params.cookie; - - return result; -} - -status_t get_device_info_for(uint64 id, struct device_info *info, - uint32 size) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_DEVICE_INFO_FOR; - params.cookie = id; - params.data = (void *)info; - params.data_len = size; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -status_t get_size_of_current_configuration_for(uint64 id) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_SIZE_OF_CURRENT_CONFIGURATION_FOR; - params.cookie = id; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -status_t get_current_configuration_for(uint64 id, - struct device_configuration *current, uint32 size) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_CURRENT_CONFIGURATION_FOR; - params.cookie = id; - params.data = (void *)current; - params.data_len = size; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -status_t get_size_of_possible_configurations_for(uint64 id) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_SIZE_OF_POSSIBLE_CONFIGURATIONS_FOR; - params.cookie = id; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -status_t get_possible_configurations_for(uint64 id, - struct possible_device_configurations *possible, uint32 size) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_POSSIBLE_CONFIGURATIONS_FOR; - params.cookie = id; - params.data = (void *)possible; - params.data_len = size; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - - -status_t count_resource_descriptors_of_type( - struct device_configuration *c, resource_type type) -{ - struct cm_ioctl_data params; - - params.magic = CM_COUNT_RESOURCE_DESCRIPTORS_OF_TYPE; - params.config = c; - params.type = type; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -status_t get_nth_resource_descriptor_of_type( - struct device_configuration *c, uint32 n, - resource_type type, resource_descriptor *d, uint32 size) -{ - struct cm_ioctl_data params; - - params.magic = CM_GET_NTH_RESOURCE_DESCRIPTOR_OF_TYPE; - params.config = c; - params.n = n; - params.type = type; - params.data = d; - params.data_len = size; - - return ioctl(fd, params.magic, ¶ms, sizeof(params)); -} - -uchar mask_to_value(uint32 mask) -{ - uchar value; - if (!mask) return 0; - for (value=0,mask>>=1;mask;value++,mask>>=1) - ; - return value; -} diff --git a/src/bin/listdev/cm_wrapper.h b/src/bin/listdev/cm_wrapper.h deleted file mode 100644 index a923105427..0000000000 --- a/src/bin/listdev/cm_wrapper.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _CM_WRAPPER_H_ -#define _CM_WRAPPER_H_ - -status_t init_cm_wrapper(void); -status_t uninit_cm_wrapper(void); - -status_t get_next_device_info(bus_type bus, uint64 *cookie, - struct device_info *info, uint32 size); -status_t get_device_info_for(uint64 id, struct device_info *info, - uint32 size); -status_t get_size_of_current_configuration_for(uint64 id); -status_t get_current_configuration_for(uint64 id, - struct device_configuration *current, uint32 size); -status_t get_size_of_possible_configurations_for(uint64 id); -status_t get_possible_configurations_for(uint64 id, - struct possible_device_configurations *possible, uint32 size); -status_t count_resource_descriptors_of_type( - struct device_configuration *c, resource_type type); -status_t get_nth_resource_descriptor_of_type( - struct device_configuration *c, uint32 n, resource_type type, - resource_descriptor *d, uint32 size); - -uchar mask_to_value(uint32 mask); - -#endif diff --git a/src/bin/listdev/config_driver.h b/src/bin/listdev/config_driver.h deleted file mode 100644 index bd70f0411b..0000000000 --- a/src/bin/listdev/config_driver.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _CONFIG_MANAGER_DRIVER_H_ -#define _CONFIG_MANAGER_DRIVER_H_ - -/* the magic is the ioctl */ - -#define CM_GET_NEXT_DEVICE_INFO 'GNDI' -#define CM_GET_DEVICE_INFO_FOR 'GDIF' -#define CM_GET_SIZE_OF_CURRENT_CONFIGURATION_FOR 'GSCC' -#define CM_GET_CURRENT_CONFIGURATION_FOR 'GCCF' -#define CM_GET_SIZE_OF_POSSIBLE_CONFIGURATIONS_FOR 'GSPC' -#define CM_GET_POSSIBLE_CONFIGURATIONS_FOR 'GPCF' - -#define CM_COUNT_RESOURCE_DESCRIPTORS_OF_TYPE 'CRDT' -#define CM_GET_NTH_RESOURCE_DESCRIPTOR_OF_TYPE 'GNRD' - -struct cm_ioctl_data { - uint32 magic; - bus_type bus; - uint64 cookie; - void *config; - uint32 n; - uint32 type; - void *data; - uint32 data_len; -}; - -#define CM_DEVICE_NAME "misc/config" - -#endif diff --git a/src/bin/listdev/dm_wrapper.c b/src/bin/listdev/dm_wrapper.c new file mode 100644 index 0000000000..5e79f783f5 --- /dev/null +++ b/src/bin/listdev/dm_wrapper.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dm_wrapper.h" + + +status_t init_dm_wrapper(void) +{ + uint32 version = 0; + return _kern_generic_syscall(DEVICE_MANAGER_SYSCALLS, B_SYSCALL_INFO, &version, sizeof(version)); +} + +status_t uninit_dm_wrapper(void) +{ + return B_OK; +} + +status_t +get_root(uint32 *cookie) +{ + return _kern_generic_syscall(DEVICE_MANAGER_SYSCALLS, DM_GET_ROOT, cookie, sizeof(uint32)); +} + +status_t +get_child(uint32 *device) +{ + return _kern_generic_syscall(DEVICE_MANAGER_SYSCALLS, DM_GET_CHILD, device, sizeof(uint32)); +} + +status_t +get_next_child(uint32 *device) +{ + return _kern_generic_syscall(DEVICE_MANAGER_SYSCALLS, DM_GET_NEXT_CHILD, device, sizeof(uint32)); +} + +status_t +dm_get_next_attr(struct dev_attr *attr) +{ + return _kern_generic_syscall(DEVICE_MANAGER_SYSCALLS, DM_GET_NEXT_ATTRIBUTE, attr, sizeof(struct dev_attr)); +} + diff --git a/src/bin/listdev/dm_wrapper.h b/src/bin/listdev/dm_wrapper.h new file mode 100644 index 0000000000..c03430d47b --- /dev/null +++ b/src/bin/listdev/dm_wrapper.h @@ -0,0 +1,14 @@ +#ifndef _DM_WRAPPER_H_ +#define _DM_WRAPPER_H_ + +#include "kdevice_manager.h" + +status_t init_dm_wrapper(void); +status_t uninit_dm_wrapper(void); + +status_t get_root(uint32 *cookie); +status_t get_child(uint32 *cookie); +status_t get_next_child(uint32 *cookie); +status_t dm_get_next_attr(struct dev_attr *attr); + +#endif diff --git a/src/bin/listdev/listdev.c b/src/bin/listdev/listdev.c index 9f87f11cd9..2f2071f86c 100644 --- a/src/bin/listdev/listdev.c +++ b/src/bin/listdev/listdev.c @@ -3,304 +3,96 @@ #include #include -#include -#include +#include #include #include -#include "cm_wrapper.h" -#include "config_driver.h" +#include "dm_wrapper.h" -#define NEXT_POSSIBLE(c) \ - (c) = (void *)((uchar *)(c) + sizeof(struct device_configuration) \ - + (c)->num_resources * sizeof(resource_descriptor)); +static void +put_level(int32 level) +{ + while (level-- > 0) + printf(" "); +} static void -dump_mask(uint32 mask) +dump_attribute(struct dev_attr *attr, int32 level) { - bool first = true; - int i = 0; - printf("["); - if (!mask) - printf("none"); - for (;mask;mask>>=1,i++) - if (mask & 1) { - printf("%s%d", first ? "" : ",", i); - first = false; - } - printf("]"); + 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_configuration(struct device_configuration *c) +dump_device(uint32 *node, uint8 level) { - int i, num; - resource_descriptor r; + char data[256]; + struct dev_attr attr; + attr.cookie = 0; + attr.node_cookie = *node; + attr.value.raw.data = data; + attr.value.raw.length = sizeof(data); - num = count_resource_descriptors_of_type(c, B_IRQ_RESOURCE); - if (num) { - printf("irq%s ", (num == 1) ? "" : "s"); - for (i=0;idevtype.base < 13) ? base_desc[info->devtype.base] : "Unknown"); - if (info->devtype.subtype == 0x80) - printf(" (Other)"); - else { - struct subtype_descriptions *s = subtype_desc; - - while (s->name) { - if ((info->devtype.base == s->base) && (info->devtype.subtype == s->subtype)) - break; - s++; - } - printf(" (%s)", (s->name) ? s->name : "Unknown"); - } - printf(" [%x|%x|%x]\n", info->devtype.base, info->devtype.subtype, info->devtype.interface); + if (get_child(&child) != B_OK) + return; - if (!(info->flags & B_DEVICE_INFO_ENABLED)) { - printf("Device is disabled (%s)\n", strerror(info->config_status)); - } else if (info->flags & B_DEVICE_INFO_CONFIGURED) { - printf("Current configuration: "); - dump_device_configuration(current); - } else { - printf("Currently unconfigured.\n"); - } + do { + dump_nodes(&child, level+1); + } while ((err = get_next_child(&child)) == B_OK); - printf("%lx configurations\n", possible->num_possible); - config = possible->possible + 0; - for (i=0;inum_possible;i++) { - printf("\nPossible configuration #%d: ", i); - dump_device_configuration(config); - NEXT_POSSIBLE(config); - } - - printf("\n"); -} - -static void -dump_isa_info(struct device_info *info) -{ - struct isa_info *isa = (struct isa_info *) - ((uchar *)info + info->bus_dependent_info_offset); - - printf("CSN %x LDN %x %s %s\n", isa->csn, - isa->ldn, isa->card_name, isa->logical_device_name); -} - -static void -dump_pci_info(struct device_info *info) -{ - struct pci_info *pci = (struct pci_info *) - ((uchar *)info + info->bus_dependent_info_offset); - - printf("vendor id: %x, device id: %x\n", pci->vendor_id, pci->device_id); -} - -static void -dump_devices_for_bus(bus_type bus, void (*f)(struct device_info *)) -{ - status_t size; - uint64 cookie; - int index = 0; - void *current, *possible; - struct device_info dummy, *info; - - cookie = 0; - while (get_next_device_info(bus, &cookie, &dummy, sizeof(dummy)) == B_OK) { - info = (struct device_info *)malloc(dummy.size); - if (!info) { - printf("Out of core\n"); - break; - } - - if (get_device_info_for(cookie, info, dummy.size) != B_OK) { - printf("Error getting device information\n"); - break; - } - - size = get_size_of_current_configuration_for(cookie); - if (size < B_OK) { - printf("Error getting the size of the current configuration\n"); - break; - } - current = malloc(size); - if (!current) { - printf("Out of core\n"); - break; - } - - if (get_current_configuration_for(cookie, current, size) != B_OK) { - printf("Error getting the current configuration\n"); - break; - } - - size = get_size_of_possible_configurations_for(cookie); - if (size < B_OK) { - printf("Error getting the size of the possible configurations\n"); - break; - } - possible = malloc(size); - if (!possible) { - printf("Out of core\n"); - break; - } - - if (get_possible_configurations_for(cookie, possible, size) != B_OK) { - printf("Error getting the possible configurations\n"); - break; - } - - switch (info->bus) { - case B_ISA_BUS : printf("ISA"); break; - case B_PCI_BUS : printf("PCI"); break; - default : printf("unknown"); break; - } - printf(" bus, device #%d: ", index++); - - dump_device_info(info, current, possible); - if (f) { - printf("Bus-dependent information:\n"); - (*f)(info); - } - printf("\n"); - - free(possible); - free(current); - free(info); - } } int main() { status_t error; + uint32 root; - if ((error = init_cm_wrapper()) < 0) { - printf("Error initializing configuration manager (%s)\n", strerror(error)); + if ((error = init_dm_wrapper()) < 0) { + printf("Error initializing device manager (%s)\n", strerror(error)); return error; } - dump_devices_for_bus(B_ISA_BUS, dump_isa_info); - dump_devices_for_bus(B_PCI_BUS, dump_pci_info); + get_root(&root); + dump_nodes(&root, 0); - uninit_cm_wrapper(); + uninit_dm_wrapper(); return 0; } diff --git a/src/system/kernel/device_manager/device_manager.c b/src/system/kernel/device_manager/device_manager.c index 3567e4595d..8f817d00eb 100644 --- a/src/system/kernel/device_manager/device_manager.c +++ b/src/system/kernel/device_manager/device_manager.c @@ -14,6 +14,7 @@ #include "device_manager_private.h" #include +#include #include #include @@ -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; } diff --git a/src/system/kernel/device_manager/device_manager_private.h b/src/system/kernel/device_manager/device_manager_private.h index 6ddf8a6a18..845438aeb0 100644 --- a/src/system/kernel/device_manager/device_manager_private.h +++ b/src/system/kernel/device_manager/device_manager_private.h @@ -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 diff --git a/src/system/kernel/device_manager/nodes.c b/src/system/kernel/device_manager/nodes.c index 309fc7e7fd..a286cc8e07 100644 --- a/src/system/kernel/device_manager/nodes.c +++ b/src/system/kernel/device_manager/nodes.c @@ -24,6 +24,8 @@ #include "device_manager_private.h" #include "dl_list.h" +#include + #include #include @@ -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; +}