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