source: mainline/uspace/app/devctl/devctl.c@ 5c769d54

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

devctl list-drv can use io/table.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/*
2 * Copyright (c) 2011 Jiri Svoboda
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 devctl
30 * @{
31 */
32/** @file Control device framework (devman server).
33 */
34
35#include <devman.h>
36#include <errno.h>
37#include <io/table.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str_error.h>
42
43#define NAME "devctl"
44
45#define MAX_NAME_LENGTH 1024
46
47static char name[MAX_NAME_LENGTH];
48static char drv_name[MAX_NAME_LENGTH];
49static bool verbose = false;
50
51static const char *drv_state_str(driver_state_t state)
52{
53 const char *sstate;
54
55 switch (state) {
56 case DRIVER_NOT_STARTED:
57 sstate = "not started";
58 break;
59 case DRIVER_STARTING:
60 sstate = "starting";
61 break;
62 case DRIVER_RUNNING:
63 sstate = "running";
64 break;
65 default:
66 sstate = "unknown";
67 }
68
69 return sstate;
70}
71
72static int fun_subtree_print(devman_handle_t funh, int lvl)
73{
74 devman_handle_t devh;
75 devman_handle_t *cfuns;
76 size_t count, i;
77 unsigned int score;
78 int rc;
79 int j;
80
81 for (j = 0; j < lvl; j++)
82 printf(" ");
83
84 rc = devman_fun_get_name(funh, name, MAX_NAME_LENGTH);
85 if (rc != EOK)
86 return ELIMIT;
87
88 if (name[0] == '\0')
89 str_cpy(name, MAX_NAME_LENGTH, "/");
90
91 rc = devman_fun_get_driver_name(funh, drv_name, MAX_NAME_LENGTH);
92 if (rc != EOK && rc != EINVAL)
93 return ELIMIT;
94
95 if (rc == EINVAL)
96 printf("%s\n", name);
97 else
98 printf("%s : %s\n", name, drv_name);
99
100 if (verbose) {
101 for (i = 0; true; i++) {
102 rc = devman_fun_get_match_id(funh, i, name, MAX_NAME_LENGTH,
103 &score);
104 if (rc != EOK)
105 break;
106
107 for (j = 0; j < lvl; j++)
108 printf(" ");
109
110 printf(" %u %s\n", score, name);
111 }
112 }
113
114 rc = devman_fun_get_child(funh, &devh);
115 if (rc == ENOENT)
116 return EOK;
117
118 if (rc != EOK) {
119 printf(NAME ": Failed getting child device for function "
120 "%s.\n", "xxx");
121 return rc;
122 }
123
124 rc = devman_dev_get_functions(devh, &cfuns, &count);
125 if (rc != EOK) {
126 printf(NAME ": Failed getting list of functions for "
127 "device %s.\n", "xxx");
128 return rc;
129 }
130
131 for (i = 0; i < count; i++)
132 fun_subtree_print(cfuns[i], lvl + 1);
133
134 free(cfuns);
135 return EOK;
136}
137
138static int fun_tree_print(void)
139{
140 devman_handle_t root_fun;
141 int rc;
142
143 rc = devman_fun_get_handle("/", &root_fun, 0);
144 if (rc != EOK) {
145 printf(NAME ": Error resolving root function.\n");
146 return EIO;
147 }
148
149 rc = fun_subtree_print(root_fun, 0);
150 if (rc != EOK)
151 return EIO;
152
153 return EOK;
154}
155
156static int fun_online(const char *path)
157{
158 devman_handle_t funh;
159 int rc;
160
161 rc = devman_fun_get_handle(path, &funh, 0);
162 if (rc != EOK) {
163 printf(NAME ": Error resolving device function '%s' (%s)\n",
164 path, str_error(rc));
165 return rc;
166 }
167
168 rc = devman_fun_online(funh);
169 if (rc != EOK) {
170 printf(NAME ": Failed to online function '%s'.\n", path);
171 return rc;
172 }
173
174 return EOK;
175}
176
177static int fun_offline(const char *path)
178{
179 devman_handle_t funh;
180 int rc;
181
182 rc = devman_fun_get_handle(path, &funh, 0);
183 if (rc != EOK) {
184 printf(NAME ": Error resolving device function '%s' (%s)\n",
185 path, str_error(rc));
186 return rc;
187 }
188
189 rc = devman_fun_offline(funh);
190 if (rc != EOK) {
191 printf(NAME ": Failed to offline function '%s' (%s)\n", path,
192 str_error(rc));
193 return rc;
194 }
195
196 return EOK;
197}
198
199static int drv_list(void)
200{
201 devman_handle_t *devs;
202 devman_handle_t *drvs;
203 driver_state_t state;
204 const char *sstate;
205 size_t ndrvs;
206 size_t ndevs;
207 size_t i;
208 table_t *table = NULL;
209 int rc;
210
211 rc = devman_get_drivers(&drvs, &ndrvs);
212 if (rc != EOK)
213 return rc;
214
215 rc = table_create(&table);
216 if (rc != EOK) {
217 assert(rc == ENOMEM);
218 goto out;
219 }
220
221 table_header_row(table);
222 table_printf(table, "Driver\t" "Devs\t" "State\n");
223
224 for (i = 0; i < ndrvs; i++) {
225 devs = NULL;
226
227 rc = devman_driver_get_name(drvs[i], drv_name, MAX_NAME_LENGTH);
228 if (rc != EOK)
229 goto skip;
230 rc = devman_driver_get_state(drvs[i], &state);
231 if (rc != EOK)
232 goto skip;
233 rc = devman_driver_get_devices(drvs[i], &devs, &ndevs);
234 if (rc != EOK)
235 goto skip;
236
237 sstate = drv_state_str(state);
238
239 table_printf(table, "%s\t" "%zu\t" "%s\n", drv_name, ndevs, sstate);
240skip:
241 free(devs);
242 }
243
244 rc = table_print_out(table, stdout);
245 if (rc != EOK)
246 printf("Error printing driver table.\n");
247out:
248 free(drvs);
249 table_destroy(table);
250
251 return rc;
252}
253
254static int drv_show(char *drvname)
255{
256 devman_handle_t *devs;
257 devman_handle_t drvh;
258 devman_handle_t funh;
259 driver_state_t state;
260 const char *sstate;
261 unsigned int score;
262 size_t ndevs;
263 size_t i;
264 int rc;
265
266 rc = devman_driver_get_handle(drvname, &drvh);
267 if (rc != EOK)
268 return rc;
269
270 devs = NULL;
271
272 rc = devman_driver_get_name(drvh, drv_name, MAX_NAME_LENGTH);
273 if (rc != EOK)
274 return rc;
275
276 rc = devman_driver_get_state(drvh, &state);
277 if (rc != EOK)
278 return rc;
279
280 rc = devman_driver_get_devices(drvh, &devs, &ndevs);
281 if (rc != EOK)
282 return rc;
283
284 sstate = drv_state_str(state);
285
286 printf("Driver: %s\n", drv_name);
287 printf("State: %s\n", sstate);
288
289 printf("Attached devices:\n");
290
291 for (i = 0; i < ndevs; i++) {
292 rc = devman_dev_get_parent(devs[i], &funh);
293 if (rc != EOK)
294 goto error;
295
296 rc = devman_fun_get_path(funh, name, MAX_NAME_LENGTH);
297 if (rc != EOK)
298 goto error;
299 printf("\t%s\n", name);
300 }
301
302 printf("Match IDs:\n");
303
304 for (i = 0; true; i++) {
305 rc = devman_driver_get_match_id(drvh, i, name, MAX_NAME_LENGTH,
306 &score);
307 if (rc != EOK)
308 break;
309
310 printf("\t%u %s\n", score, name);
311 }
312
313error:
314 free(devs);
315
316 return EOK;
317}
318
319static int drv_load(const char *drvname)
320{
321 int rc;
322 devman_handle_t drvh;
323
324 rc = devman_driver_get_handle(drvname, &drvh);
325 if (rc != EOK) {
326 printf("Failed resolving driver '%s' (%d).\n", drvname, rc);
327 return rc;
328 }
329
330 rc = devman_driver_load(drvh);
331 if (rc != EOK) {
332 printf("Failed loading driver '%s' (%d).\n", drvname, rc);
333 return rc;
334 }
335
336 return EOK;
337}
338
339static void print_syntax(void)
340{
341 printf("syntax:\n");
342 printf("\tdevctl\n");
343 printf("\tdevctl online <function>]\n");
344 printf("\tdevctl offline <function>]\n");
345 printf("\tdevctl list-drv\n");
346 printf("\tdevctl show-drv <driver-name>\n");
347 printf("\tdevctl load-drv <driver-name>\n");
348}
349
350int main(int argc, char *argv[])
351{
352 int rc;
353
354 if (argc == 1 || argv[1][0] == '-') {
355 if (argc > 1) {
356 if (str_cmp(argv[1], "-v") == 0) {
357 verbose = true;
358 } else {
359 printf(NAME ": Invalid argument '%s'\n", argv[1]);
360 print_syntax();
361 return 1;
362 }
363 }
364 rc = fun_tree_print();
365 if (rc != EOK)
366 return 2;
367 } else if (str_cmp(argv[1], "online") == 0) {
368 if (argc < 3) {
369 printf(NAME ": Argument missing.\n");
370 print_syntax();
371 return 1;
372 }
373
374 rc = fun_online(argv[2]);
375 if (rc != EOK) {
376 return 2;
377 }
378 } else if (str_cmp(argv[1], "offline") == 0) {
379 if (argc < 3) {
380 printf(NAME ": Argument missing.\n");
381 print_syntax();
382 return 1;
383 }
384
385 rc = fun_offline(argv[2]);
386 if (rc != EOK) {
387 return 2;
388 }
389 } else if (str_cmp(argv[1], "list-drv") == 0) {
390 rc = drv_list();
391 if (rc != EOK)
392 return 2;
393 } else if (str_cmp(argv[1], "show-drv") == 0) {
394 if (argc < 3) {
395 printf(NAME ": Argument missing.\n");
396 print_syntax();
397 return 1;
398 }
399
400 rc = drv_show(argv[2]);
401 if (rc != EOK) {
402 return 2;
403 }
404 } else if (str_cmp(argv[1], "load-drv") == 0) {
405 if (argc < 3) {
406 printf(NAME ": Argument missing.\n");
407 print_syntax();
408 return 1;
409 }
410
411 rc = drv_load(argv[2]);
412 if (rc != EOK)
413 return 2;
414 } else {
415 printf(NAME ": Invalid argument '%s'.\n", argv[1]);
416 print_syntax();
417 return 1;
418 }
419
420 return 0;
421}
422
423/** @}
424 */
Note: See TracBrowser for help on using the repository browser.