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 void *sRandomCookie; 38 device_manager_info* gDeviceManager; 39 40 41 typedef struct { 42 device_node* node; 43 } random_driver_info; 44 45 46 static status_t 47 random_queue_randomness(uint64 value) 48 { 49 MutexLocker locker(&sRandomLock); 50 RANDOM_ENQUEUE(value); 51 return B_OK; 52 } 53 54 55 // #pragma mark - device module API 56 57 58 static status_t 59 random_init_device(void* _info, void** _cookie) 60 { 61 return B_OK; 62 } 63 64 65 static void 66 random_uninit_device(void* _cookie) 67 { 68 } 69 70 71 static status_t 72 random_open(void *deviceCookie, const char *name, int flags, void **cookie) 73 { 74 TRACE("open(\"%s\")\n", name); 75 return B_OK; 76 } 77 78 79 static status_t 80 random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) 81 { 82 TRACE("read(%Ld,, %ld)\n", position, *_numBytes); 83 84 MutexLocker locker(&sRandomLock); 85 return RANDOM_READ(sRandomCookie, _buffer, _numBytes); 86 } 87 88 89 static status_t 90 random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes) 91 { 92 TRACE("write(%Ld,, %ld)\n", position, *_numBytes); 93 MutexLocker locker(&sRandomLock); 94 return RANDOM_WRITE(sRandomCookie, buffer, _numBytes); 95 } 96 97 98 static status_t 99 random_control(void *cookie, uint32 op, void *arg, size_t length) 100 { 101 TRACE("ioctl(%ld)\n", op); 102 return B_ERROR; 103 } 104 105 106 static status_t 107 random_close(void *cookie) 108 { 109 TRACE("close()\n"); 110 return B_OK; 111 } 112 113 114 static status_t 115 random_free(void *cookie) 116 { 117 TRACE("free()\n"); 118 return B_OK; 119 } 120 121 122 static status_t 123 random_select(void *cookie, uint8 event, selectsync *sync) 124 { 125 TRACE("select()\n"); 126 127 if (event == B_SELECT_READ) { 128 /* tell there is already data to read */ 129 notify_select_event(sync, event); 130 } else if (event == B_SELECT_WRITE) { 131 /* we're now writable */ 132 notify_select_event(sync, event); 133 } 134 return B_OK; 135 } 136 137 138 static status_t 139 random_deselect(void *cookie, uint8 event, selectsync *sync) 140 { 141 TRACE("deselect()\n"); 142 return B_OK; 143 } 144 145 146 // #pragma mark - driver module API 147 148 149 static float 150 random_supports_device(device_node *parent) 151 { 152 CALLED(); 153 const char *bus; 154 155 // make sure parent is really device root 156 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 157 return -1; 158 159 if (strcmp(bus, "root")) 160 return 0.0; 161 162 return 1.0; 163 } 164 165 166 static status_t 167 random_register_device(device_node *node) 168 { 169 CALLED(); 170 171 // ready to register 172 device_attr attrs[] = { 173 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "Random" }}, 174 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_KEEP_DRIVER_LOADED }}, 175 { NULL } 176 }; 177 178 return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME, 179 attrs, NULL, NULL); 180 } 181 182 183 static status_t 184 random_init_driver(device_node *node, void **cookie) 185 { 186 CALLED(); 187 188 random_driver_info* info = (random_driver_info*)malloc( 189 sizeof(random_driver_info)); 190 if (info == NULL) 191 return B_NO_MEMORY; 192 193 mutex_init(&sRandomLock, "/dev/random lock"); 194 RANDOM_INIT(); 195 196 memset(info, 0, sizeof(*info)); 197 198 info->node = node; 199 200 *cookie = info; 201 return B_OK; 202 } 203 204 205 static void 206 random_uninit_driver(void *_cookie) 207 { 208 CALLED(); 209 210 RANDOM_UNINIT(); 211 212 mutex_destroy(&sRandomLock); 213 214 random_driver_info* info = (random_driver_info*)_cookie; 215 free(info); 216 } 217 218 219 static status_t 220 random_register_child_devices(void* _cookie) 221 { 222 CALLED(); 223 random_driver_info* info = (random_driver_info*)_cookie; 224 status_t status = gDeviceManager->publish_device(info->node, "random", 225 RANDOM_DEVICE_MODULE_NAME); 226 if (status == B_OK) { 227 gDeviceManager->publish_device(info->node, "urandom", 228 RANDOM_DEVICE_MODULE_NAME); 229 } 230 return status; 231 } 232 233 234 // #pragma mark - 235 236 237 module_dependency module_dependencies[] = { 238 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 239 {} 240 }; 241 242 243 struct device_module_info sRandomDevice = { 244 { 245 RANDOM_DEVICE_MODULE_NAME, 246 0, 247 NULL 248 }, 249 250 random_init_device, 251 random_uninit_device, 252 NULL, // remove, 253 254 random_open, 255 random_close, 256 random_free, 257 random_read, 258 random_write, 259 NULL, 260 random_control, 261 262 random_select, 263 random_deselect, 264 }; 265 266 267 struct driver_module_info sRandomDriver = { 268 { 269 RANDOM_DRIVER_MODULE_NAME, 270 0, 271 NULL 272 }, 273 274 random_supports_device, 275 random_register_device, 276 random_init_driver, 277 random_uninit_driver, 278 random_register_child_devices, 279 NULL, // rescan 280 NULL, // removed 281 }; 282 283 284 random_for_controller_interface sRandomForControllerModule = { 285 { 286 { 287 RANDOM_FOR_CONTROLLER_MODULE_NAME, 288 0, 289 NULL 290 }, 291 292 NULL, // supported devices 293 NULL, 294 NULL, 295 NULL, 296 NULL 297 }, 298 299 random_queue_randomness, 300 }; 301 302 303 module_info* modules[] = { 304 (module_info*)&sRandomDriver, 305 (module_info*)&sRandomDevice, 306 (module_info*)&sRandomForControllerModule, 307 NULL 308 }; 309