xref: /haiku/src/add-ons/kernel/bus_managers/random/driver.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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