source: mainline/uspace/srv/devman/devman.c@ 08d9c4e6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 08d9c4e6 was 08d9c4e6, checked in by Lenka Trochtova <trochtova.lenka@…>, 15 years ago

device manager - initialization of the list of available drivers

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2010 Lenka Trochtova
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup devman
30 * @{
31 */
32
33#include <errno.h>
34#include <fcntl.h>
35#include <sys/stat.h>
36
37#include "devman.h"
38#include "util.h"
39
40
41driver_t * create_driver()
42{
43 printf(NAME ": create_driver\n");
44
45 driver_t *res = malloc(sizeof(driver_t));
46 if(res != NULL) {
47 init_driver(res);
48 }
49 return res;
50}
51
52char * read_id(const char **buf)
53{
54 char *res = NULL;
55 size_t len = get_nonspace_len(*buf);
56 if (len > 0) {
57 res = malloc(len + 1);
58 if (res != NULL) {
59 str_ncpy(res, len + 1, *buf, len);
60 *buf += len;
61 }
62 }
63 return res;
64}
65
66bool parse_match_ids(const char *buf, match_id_list_t *ids)
67{
68 int score = 0;
69 char *id = NULL;
70 int ids_read = 0;
71
72 while (true) {
73 // skip spaces
74 if (!skip_spaces(&buf)) {
75 break;
76 }
77 // read score
78 score = strtoul(buf, &buf, 10);
79
80 // skip spaces
81 if (!skip_spaces(&buf)) {
82 break;
83 }
84
85 // read id
86 if (NULL == (id = read_id(&buf))) {
87 break;
88 }
89
90 // create new match_id structure
91 match_id_t *mid = create_match_id();
92 mid->id = id;
93 mid->score = score;
94
95 /// add it to the list
96 add_match_id(ids, mid);
97
98 ids_read++;
99 }
100
101 return ids_read > 0;
102}
103
104bool read_match_ids(const char *conf_path, match_id_list_t *ids)
105{
106 printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);
107
108 bool suc = false;
109 char *buf = NULL;
110 bool opened = false;
111 int fd;
112 off_t len = 0;
113
114 fd = open(conf_path, O_RDONLY);
115 if (fd < 0) {
116 printf(NAME ": unable to open %s\n", conf_path);
117 goto cleanup;
118 }
119 opened = true;
120
121 len = lseek(fd, 0, SEEK_END);
122 lseek(fd, 0, SEEK_SET);
123 if (len == 0) {
124 printf(NAME ": configuration file '%s' is empty.\n", conf_path);
125 goto cleanup;
126 }
127
128 buf = malloc(len + 1);
129 if (buf == NULL) {
130 printf(NAME ": memory allocation failed when parsing file '%s'.\n", conf_path);
131 goto cleanup;
132 }
133
134 if (0 >= read(fd, buf, len)) {
135 printf(NAME ": unable to read file '%s'.\n", conf_path);
136 goto cleanup;
137 }
138 buf[len] = 0;
139
140 suc = parse_match_ids(buf, ids);
141
142cleanup:
143
144 free(buf);
145
146 if(opened) {
147 close(fd);
148 }
149
150 return suc;
151}
152
153
154bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
155{
156 printf(NAME ": get_driver_info base_path = %s, name = %s.\n", base_path, name);
157
158 assert(base_path != NULL && name != NULL && drv != NULL);
159
160 bool suc = false;
161 char *match_path = NULL;
162 size_t name_size = 0;
163
164 // read the list of match ids from the driver's configuration file
165 if (NULL == (match_path = get_abs_path(base_path, name, MATCH_EXT))) {
166 goto cleanup;
167 }
168
169 printf(NAME ": get_driver_info - path to match id list = %s.\n", match_path);
170
171 if (!read_match_ids(match_path, &drv->match_ids)) {
172 goto cleanup;
173 }
174
175 // allocate and fill driver's name
176 name_size = str_size(name)+1;
177 drv->name = malloc(name_size);
178 if (!drv->name) {
179 goto cleanup;
180 }
181 str_cpy(drv->name, name_size, name);
182
183 // initialize path with driver's binary
184 if (NULL == (drv->binary_path = get_abs_path(base_path, name, ""))) {
185 goto cleanup;
186 }
187
188 // check whether the driver's binary exists
189 struct stat s;
190 if (stat(drv->binary_path, &s) == ENOENT) {
191 printf(NAME ": driver not found at path %s.", drv->binary_path);
192 goto cleanup;
193 }
194
195 suc = true;
196
197cleanup:
198
199 if (!suc) {
200 free(drv->binary_path);
201 free(drv->name);
202 // set the driver structure to the default state
203 init_driver(drv);
204 }
205
206 free(match_path);
207
208 return suc;
209}
210
211/** Lookup drivers in the directory.
212 *
213 * @param drivers_list the list of available drivers.
214 * @param dir_path the path to the directory where we search for drivers.
215 */
216int lookup_available_drivers(link_t *drivers_list, const char *dir_path)
217{
218 printf(NAME ": lookup_available_drivers \n");
219
220 int drv_cnt = 0;
221 DIR *dir = NULL;
222 struct dirent *diren;
223
224 dir = opendir(dir_path);
225 printf(NAME ": lookup_available_drivers has opened directory %s for driver search.\n", dir_path);
226
227 if (dir != NULL) {
228 driver_t *drv = create_driver();
229 printf(NAME ": lookup_available_drivers has created driver structure.\n");
230 while ((diren = readdir(dir))) {
231 if (get_driver_info(dir_path, diren->d_name, drv)) {
232 add_driver(drivers_list, drv);
233 drv_cnt++;
234 drv = create_driver();
235 }
236 }
237 delete_driver(drv);
238 closedir(dir);
239 }
240
241 return drv_cnt;
242}
243
244node_t * create_root_node()
245{
246 node_t *node = create_dev_node();
247 if (node) {
248 init_dev_node(node, NULL);
249 match_id_t *id = create_match_id();
250 id->id = "root";
251 id->score = 100;
252 add_match_id(&node->match_ids, id);
253 }
254 return node;
255}
256
257driver_t * find_best_match_driver(link_t *drivers_list, node_t *node)
258{
259 driver_t *best_drv = NULL, *drv = NULL;
260 int best_score = 0, score = 0;
261 link_t *link = drivers_list->next;
262
263 while (link != drivers_list) {
264 drv = list_get_instance(link, driver_t, drivers);
265 score = get_match_score(drv, node);
266 if (score > best_score) {
267 best_score = score;
268 best_drv = drv;
269 }
270 }
271
272 return best_drv;
273}
274
275void attach_driver(node_t *node, driver_t *drv)
276{
277 node->drv = drv;
278 list_append(&node->driver_devices, &drv->devices);
279}
280
281bool start_driver(driver_t *drv)
282{
283 char *argv[2];
284
285 printf(NAME ": spawning driver %s\n", drv->name);
286
287 argv[0] = drv->name;
288 argv[1] = NULL;
289
290 if (!task_spawn(drv->binary_path, argv)) {
291 printf(NAME ": error spawning %s\n", drv->name);
292 return false;
293 }
294
295 return true;
296}
297
298bool add_device(driver_t *drv, node_t *node)
299{
300 // TODO
301
302 // pass a new device to the running driver, which was previously assigned to it
303 // send the phone of the parent's driver and device's handle within the parent's driver to the driver
304 // let the driver to probe the device and specify whether the device is actually present
305 // if the device is present, remember its handle within the driver
306
307 return true;
308}
309
310bool assign_driver(node_t *node, link_t *drivers_list)
311{
312 // find the driver which is the most suitable for handling this device
313 driver_t *drv = find_best_match_driver(drivers_list, node);
314 if (NULL == drv) {
315 return false;
316 }
317
318 // attach the driver to the device
319 attach_driver(node, drv);
320
321 if (!drv->running) {
322 // start driver
323 start_driver(drv);
324 } else {
325 // notify driver about new device
326 add_device(drv, node);
327 }
328
329 return true;
330}
331
332bool init_device_tree(dev_tree_t *tree, link_t *drivers_list)
333{
334 printf(NAME ": init_device_tree.");
335 // create root node and add it to the device tree
336 if (NULL == (tree->root_node = create_root_node())) {
337 return false;
338 }
339
340 // find suitable driver and start it
341 return assign_driver(tree->root_node, drivers_list);
342}
343
Note: See TracBrowser for help on using the repository browser.