xref: /haiku/src/add-ons/kernel/bus_managers/random/driver.cpp (revision 7032e7033039a3bea39e49fdd7084369ce9c7d47)
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 device_manager_info* sDeviceManager;
36 
37 
38 typedef struct {
39 	device_node*			node;
40 } random_driver_info;
41 
42 
43 //	#pragma mark - device module API
44 
45 
46 static status_t
47 random_init_device(void* _info, void** _cookie)
48 {
49 	mutex_init(&sRandomLock, "/dev/random lock");
50 	return gYarrowRandomModule->init();
51 }
52 
53 
54 static void
55 random_uninit_device(void* _cookie)
56 {
57 	gYarrowRandomModule->uninit();
58 	mutex_destroy(&sRandomLock);
59 }
60 
61 
62 static status_t
63 random_open(void *deviceCookie, const char *name, int flags, void **cookie)
64 {
65 	TRACE("open(\"%s\")\n", name);
66 	return B_OK;
67 }
68 
69 
70 static status_t
71 random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes)
72 {
73 	TRACE("read(%Ld,, %ld)\n", position, *_numBytes);
74 
75 	MutexLocker locker(&sRandomLock);
76 	return gYarrowRandomModule->read(_buffer, _numBytes);
77 }
78 
79 
80 static status_t
81 random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes)
82 {
83 	TRACE("write(%Ld,, %ld)\n", position, *_numBytes);
84 	MutexLocker locker(&sRandomLock);
85 	return gYarrowRandomModule->write(buffer, _numBytes);
86 }
87 
88 
89 static status_t
90 random_control(void *cookie, uint32 op, void *arg, size_t length)
91 {
92 	TRACE("ioctl(%ld)\n", op);
93 	return B_ERROR;
94 }
95 
96 
97 static status_t
98 random_close(void *cookie)
99 {
100 	TRACE("close()\n");
101 	return B_OK;
102 }
103 
104 
105 static status_t
106 random_free(void *cookie)
107 {
108 	TRACE("free()\n");
109 	return B_OK;
110 }
111 
112 
113 static status_t
114 random_select(void *cookie, uint8 event, selectsync *sync)
115 {
116 	TRACE("select()\n");
117 
118 	if (event == B_SELECT_READ) {
119 		/* tell there is already data to read */
120 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
121 		notify_select_event(sync, ref);
122 #else
123 		notify_select_event(sync, event);
124 #endif
125 	} else if (event == B_SELECT_WRITE) {
126 		/* we're now writable */
127 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
128 		notify_select_event(sync, ref);
129 #else
130 		notify_select_event(sync, event);
131 #endif
132 	}
133 	return B_OK;
134 }
135 
136 
137 static status_t
138 random_deselect(void *cookie, uint8 event, selectsync *sync)
139 {
140 	TRACE("deselect()\n");
141 	return B_OK;
142 }
143 
144 
145 //	#pragma mark - driver module API
146 
147 
148 static float
149 random_supports_device(device_node *parent)
150 {
151 	CALLED();
152 	const char *bus;
153 
154 	// make sure parent is really device root
155 	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
156 		return -1;
157 
158 	if (strcmp(bus, "root"))
159 		return 0.0;
160 
161 	return 1.0;
162 }
163 
164 
165 static status_t
166 random_register_device(device_node *node)
167 {
168 	CALLED();
169 
170 	// ready to register
171 	device_attr attrs[] = {
172 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "Random" }},
173 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }},
174 		{ NULL }
175 	};
176 
177 	return sDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME,
178 		attrs, NULL, NULL);
179 }
180 
181 
182 static status_t
183 random_init_driver(device_node *node, void **cookie)
184 {
185 	CALLED();
186 
187 	random_driver_info* info = (random_driver_info*)malloc(
188 		sizeof(random_driver_info));
189 	if (info == NULL)
190 		return B_NO_MEMORY;
191 
192 	memset(info, 0, sizeof(*info));
193 
194 	info->node = node;
195 
196 	*cookie = info;
197 	return B_OK;
198 }
199 
200 
201 static void
202 random_uninit_driver(void *_cookie)
203 {
204 	CALLED();
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 = sDeviceManager->publish_device(info->node, "random",
216 		RANDOM_DEVICE_MODULE_NAME);
217 	if (status == B_OK) {
218 		sDeviceManager->publish_device(info->node, "urandom",
219 			RANDOM_DEVICE_MODULE_NAME);
220 	}
221 
222 	return status;
223 }
224 
225 
226 //	#pragma mark -
227 
228 
229 module_dependency module_dependencies[] = {
230 	{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
231 	{}
232 };
233 
234 struct device_module_info sRandomDevice = {
235 	{
236 		RANDOM_DEVICE_MODULE_NAME,
237 		0,
238 		NULL
239 	},
240 
241 	random_init_device,
242 	random_uninit_device,
243 	NULL, // remove,
244 
245 	random_open,
246 	random_close,
247 	random_free,
248 	random_read,
249 	random_write,
250 	NULL,
251 	random_control,
252 
253 	random_select,
254 	random_deselect,
255 };
256 
257 struct driver_module_info sRandomDriver = {
258 	{
259 		RANDOM_DRIVER_MODULE_NAME,
260 		0,
261 		NULL
262 	},
263 
264 	random_supports_device,
265 	random_register_device,
266 	random_init_driver,
267 	random_uninit_driver,
268 	random_register_child_devices,
269 	NULL,	// rescan
270 	NULL,	// removed
271 };
272 
273 module_info* modules[] = {
274 	(module_info*)&sRandomDriver,
275 	(module_info*)&sRandomDevice,
276 	NULL
277 };
278