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 <malloc.h> 17 #include <string.h> 18 #include <util/AutoLock.h> 19 20 #include "yarrow_rng.h" 21 22 23 //#define TRACE_DRIVER 24 #ifdef TRACE_DRIVER 25 # define TRACE(x...) dprintf("random: " x) 26 #else 27 # define TRACE(x...) ; 28 #endif 29 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 30 31 32 #define RANDOM_DRIVER_MODULE_NAME "bus_managers/random/driver_v1" 33 #define RANDOM_DEVICE_MODULE_NAME "bus_managers/random/device_v1" 34 35 36 static mutex sRandomLock; 37 static random_module_info *sRandomModule; 38 static void *sRandomCookie; 39 device_manager_info* gDeviceManager; 40 41 42 typedef struct { 43 device_node* node; 44 } random_driver_info; 45 46 47 // #pragma mark - device module API 48 49 50 static status_t 51 random_init_device(void* _info, void** _cookie) 52 { 53 return B_OK; 54 } 55 56 57 static void 58 random_uninit_device(void* _cookie) 59 { 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 mutex_init(&sRandomLock, "/dev/random lock"); 190 191 memset(info, 0, sizeof(*info)); 192 193 info->node = node; 194 195 *cookie = info; 196 return B_OK; 197 } 198 199 200 static void 201 random_uninit_driver(void *_cookie) 202 { 203 CALLED(); 204 205 mutex_destroy(&sRandomLock); 206 207 random_driver_info* info = (random_driver_info*)_cookie; 208 free(info); 209 } 210 211 212 static status_t 213 random_register_child_devices(void* _cookie) 214 { 215 CALLED(); 216 random_driver_info* info = (random_driver_info*)_cookie; 217 status_t status = gDeviceManager->publish_device(info->node, "random", 218 RANDOM_DEVICE_MODULE_NAME); 219 if (status == B_OK) { 220 gDeviceManager->publish_device(info->node, "urandom", 221 RANDOM_DEVICE_MODULE_NAME); 222 } 223 224 // add the default Yarrow RNG 225 device_attr attrs[] = { 226 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 227 { string: "Yarrow RNG" }}, 228 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 229 { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, 230 { NULL } 231 }; 232 233 device_node* node; 234 return gDeviceManager->register_node(info->node, 235 YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node); 236 } 237 238 239 // #pragma mark - 240 241 242 status_t 243 random_added_device(device_node *node) 244 { 245 CALLED(); 246 247 status_t status = gDeviceManager->get_driver(node, 248 (driver_module_info **)&sRandomModule, &sRandomCookie); 249 250 return status; 251 } 252 253 254 255 // #pragma mark - 256 257 258 module_dependency module_dependencies[] = { 259 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 260 {} 261 }; 262 263 264 struct device_module_info sRandomDevice = { 265 { 266 RANDOM_DEVICE_MODULE_NAME, 267 0, 268 NULL 269 }, 270 271 random_init_device, 272 random_uninit_device, 273 NULL, // remove, 274 275 random_open, 276 random_close, 277 random_free, 278 random_read, 279 random_write, 280 NULL, 281 random_control, 282 283 random_select, 284 random_deselect, 285 }; 286 287 288 struct driver_module_info sRandomDriver = { 289 { 290 RANDOM_DRIVER_MODULE_NAME, 291 0, 292 NULL 293 }, 294 295 random_supports_device, 296 random_register_device, 297 random_init_driver, 298 random_uninit_driver, 299 random_register_child_devices, 300 NULL, // rescan 301 NULL, // removed 302 }; 303 304 305 random_for_controller_interface sRandomForControllerModule = { 306 { 307 { 308 RANDOM_FOR_CONTROLLER_MODULE_NAME, 309 0, 310 NULL 311 }, 312 313 NULL, // supported devices 314 random_added_device, 315 NULL, 316 NULL, 317 NULL 318 } 319 }; 320 321 322 module_info* modules[] = { 323 (module_info*)&sRandomDriver, 324 (module_info*)&sRandomDevice, 325 (module_info*)&sRandomForControllerModule, 326 (module_info*)&gYarrowRandomModule, 327 NULL 328 }; 329