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