source: mainline/uspace/srv/devman/match.c@ 181c32f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 181c32f was a60e90b, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Move rest of functionality from devman.c to other modules.

  • Property mode set to 100644
File size: 6.1 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 <fcntl.h>
34#include <io/log.h>
35#include <str.h>
36#include <str_error.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39
40#include "devman.h"
41#include "match.h"
42
43/** Compute compound score of driver and device.
44 *
45 * @param driver Match id of the driver.
46 * @param device Match id of the device.
47 * @return Compound score.
48 * @retval 0 No match at all.
49 */
50static int compute_match_score(match_id_t *driver, match_id_t *device)
51{
52 if (str_cmp(driver->id, device->id) == 0) {
53 /*
54 * The strings match, return the product of their scores.
55 */
56 return driver->score * device->score;
57 } else {
58 /*
59 * Different strings, return zero.
60 */
61 return 0;
62 }
63}
64
65int get_match_score(driver_t *drv, dev_node_t *dev)
66{
67 link_t *drv_head = &drv->match_ids.ids.head;
68 link_t *dev_head = &dev->pfun->match_ids.ids.head;
69
70 if (list_empty(&drv->match_ids.ids) ||
71 list_empty(&dev->pfun->match_ids.ids)) {
72 return 0;
73 }
74
75 /*
76 * Go through all pairs, return the highest score obtained.
77 */
78 int highest_score = 0;
79
80 link_t *drv_link = drv->match_ids.ids.head.next;
81 while (drv_link != drv_head) {
82 link_t *dev_link = dev_head->next;
83 while (dev_link != dev_head) {
84 match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
85 match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
86
87 int score = compute_match_score(drv_id, dev_id);
88 if (score > highest_score) {
89 highest_score = score;
90 }
91
92 dev_link = dev_link->next;
93 }
94
95 drv_link = drv_link->next;
96 }
97
98 return highest_score;
99}
100
101/** Read match id at the specified position of a string and set the position in
102 * the string to the first character following the id.
103 *
104 * @param buf The position in the input string.
105 * @return The match id.
106 */
107char *read_match_id(char **buf)
108{
109 char *res = NULL;
110 size_t len = get_nonspace_len(*buf);
111
112 if (len > 0) {
113 res = malloc(len + 1);
114 if (res != NULL) {
115 str_ncpy(res, len + 1, *buf, len);
116 *buf += len;
117 }
118 }
119
120 return res;
121}
122
123/**
124 * Read match ids and associated match scores from a string.
125 *
126 * Each match score in the string is followed by its match id.
127 * The match ids and match scores are separated by whitespaces.
128 * Neither match ids nor match scores can contain whitespaces.
129 *
130 * @param buf The string from which the match ids are read.
131 * @param ids The list of match ids into which the match ids and
132 * scores are added.
133 * @return True if at least one match id and associated match score
134 * was successfully read, false otherwise.
135 */
136bool parse_match_ids(char *buf, match_id_list_t *ids)
137{
138 int score = 0;
139 char *id = NULL;
140 int ids_read = 0;
141
142 while (true) {
143 /* skip spaces */
144 if (!skip_spaces(&buf))
145 break;
146
147 /* read score */
148 score = strtoul(buf, &buf, 10);
149
150 /* skip spaces */
151 if (!skip_spaces(&buf))
152 break;
153
154 /* read id */
155 id = read_match_id(&buf);
156 if (NULL == id)
157 break;
158
159 /* create new match_id structure */
160 match_id_t *mid = create_match_id();
161 mid->id = id;
162 mid->score = score;
163
164 /* add it to the list */
165 add_match_id(ids, mid);
166
167 ids_read++;
168 }
169
170 return ids_read > 0;
171}
172
173/**
174 * Read match ids and associated match scores from a file.
175 *
176 * Each match score in the file is followed by its match id.
177 * The match ids and match scores are separated by whitespaces.
178 * Neither match ids nor match scores can contain whitespaces.
179 *
180 * @param buf The path to the file from which the match ids are read.
181 * @param ids The list of match ids into which the match ids and
182 * scores are added.
183 * @return True if at least one match id and associated match score
184 * was successfully read, false otherwise.
185 */
186bool read_match_ids(const char *conf_path, match_id_list_t *ids)
187{
188 log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
189
190 bool suc = false;
191 char *buf = NULL;
192 bool opened = false;
193 int fd;
194 size_t len = 0;
195
196 fd = open(conf_path, O_RDONLY);
197 if (fd < 0) {
198 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
199 conf_path, str_error(fd));
200 goto cleanup;
201 }
202 opened = true;
203
204 len = lseek(fd, 0, SEEK_END);
205 lseek(fd, 0, SEEK_SET);
206 if (len == 0) {
207 log_msg(LOG_DEFAULT, LVL_ERROR, "Configuration file '%s' is empty.",
208 conf_path);
209 goto cleanup;
210 }
211
212 buf = malloc(len + 1);
213 if (buf == NULL) {
214 log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed when parsing file "
215 "'%s'.", conf_path);
216 goto cleanup;
217 }
218
219 ssize_t read_bytes = read_all(fd, buf, len);
220 if (read_bytes <= 0) {
221 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
222 read_bytes);
223 goto cleanup;
224 }
225 buf[read_bytes] = 0;
226
227 suc = parse_match_ids(buf, ids);
228
229cleanup:
230 free(buf);
231
232 if (opened)
233 close(fd);
234
235 return suc;
236}
237
238/** @}
239 */
Note: See TracBrowser for help on using the repository browser.