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