source: mainline/uspace/srv/devman/devman.c@ e2b9a993

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

device manager - parts of code

  • Property mode set to 100644
File size: 7.2 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 driver_t *res = malloc(sizeof(driver_t));
44 if(res != NULL) {
45 clean_driver(res);
46 }
47 return res;
48}
49
50char * read_id(const char **buf)
51{
52 char *res = NULL;
53 size_t len = get_nonspace_len(*buf);
54 if (len > 0) {
55 res = malloc(len + 1);
56 if (res != NULL) {
57 str_ncpy(res, len + 1, *buf, len);
58 *buf += len;
59 }
60 }
61 return res;
62}
63
64bool parse_match_ids(const char *buf, match_id_list_t *ids)
65{
66 int score = 0;
67 char *id = NULL;
68 int ids_read = 0;
69
70 while (true) {
71 // skip spaces
72 if (!skip_spaces(&buf)) {
73 break;
74 }
75 // read score
76 score = strtoul(buf, &buf, 10);
77
78 // skip spaces
79 if (!skip_spaces(&buf)) {
80 break;
81 }
82
83 // read id
84 if (NULL == (id = read_id(&buf))) {
85 break;
86 }
87
88 // create new match_id structure
89 match_id_t *mid = create_match_id();
90 mid->id = id;
91 mid->score = score;
92
93 /// add it to the list
94 add_match_id(ids, mid);
95
96 ids_read++;
97 }
98
99 return ids_read > 0;
100}
101
102bool read_match_ids(const char *conf_path, match_id_list_t *ids)
103{
104 bool suc = false;
105 char *buf = NULL;
106 bool opened = false;
107 int fd;
108 off_t len = 0;
109
110 fd = open(conf_path, O_RDONLY);
111 if (fd < 0) {
112 printf(NAME ": unable to open %s\n", conf_path);
113 goto cleanup;
114 }
115 opened = true;
116
117 len = lseek(fd, 0, SEEK_END);
118 lseek(fd, 0, SEEK_SET);
119 if (len == 0) {
120 printf(NAME ": configuration file '%s' is empty.\n", conf_path);
121 goto cleanup;
122 }
123
124 buf = malloc(len + 1);
125 if (buf == NULL) {
126 printf(NAME ": memory allocation failed when parsing file '%s'.\n", conf_path);
127 goto cleanup;
128 }
129
130 if (0 >= read(fd, buf, len)) {
131 printf(NAME ": unable to read file '%s'.\n", conf_path);
132 goto cleanup;
133 }
134 buf[len] = 0;
135
136 suc = parse_match_ids(buf, ids);
137
138cleanup:
139
140 free(buf);
141
142 if(opened) {
143 close(fd);
144 }
145
146 return suc;
147}
148
149
150bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
151{
152 assert(base_path != NULL && name != NULL && drv != NULL);
153
154 bool suc = false;
155 char *match_path = NULL;
156 size_t name_size = 0;
157
158 // read the list of match ids from the driver's configuration file
159 if (NULL == (match_path = get_abs_path(base_path, name, MATCH_EXT))) {
160 goto cleanup;
161 }
162
163 if (!read_match_ids(match_path, &drv->match_ids)) {
164 goto cleanup;
165 }
166
167 // allocate and fill driver's name
168 name_size = str_size(name)+1;
169 drv->name = malloc(name_size);
170 if (!drv->name) {
171 goto cleanup;
172 }
173 str_cpy(drv->name, name_size, name);
174
175 // initialize path with driver's binary
176 if (NULL == (drv->binary_path = get_abs_path(base_path, name, ""))) {
177 goto cleanup;
178 }
179
180 // check whether the driver's binary exists
181 struct stat s;
182 if (stat(drv->binary_path, &s) == ENOENT) {
183 printf(NAME ": driver not found at path %s.", drv->binary_path);
184 goto cleanup;
185 }
186
187 suc = true;
188
189cleanup:
190
191 if (!suc) {
192 free(drv->binary_path);
193 free(drv->name);
194 // set the driver structure to the default state
195 init_driver(drv);
196 }
197
198 free(match_path);
199
200 return suc;
201}
202
203/** Lookup drivers in the directory.
204 *
205 * @param drivers_list the list of available drivers.
206 * @param dir_path the path to the directory where we search for drivers.
207 */
208int lookup_available_drivers(link_t *drivers_list, const char *dir_path)
209{
210 int drv_cnt = 0;
211 DIR *dir = NULL;
212 struct dirent *diren;
213
214 dir = opendir(dir_path);
215 if (dir != NULL) {
216 driver_t *drv = create_driver();
217 while ((diren = readdir(dir))) {
218 if (get_driver_info(dir_path, diren->d_name, drv)) {
219 add_driver(drivers_list, drv);
220 drv = create_driver();
221 }
222 }
223 delete_driver(drv);
224 closedir(dir);
225 }
226
227 return drv_cnt;
228}
229
230node_t * create_root_node()
231{
232 node_t *node = create_dev_node();
233 if (node) {
234 init_dev_node(node, NULL);
235 match_id_t *id = create_match_id();
236 id->id = "root";
237 id->score = 100;
238 add_match_id(&node->match_ids, id);
239 }
240 return node;
241}
242
243driver_t * find_best_match_driver(link_t *drivers_list, node_t *node)
244{
245 driver_t *best_drv = NULL, *drv = NULL;
246 int best_score = 0, score = 0;
247 link_t *link = drivers_list->next;
248
249 while (link != drivers_list) {
250 drv = list_get_instance(link, driver_t, drivers);
251 score = get_match_score(drv, node);
252 if (score > best_score) {
253 best_score = score;
254 best_drv = drv;
255 }
256 }
257
258 return best_drv;
259}
260
261void attach_driver(node_t *node, driver_t *drv)
262{
263 node->drv = drv;
264 list_append(&node->driver_devices, &drv->devices);
265}
266
267bool start_driver(driver_t *drv)
268{
269 char *argv[2];
270
271 printf(NAME ": spawning driver %s\n", drv->name);
272
273 argv[0] = drv->name;
274 argv[1] = NULL;
275
276 if (!task_spawn(drv->binary_path, argv)) {
277 printf(NAME ": error spawning %s\n", drv->name);
278 return false;
279 }
280
281 return true;
282}
283
284bool add_device(driver_t *drv, node_t *node)
285{
286 // TODO
287
288 // pass a new device to the running driver, which was previously assigned to it
289 // send the phone of the parent's driver and device's handle within the parent's driver to the driver
290 // let the driver to probe the device and specify whether the device is actually present
291 // if the device is present, remember its handle within the driver
292
293 return true;
294}
295
296bool assign_driver(node_t *node, link_t *drivers_list)
297{
298 // find the driver which is the most suitable for handling this device
299 driver_t *drv = find_best_match_driver(drivers_list, node);
300 if (NULL == drv) {
301 return false;
302 }
303
304 // attach the driver to the device
305 attach_driver(node, drv);
306
307 if (!drv->running) {
308 // start driver
309 start_driver(drv);
310 } else {
311 // notify driver about new device
312 add_device(drv, node);
313 }
314
315 return true;
316}
317
318bool init_device_tree(dev_tree_t *tree, link_t *drivers_list)
319{
320 // create root node and add it to the device tree
321 if (NULL == (tree->root_node = create_root_node())) {
322 return false;
323 }
324
325 // find suitable driver and start it
326 return assign_driver(tree->root_node, drivers_list);
327}
328
Note: See TracBrowser for help on using the repository browser.