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