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 notify_select_event(sync, event); 126 } else if (event == B_SELECT_WRITE) { 127 /* we're now writable */ 128 notify_select_event(sync, event); 129 } 130 return B_OK; 131 } 132 133 134 static status_t 135 random_deselect(void *cookie, uint8 event, selectsync *sync) 136 { 137 TRACE("deselect()\n"); 138 return B_OK; 139 } 140 141 142 // #pragma mark - driver module API 143 144 145 static float 146 random_supports_device(device_node *parent) 147 { 148 CALLED(); 149 const char *bus; 150 151 // make sure parent is really device root 152 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 153 return -1; 154 155 if (strcmp(bus, "root")) 156 return 0.0; 157 158 return 1.0; 159 } 160 161 162 static status_t 163 random_register_device(device_node *node) 164 { 165 CALLED(); 166 167 // ready to register 168 device_attr attrs[] = { 169 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "Random" }}, 170 { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }}, 171 { NULL } 172 }; 173 174 return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME, 175 attrs, NULL, NULL); 176 } 177 178 179 static status_t 180 random_init_driver(device_node *node, void **cookie) 181 { 182 CALLED(); 183 184 random_driver_info* info = (random_driver_info*)malloc( 185 sizeof(random_driver_info)); 186 if (info == NULL) 187 return B_NO_MEMORY; 188 189 memset(info, 0, sizeof(*info)); 190 191 info->node = node; 192 193 *cookie = info; 194 return B_OK; 195 } 196 197 198 static void 199 random_uninit_driver(void *_cookie) 200 { 201 CALLED(); 202 random_driver_info* info = (random_driver_info*)_cookie; 203 free(info); 204 } 205 206 207 static status_t 208 random_register_child_devices(void* _cookie) 209 { 210 CALLED(); 211 random_driver_info* info = (random_driver_info*)_cookie; 212 status_t status = gDeviceManager->publish_device(info->node, "random", 213 RANDOM_DEVICE_MODULE_NAME); 214 if (status == B_OK) { 215 gDeviceManager->publish_device(info->node, "urandom", 216 RANDOM_DEVICE_MODULE_NAME); 217 } 218 219 // add the default Yarrow RNG 220 device_attr attrs[] = { 221 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 222 { string: "Yarrow RNG" }}, 223 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 224 { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, 225 { NULL } 226 }; 227 228 device_node* node; 229 return gDeviceManager->register_node(info->node, 230 YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node); 231 } 232 233 234 // #pragma mark - 235 236 237 status_t 238 random_added_device(device_node *node) 239 { 240 CALLED(); 241 242 status_t status = gDeviceManager->get_driver(node, 243 (driver_module_info **)&sRandomModule, &sRandomCookie); 244 245 return status; 246 } 247 248 249 250 // #pragma mark - 251 252 253 module_dependency module_dependencies[] = { 254 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 255 {} 256 }; 257 258 259 struct device_module_info sRandomDevice = { 260 { 261 RANDOM_DEVICE_MODULE_NAME, 262 0, 263 NULL 264 }, 265 266 random_init_device, 267 random_uninit_device, 268 NULL, // remove, 269 270 random_open, 271 random_close, 272 random_free, 273 random_read, 274 random_write, 275 NULL, 276 random_control, 277 278 random_select, 279 random_deselect, 280 }; 281 282 283 struct driver_module_info sRandomDriver = { 284 { 285 RANDOM_DRIVER_MODULE_NAME, 286 0, 287 NULL 288 }, 289 290 random_supports_device, 291 random_register_device, 292 random_init_driver, 293 random_uninit_driver, 294 random_register_child_devices, 295 NULL, // rescan 296 NULL, // removed 297 }; 298 299 300 random_for_controller_interface sRandomForControllerModule = { 301 { 302 { 303 RANDOM_FOR_CONTROLLER_MODULE_NAME, 304 0, 305 NULL 306 }, 307 308 NULL, // supported devices 309 random_added_device, 310 NULL, 311 NULL, 312 NULL 313 } 314 }; 315 316 317 module_info* modules[] = { 318 (module_info*)&sRandomDriver, 319 (module_info*)&sRandomDevice, 320 (module_info*)&sRandomForControllerModule, 321 (module_info*)&gYarrowRandomModule, 322 NULL 323 }; 324