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