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
config_open(const char * name,uint32 flags,void ** _cookie)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
config_close(void * cookie)54 config_close(void *cookie)
55 {
56 return B_OK;
57 }
58
59
60 static status_t
config_free_cookie(void * cookie)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
config_ioctl(void * cookie,uint32 op,void * buffer,size_t len)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
config_read(void * cookie,off_t pos,void * buf,size_t * _length)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
config_write(void * cookie,off_t pos,const void * buf,size_t * _length)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
init_hardware()178 init_hardware()
179 {
180 return B_OK;
181 }
182
183
184 const char **
publish_devices(void)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 *
find_device(const char * name)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
init_driver()223 init_driver()
224 {
225 return get_module(B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager);
226 }
227
228
229 void
uninit_driver()230 uninit_driver()
231 {
232 if (gDeviceManager != NULL)
233 put_module(B_DEVICE_MANAGER_MODULE_NAME);
234 }
235
236