xref: /haiku/src/tests/system/kernel/device_manager/config.c (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /* config driver
2  * provides userland access to the device manager
3  *
4  * Copyright 2002-2004, Axel Doerfler. All rights reserved.
5  * Distributed under the terms of the MIT License.
6  *
7  * Authors : Axel Doerfler, Jerome Duval
8  */
9 
10 
11 #include <Drivers.h>
12 #include <drivers/device_manager.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "config_driver.h"
17 
18 #ifdef DEBUG
19 #define TRACE(x...) dprintf(x)
20 #else
21 #define TRACE(x...)
22 #endif
23 
24 #define DEVICE_NAME "misc/config"
25 
26 int32 api_version = B_CUR_DRIVER_API_VERSION;
27 
28 device_manager_info *gDeviceManager;
29 
30 typedef struct _driver_cookie {
31 	device_node_handle parent;
32 	device_node_handle child;
33 	device_attr_handle attr;
34 } driver_cookie;
35 
36 //	Device interface
37 
38 
39 static status_t
40 config_open(const char *name, uint32 flags, void **_cookie)
41 {
42 	driver_cookie *cookie = malloc(sizeof(driver_cookie));
43 	if (cookie == NULL)
44 		return B_ERROR;
45 	*_cookie = cookie;
46 	cookie->child = gDeviceManager->get_root();
47 	cookie->parent = NULL;
48 	cookie->attr = NULL;
49 	return B_OK;
50 }
51 
52 
53 static status_t
54 config_close(void *cookie)
55 {
56 	return B_OK;
57 }
58 
59 
60 static status_t
61 config_free_cookie(void *cookie)
62 {
63 	driver_cookie *cook = (driver_cookie *)cookie;
64 	gDeviceManager->put_device_node(cook->child);
65 	if (cook->parent)
66 		gDeviceManager->put_device_node(cook->parent);
67 	return B_OK;
68 }
69 
70 
71 static status_t
72 config_ioctl(void *cookie, uint32 op, void *buffer, size_t len)
73 {
74 	driver_cookie *cook = (driver_cookie *)cookie;
75 	device_node_handle child = NULL;
76 	const device_attr *attr = NULL;
77 
78 	struct dm_ioctl_data *params = (struct dm_ioctl_data *)buffer;
79 	status_t err = B_OK;
80 
81 	// simple check for validity of the argument
82 	if (params == NULL || params->magic != op)
83 		return B_BAD_VALUE;
84 
85 	switch (op) {
86 		case DM_GET_CHILD:
87 			TRACE("DM_GET_CHILD parent %p child %p\n", cook->parent, cook->child);
88 			if (cook->attr) {
89 				gDeviceManager->release_attr(cook->child, cook->attr);
90 				cook->attr = NULL;
91 			}
92 			err = gDeviceManager->get_next_child_device(cook->child, &child, NULL);
93 			if (err == B_OK) {
94 				if (cook->parent)
95 					gDeviceManager->put_device_node(cook->parent);
96 				cook->parent = cook->child;
97 				cook->child = child;
98 			}
99 			return err;
100 		case DM_GET_NEXT_CHILD:
101 			TRACE("DM_GET_NEXT_CHILD parent %p child %p\n", cook->parent, cook->child);
102 			if (!cook->parent)
103 				return B_ENTRY_NOT_FOUND;
104 			if (cook->attr) {
105 				gDeviceManager->release_attr(cook->child, cook->attr);
106 				cook->attr = NULL;
107 			}
108 			return gDeviceManager->get_next_child_device(cook->parent, &cook->child, NULL);
109 		case DM_GET_PARENT:
110 			TRACE("DM_GET_PARENT parent %p child %p\n", cook->parent, cook->child);
111 			if (!cook->parent)
112 				return B_ENTRY_NOT_FOUND;
113 			if (cook->attr) {
114 				gDeviceManager->release_attr(cook->child, cook->attr);
115 				cook->attr = NULL;
116 			}
117 			if (cook->child)
118 				gDeviceManager->put_device_node(cook->child);
119 			cook->child = cook->parent;
120 			cook->parent = gDeviceManager->get_parent(cook->child);
121 			return B_OK;
122 		case DM_GET_NEXT_ATTRIBUTE:
123 			TRACE("DM_NEXT_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr);
124 			return gDeviceManager->get_next_attr(cook->child, &cook->attr);
125 		case DM_RETRIEVE_ATTRIBUTE:
126 			TRACE("DM_RETRIEVE_ATTRIBUTE parent %p child %p attr %p\n", cook->parent, cook->child, cook->attr);
127 			err = gDeviceManager->retrieve_attr(cook->attr, &attr);
128 			if (err == B_OK) {
129 				strlcpy(params->attr->name, attr->name, 254);
130 				params->attr->type = attr->type;
131 				switch (attr->type) {
132 					case B_UINT8_TYPE:
133 						params->attr->value.ui8 = attr->value.ui8; break;
134 					case B_UINT16_TYPE:
135 						params->attr->value.ui16 = attr->value.ui16; break;
136 					case B_UINT32_TYPE:
137 						params->attr->value.ui32 = attr->value.ui32; break;
138 					case B_UINT64_TYPE:
139 						params->attr->value.ui64 = attr->value.ui64; break;
140 					case B_STRING_TYPE:
141 						strlcpy(params->attr->value.string, attr->value.string, 254); break;
142 					case B_RAW_TYPE:
143 						if (params->attr->value.raw.length > attr->value.raw.length)
144 							params->attr->value.raw.length = attr->value.raw.length;
145 						memcpy(params->attr->value.raw.data, attr->value.raw.data,
146 							params->attr->value.raw.length);
147 						break;
148 				}
149 			}
150 			return err;
151 	}
152 
153 	return B_BAD_VALUE;
154 }
155 
156 
157 static status_t
158 config_read(void * cookie, off_t pos, void *buf, size_t *_length)
159 {
160 	*_length = 0;
161 	return B_OK;
162 }
163 
164 
165 static status_t
166 config_write(void * cookie, off_t pos, const void *buf, size_t *_length)
167 {
168 	*_length = 0;
169 	return B_OK;
170 }
171 
172 
173 //	#pragma mark -
174 //	Driver interface
175 
176 
177 status_t
178 init_hardware()
179 {
180 	return B_OK;
181 }
182 
183 
184 const char **
185 publish_devices(void)
186 {
187 	static const char *devices[] = {
188 		DEVICE_NAME,
189 		NULL
190 	};
191 
192 	return devices;
193 }
194 
195 
196 device_hooks *
197 find_device(const char *name)
198 {
199 	static device_hooks hooks = {
200 		&config_open,
201 		&config_close,
202 		&config_free_cookie,
203 		&config_ioctl,
204 		&config_read,
205 		&config_write,
206 		/* Leave select/deselect/readv/writev undefined. The kernel will
207 		 * use its own default implementation. The basic hooks above this
208 		 * line MUST be defined, however. */
209 		NULL,
210 		NULL,
211 		NULL,
212 		NULL
213 	};
214 
215 	if (!strcmp(name, DEVICE_NAME))
216 		return &hooks;
217 
218 	return NULL;
219 }
220 
221 
222 status_t
223 init_driver()
224 {
225 	return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager);
226 }
227 
228 
229 void
230 uninit_driver()
231 {
232 	if (gDeviceManager != NULL)
233 		put_module(B_DEVICE_MANAGER_MODULE_NAME);
234 }
235 
236