1/* config driver 2 * provides userland access to the device manager 3 * 4 * Copyright 2002-2004, Axel Doerfler. All rights reserved. 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors : Axel Doerfler, Jerome Duval 8 */ 9 10 11#include <Drivers.h> 12#include <drivers/device_manager.h> 13#include <stdlib.h> 14#include <string.h> 15 16#include "config_driver.h" 17 18#ifdef DEBUG 19#define TRACE(x...) dprintf(x) 20#else 21#define TRACE(x...) 22#endif 23 24#define DEVICE_NAME "misc/config" 25 26int32 api_version = B_CUR_DRIVER_API_VERSION; 27 28device_manager_info *gDeviceManager; 29 30typedef struct _driver_cookie { 31 device_node_handle parent; 32 device_node_handle child; 33 device_attr_handle attr; 34} driver_cookie; 35 36// Device interface 37 38 39static status_t 40config_open(const char *name, uint32 flags, void **_cookie) 41{ 42 driver_cookie *cookie = malloc(sizeof(driver_cookie)); 43 if (cookie == NULL) 44 return B_ERROR; 45 *_cookie = cookie; 46 cookie->child = gDeviceManager->get_root(); 47 cookie->parent = NULL; 48 cookie->attr = NULL; 49 return B_OK; 50} 51 52 53static status_t 54config_close(void *cookie) 55{ 56 return B_OK; 57} 58 59 60static status_t 61config_free_cookie(void *cookie) 62{ 63 driver_cookie *cook = (driver_cookie *)cookie; 64 gDeviceManager->put_device_node(cook->child); 65 if (cook->parent) 66 gDeviceManager->put_device_node(cook->parent); 67 return B_OK; 68} 69 70 71static status_t 72config_ioctl(void *cookie, uint32 op, void *buffer, size_t len) 73{ 74 driver_cookie *cook = (driver_cookie *)cookie; 75 device_node_handle child = NULL; 76 const device_attr *attr = NULL; 77 78 struct dm_ioctl_data *params = (struct dm_ioctl_data *)buffer; 79 status_t err = B_OK; 80 81 // simple check for validity of the argument 82 if (params == NULL || params->magic != op) 83 return B_BAD_VALUE; 84 85 switch (op) { 86 case DM_GET_CHILD: 87 TRACE("DM_GET_CHILD parent %p child %p\n", cook->parent, cook->child); 88 if (cook->attr) { 89 gDeviceManager->release_attr(cook->child, cook->attr); 90 cook->attr = NULL; 91 } 92 err = gDeviceManager->get_next_child_device(cook->child, &child, NULL); 93 if (err == B_OK) { 94 if (cook->parent) 95 gDeviceManager->put_device_node(cook->parent); 96 cook->parent = cook->child; 97 cook->child = child; 98 } 99 return err; 100 case DM_GET_NEXT_CHILD: 101 TRACE("DM_GET_NEXT_CHILD parent %p child %p\n", cook->parent, cook->child); 102 if (!cook->parent) 103 return B_ENTRY_NOT_FOUND; 104 if (cook->attr) { 105 gDeviceManager->release_attr(cook->child, cook->attr); 106 cook->attr = NULL; 107 } 108 return gDeviceManager->get_next_child_device(cook->parent, &cook->child, NULL); 109 case DM_GET_PARENT: 110 TRACE("DM_GET_PARENT parent %p child %p\n", cook->parent, cook->child); 111 if (!cook->parent) 112 return B_ENTRY_NOT_FOUND; 113 if (cook->attr) { 114 gDeviceManager->release_attr(cook->child, cook->attr); 115 cook->attr = NULL; 116 } 117 if (cook->child) 118 gDeviceManager->put_device_node(cook->child); 119 cook->child = cook->parent; 120 cook->parent = gDeviceManager->get_parent(cook->child); 121 return B_OK; 122 case DM_GET_NEXT_ATTRIBUTE: 123 TRACE("DM_NEXT_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr); 124 return gDeviceManager->get_next_attr(cook->child, &cook->attr); 125 case DM_RETRIEVE_ATTRIBUTE: 126 TRACE("DM_RETRIEVE_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr); 127 err = gDeviceManager->retrieve_attr(cook->attr, &attr); 128 if (err == B_OK) { 129 strlcpy(params->attr->name, attr->name, 254); 130 params->attr->type = attr->type; 131 switch (attr->type) { 132 case B_UINT8_TYPE: 133 params->attr->value.ui8 = attr->value.ui8; break; 134 case B_UINT16_TYPE: 135 params->attr->value.ui16 = attr->value.ui16; break; 136 case B_UINT32_TYPE: 137 params->attr->value.ui32 = attr->value.ui32; break; 138 case B_UINT64_TYPE: 139 params->attr->value.ui64 = attr->value.ui64; break; 140 case B_STRING_TYPE: 141 strlcpy(params->attr->value.string, attr->value.string, 254); break; 142 case B_RAW_TYPE: 143 if (params->attr->value.raw.length > attr->value.raw.length) 144 params->attr->value.raw.length = attr->value.raw.length; 145 memcpy(params->attr->value.raw.data, attr->value.raw.data, 146 params->attr->value.raw.length); 147 break; 148 } 149 } 150 return err; 151 } 152 153 return B_BAD_VALUE; 154} 155 156 157static status_t 158config_read(void * cookie, off_t pos, void *buf, size_t *_length) 159{ 160 *_length = 0; 161 return B_OK; 162} 163 164 165static status_t 166config_write(void * cookie, off_t pos, const void *buf, size_t *_length) 167{ 168 *_length = 0; 169 return B_OK; 170} 171 172 173// #pragma mark - 174// Driver interface 175 176 177status_t 178init_hardware() 179{ 180 return B_OK; 181} 182 183 184const char ** 185publish_devices(void) 186{ 187 static const char *devices[] = { 188 DEVICE_NAME, 189 NULL 190 }; 191 192 return devices; 193} 194 195 196device_hooks * 197find_device(const char *name) 198{ 199 static device_hooks hooks = { 200 &config_open, 201 &config_close, 202 &config_free_cookie, 203 &config_ioctl, 204 &config_read, 205 &config_write, 206 /* Leave select/deselect/readv/writev undefined. The kernel will 207 * use its own default implementation. The basic hooks above this 208 * line MUST be defined, however. */ 209 NULL, 210 NULL, 211 NULL, 212 NULL 213 }; 214 215 if (!strcmp(name, DEVICE_NAME)) 216 return &hooks; 217 218 return NULL; 219} 220 221 222status_t 223init_driver() 224{ 225 return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager); 226} 227 228 229void 230uninit_driver() 231{ 232 if (gDeviceManager != NULL) 233 put_module(B_DEVICE_MANAGER_MODULE_NAME); 234} 235 236