1 /* 2 * Copyright 2002-2013, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval, korli@berlios.de 7 * Axel Dörfler, axeld@pinc-software.de 8 * David Reid 9 */ 10 11 12 #include <stdio.h> 13 14 #include <device_manager.h> 15 #include <Drivers.h> 16 #include <util/AutoLock.h> 17 18 #include "yarrow_rng.h" 19 20 21 //#define TRACE_DRIVER 22 #ifdef TRACE_DRIVER 23 # define TRACE(x...) dprintf("random: " x) 24 #else 25 # define TRACE(x...) ; 26 #endif 27 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 28 29 30 #define RANDOM_DRIVER_MODULE_NAME "bus_managers/random/driver_v1" 31 #define RANDOM_DEVICE_MODULE_NAME "bus_managers/random/device_v1" 32 33 34 static mutex sRandomLock; 35 static random_module_info *sRandomModule; 36 static void *sRandomCookie; 37 device_manager_info* gDeviceManager; 38 39 40 typedef struct { 41 device_node* node; 42 } random_driver_info; 43 44 45 // #pragma mark - device module API 46 47 48 static status_t 49 random_init_device(void* _info, void** _cookie) 50 { 51 mutex_init(&sRandomLock, "/dev/random lock"); 52 return B_OK; 53 } 54 55 56 static void 57 random_uninit_device(void* _cookie) 58 { 59 mutex_destroy(&sRandomLock); 60 } 61 62 63 static status_t 64 random_open(void *deviceCookie, const char *name, int flags, void **cookie) 65 { 66 TRACE("open(\"%s\")\n", name); 67 return B_OK; 68 } 69 70 71 static status_t 72 random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) 73 { 74 TRACE("read(%Ld,, %ld)\n", position, *_numBytes); 75 76 MutexLocker locker(&sRandomLock); 77 return sRandomModule->read(sRandomCookie, _buffer, _numBytes); 78 } 79 80 81 static status_t 82 random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes) 83 { 84 TRACE("write(%Ld,, %ld)\n", position, *_numBytes); 85 MutexLocker locker(&sRandomLock); 86 if (sRandomModule->write == NULL) { 87 *_numBytes = 0; 88 return EINVAL; 89 } 90 return sRandomModule->write(sRandomCookie, buffer, _numBytes); 91 } 92 93 94 static status_t 95 random_control(void *cookie, uint32 op, void *arg, size_t length) 96 { 97 TRACE("ioctl(%ld)\n", op); 98 return B_ERROR; 99 } 100 101 102 static status_t 103 random_close(void *cookie) 104 { 105 TRACE("close()\n"); 106 return B_OK; 107 } 108 109 110 static status_t 111 random_free(void *cookie) 112 { 113 TRACE("free()\n"); 114 return B_OK; 115 } 116 117 118 static status_t 119 random_select(void *cookie, uint8 event, selectsync *sync) 120 { 121 TRACE("select()\n"); 122 123 if (event == B_SELECT_READ) { 124 /* tell there is already data to read */ 125 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 126 notify_select_event(sync, ref); 127 #else 128 notify_select_event(sync, event); 129 #endif 130 } else if (event == B_SELECT_WRITE) { 131 /* we're now writable */ 132 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 133 notify_select_event(sync, ref); 134 #else 135 notify_select_event(sync, event); 136 #endif 137 } 138 return B_OK; 139 } 140 141 142 static status_t 143 random_deselect(void *cookie, uint8 event, selectsync *sync) 144 { 145 TRACE("deselect()\n"); 146 return B_OK; 147 } 148 149 150 // #pragma mark - driver module API 151 152 153 static float 154 random_supports_device(device_node *parent) 155 { 156 CALLED(); 157 const char *bus; 158 159 // make sure parent is really device root 160 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 161 return -1; 162 163 if (strcmp(bus, "root")) 164 return 0.0; 165 166 return 1.0; 167 } 168 169 170 static status_t 171 random_register_device(device_node *node) 172 { 173 CALLED(); 174 175 // ready to register 176 device_attr attrs[] = { 177 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "Random" }}, 178 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }}, 179 { NULL } 180 }; 181 182 return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME, 183 attrs, NULL, NULL); 184 } 185 186 187 static status_t 188 random_init_driver(device_node *node, void **cookie) 189 { 190 CALLED(); 191 192 random_driver_info* info = (random_driver_info*)malloc( 193 sizeof(random_driver_info)); 194 if (info == NULL) 195 return B_NO_MEMORY; 196 197 memset(info, 0, sizeof(*info)); 198 199 info->node = node; 200 201 *cookie = info; 202 return B_OK; 203 } 204 205 206 static void 207 random_uninit_driver(void *_cookie) 208 { 209 CALLED(); 210 random_driver_info* info = (random_driver_info*)_cookie; 211 free(info); 212 } 213 214 215 static status_t 216 random_register_child_devices(void* _cookie) 217 { 218 CALLED(); 219 random_driver_info* info = (random_driver_info*)_cookie; 220 status_t status = gDeviceManager->publish_device(info->node, "random", 221 RANDOM_DEVICE_MODULE_NAME); 222 if (status == B_OK) { 223 gDeviceManager->publish_device(info->node, "urandom", 224 RANDOM_DEVICE_MODULE_NAME); 225 } 226 227 // add the default Yarrow RNG 228 device_attr attrs[] = { 229 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 230 { string: "Yarrow RNG" }}, 231 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 232 { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, 233 { NULL } 234 }; 235 236 device_node* node; 237 return gDeviceManager->register_node(info->node, 238 YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node); 239 240 return status; 241 } 242 243 244 // #pragma mark - 245 246 247 status_t 248 random_added_device(device_node *node) 249 { 250 CALLED(); 251 252 status_t status = gDeviceManager->get_driver(node, 253 (driver_module_info **)&sRandomModule, &sRandomCookie); 254 255 return status; 256 } 257 258 259 260 // #pragma mark - 261 262 263 module_dependency module_dependencies[] = { 264 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 265 {} 266 }; 267 268 269 struct device_module_info sRandomDevice = { 270 { 271 RANDOM_DEVICE_MODULE_NAME, 272 0, 273 NULL 274 }, 275 276 random_init_device, 277 random_uninit_device, 278 NULL, // remove, 279 280 random_open, 281 random_close, 282 random_free, 283 random_read, 284 random_write, 285 NULL, 286 random_control, 287 288 random_select, 289 random_deselect, 290 }; 291 292 293 struct driver_module_info sRandomDriver = { 294 { 295 RANDOM_DRIVER_MODULE_NAME, 296 0, 297 NULL 298 }, 299 300 random_supports_device, 301 random_register_device, 302 random_init_driver, 303 random_uninit_driver, 304 random_register_child_devices, 305 NULL, // rescan 306 NULL, // removed 307 }; 308 309 310 random_for_controller_interface sRandomForControllerModule = { 311 { 312 { 313 RANDOM_FOR_CONTROLLER_MODULE_NAME, 314 0, 315 NULL 316 }, 317 318 NULL, // supported devices 319 random_added_device, 320 NULL, 321 NULL, 322 NULL 323 } 324 }; 325 326 327 module_info* modules[] = { 328 (module_info*)&sRandomDriver, 329 (module_info*)&sRandomDevice, 330 (module_info*)&sRandomForControllerModule, 331 (module_info*)&gYarrowRandomModule, 332 NULL 333 }; 334