xref: /haiku/src/add-ons/kernel/bus_managers/random/driver.cpp (revision 637d99977c22c39134c5c6e38314682196941a1c)
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 	mutex_init(&sRandomLock, "/dev/random lock");
52 	return B_OK;
53 }
54 
55 
56 static void
57 random_uninit_device(void* _cookie)
58 {
59 	mutex_destroy(&sRandomLock);
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 	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 	random_driver_info* info = (random_driver_info*)_cookie;
203 	free(info);
204 }
205 
206 
207 static status_t
208 random_register_child_devices(void* _cookie)
209 {
210 	CALLED();
211 	random_driver_info* info = (random_driver_info*)_cookie;
212 	status_t status = gDeviceManager->publish_device(info->node, "random",
213 		RANDOM_DEVICE_MODULE_NAME);
214 	if (status == B_OK) {
215 		gDeviceManager->publish_device(info->node, "urandom",
216 			RANDOM_DEVICE_MODULE_NAME);
217 	}
218 
219 	// add the default Yarrow RNG
220 	device_attr attrs[] = {
221 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
222 			{ string: "Yarrow RNG" }},
223 		{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
224 			{ string: RANDOM_FOR_CONTROLLER_MODULE_NAME }},
225 		{ NULL }
226 	};
227 
228 	device_node* node;
229 	return gDeviceManager->register_node(info->node,
230 		YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node);
231 }
232 
233 
234 //	#pragma mark -
235 
236 
237 status_t
238 random_added_device(device_node *node)
239 {
240 	CALLED();
241 
242 	status_t status = gDeviceManager->get_driver(node,
243 		(driver_module_info **)&sRandomModule, &sRandomCookie);
244 
245 	return status;
246 }
247 
248 
249 
250 //	#pragma mark -
251 
252 
253 module_dependency module_dependencies[] = {
254 	{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
255 	{}
256 };
257 
258 
259 struct device_module_info sRandomDevice = {
260 	{
261 		RANDOM_DEVICE_MODULE_NAME,
262 		0,
263 		NULL
264 	},
265 
266 	random_init_device,
267 	random_uninit_device,
268 	NULL, // remove,
269 
270 	random_open,
271 	random_close,
272 	random_free,
273 	random_read,
274 	random_write,
275 	NULL,
276 	random_control,
277 
278 	random_select,
279 	random_deselect,
280 };
281 
282 
283 struct driver_module_info sRandomDriver = {
284 	{
285 		RANDOM_DRIVER_MODULE_NAME,
286 		0,
287 		NULL
288 	},
289 
290 	random_supports_device,
291 	random_register_device,
292 	random_init_driver,
293 	random_uninit_driver,
294 	random_register_child_devices,
295 	NULL,	// rescan
296 	NULL,	// removed
297 };
298 
299 
300 random_for_controller_interface sRandomForControllerModule = {
301 	{
302 		{
303 			RANDOM_FOR_CONTROLLER_MODULE_NAME,
304 			0,
305 			NULL
306 		},
307 
308 		NULL, // supported devices
309 		random_added_device,
310 		NULL,
311 		NULL,
312 		NULL
313 	}
314 };
315 
316 
317 module_info* modules[] = {
318 	(module_info*)&sRandomDriver,
319 	(module_info*)&sRandomDevice,
320 	(module_info*)&sRandomForControllerModule,
321 	(module_info*)&gYarrowRandomModule,
322 	NULL
323 };
324