xref: /haiku/src/add-ons/kernel/bus_managers/random/driver.cpp (revision cf70d345b2a6a2612f32868fe5b81698f3282434)
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 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
126 		notify_select_event(sync, ref);
127 #else
128 		notify_select_event(sync, event);
129 #endif
130 	} else if (event == B_SELECT_WRITE) {
131 		/* we're now writable */
132 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
133 		notify_select_event(sync, ref);
134 #else
135 		notify_select_event(sync, event);
136 #endif
137 	}
138 	return B_OK;
139 }
140 
141 
142 static status_t
143 random_deselect(void *cookie, uint8 event, selectsync *sync)
144 {
145 	TRACE("deselect()\n");
146 	return B_OK;
147 }
148 
149 
150 //	#pragma mark - driver module API
151 
152 
153 static float
154 random_supports_device(device_node *parent)
155 {
156 	CALLED();
157 	const char *bus;
158 
159 	// make sure parent is really device root
160 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
161 		return -1;
162 
163 	if (strcmp(bus, "root"))
164 		return 0.0;
165 
166 	return 1.0;
167 }
168 
169 
170 static status_t
171 random_register_device(device_node *node)
172 {
173 	CALLED();
174 
175 	// ready to register
176 	device_attr attrs[] = {
177 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "Random" }},
178 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }},
179 		{ NULL }
180 	};
181 
182 	return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME,
183 		attrs, NULL, NULL);
184 }
185 
186 
187 static status_t
188 random_init_driver(device_node *node, void **cookie)
189 {
190 	CALLED();
191 
192 	random_driver_info* info = (random_driver_info*)malloc(
193 		sizeof(random_driver_info));
194 	if (info == NULL)
195 		return B_NO_MEMORY;
196 
197 	memset(info, 0, sizeof(*info));
198 
199 	info->node = node;
200 
201 	*cookie = info;
202 	return B_OK;
203 }
204 
205 
206 static void
207 random_uninit_driver(void *_cookie)
208 {
209 	CALLED();
210 	random_driver_info* info = (random_driver_info*)_cookie;
211 	free(info);
212 }
213 
214 
215 static status_t
216 random_register_child_devices(void* _cookie)
217 {
218 	CALLED();
219 	random_driver_info* info = (random_driver_info*)_cookie;
220 	status_t status = gDeviceManager->publish_device(info->node, "random",
221 		RANDOM_DEVICE_MODULE_NAME);
222 	if (status == B_OK) {
223 		gDeviceManager->publish_device(info->node, "urandom",
224 			RANDOM_DEVICE_MODULE_NAME);
225 	}
226 
227 	// add the default Yarrow RNG
228 	device_attr attrs[] = {
229 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
230 			{ string: "Yarrow RNG" }},
231 		{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
232 			{ string: RANDOM_FOR_CONTROLLER_MODULE_NAME }},
233 		{ NULL }
234 	};
235 
236 	device_node* node;
237 	return gDeviceManager->register_node(info->node,
238 		YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node);
239 
240 	return status;
241 }
242 
243 
244 //	#pragma mark -
245 
246 
247 status_t
248 random_added_device(device_node *node)
249 {
250 	CALLED();
251 
252 	status_t status = gDeviceManager->get_driver(node,
253 		(driver_module_info **)&sRandomModule, &sRandomCookie);
254 
255 	return status;
256 }
257 
258 
259 
260 //	#pragma mark -
261 
262 
263 module_dependency module_dependencies[] = {
264 	{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
265 	{}
266 };
267 
268 
269 struct device_module_info sRandomDevice = {
270 	{
271 		RANDOM_DEVICE_MODULE_NAME,
272 		0,
273 		NULL
274 	},
275 
276 	random_init_device,
277 	random_uninit_device,
278 	NULL, // remove,
279 
280 	random_open,
281 	random_close,
282 	random_free,
283 	random_read,
284 	random_write,
285 	NULL,
286 	random_control,
287 
288 	random_select,
289 	random_deselect,
290 };
291 
292 
293 struct driver_module_info sRandomDriver = {
294 	{
295 		RANDOM_DRIVER_MODULE_NAME,
296 		0,
297 		NULL
298 	},
299 
300 	random_supports_device,
301 	random_register_device,
302 	random_init_driver,
303 	random_uninit_driver,
304 	random_register_child_devices,
305 	NULL,	// rescan
306 	NULL,	// removed
307 };
308 
309 
310 random_for_controller_interface sRandomForControllerModule = {
311 	{
312 		{
313 			RANDOM_FOR_CONTROLLER_MODULE_NAME,
314 			0,
315 			NULL
316 		},
317 
318 		NULL, // supported devices
319 		random_added_device,
320 		NULL,
321 		NULL,
322 		NULL
323 	}
324 };
325 
326 
327 module_info* modules[] = {
328 	(module_info*)&sRandomDriver,
329 	(module_info*)&sRandomDevice,
330 	(module_info*)&sRandomForControllerModule,
331 	(module_info*)&gYarrowRandomModule,
332 	NULL
333 };
334