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