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 26 int32 api_version = B_CUR_DRIVER_API_VERSION; 27 28 device_manager_info *gDeviceManager; 29 30 typedef 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 39 static status_t 40 config_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 53 static status_t 54 config_close(void *cookie) 55 { 56 return B_OK; 57 } 58 59 60 static status_t 61 config_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 71 static status_t 72 config_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 157 static status_t 158 config_read(void * cookie, off_t pos, void *buf, size_t *_length) 159 { 160 *_length = 0; 161 return B_OK; 162 } 163 164 165 static status_t 166 config_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 177 status_t 178 init_hardware() 179 { 180 return B_OK; 181 } 182 183 184 const char ** 185 publish_devices(void) 186 { 187 static const char *devices[] = { 188 DEVICE_NAME, 189 NULL 190 }; 191 192 return devices; 193 } 194 195 196 device_hooks * 197 find_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 222 status_t 223 init_driver() 224 { 225 return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager); 226 } 227 228 229 void 230 uninit_driver() 231 { 232 if (gDeviceManager != NULL) 233 put_module(B_DEVICE_MANAGER_MODULE_NAME); 234 } 235 236