source: mainline/uspace/app/disp/disp.c

Last change on this file was c0757e1f, checked in by Jiri Svoboda <jiri@…>, 2 years ago

UI display configuration utility

In addition to the command-line utility 'disp', we introduce its UI
equivalent 'display-cfg'. Currently this allows the user to configure
seats in a very comfortable way.

  • Property mode set to 100644
File size: 12.0 KB
RevLine 
[d8503fd]1/*
2 * Copyright (c) 2023 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 disp
30 * @{
31 */
32/** @file Display configuration utility.
33 *
34 * Configures the display service.
35 */
36
37#include <errno.h>
38#include <dispcfg.h>
39#include <io/table.h>
40#include <loc.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <stdint.h>
44#include <str.h>
45#include <str_error.h>
46
47#define NAME "disp"
48
49static void print_syntax(void)
50{
51 printf("%s: Display configuration utility.\n", NAME);
52 printf("Syntax:\n");
53 printf(" %s list-seat\n", NAME);
54 printf(" %s create-seat <name>\n", NAME);
55 printf(" %s delete-seat <name>\n", NAME);
[b3eeae5]56 printf(" %s assign-dev <device> <seat>\n", NAME);
57 printf(" %s unassign-dev <device>\n", NAME);
[c0757e1f]58 printf(" %s list-dev <seat>\n", NAME);
[d8503fd]59}
60
61/** Find seat by name.
62 *
63 * @param dispcfg Display configuration
64 * @param name Seat name
65 * @param rseat_id Place to store seat ID
66 * @return EOK on success or an error code
67 */
68static errno_t seat_find_by_name(dispcfg_t *dispcfg, const char *name,
69 sysarg_t *rseat_id)
70{
71 dispcfg_seat_list_t *seat_list;
72 dispcfg_seat_info_t *sinfo;
73
74 size_t i;
75 errno_t rc;
76
77 rc = dispcfg_get_seat_list(dispcfg, &seat_list);
78 if (rc != EOK) {
79 printf(NAME ": Failed getting seat list.\n");
80 return rc;
81 }
82
83 for (i = 0; i < seat_list->nseats; i++) {
84 rc = dispcfg_get_seat_info(dispcfg, seat_list->seats[i],
85 &sinfo);
86 if (rc != EOK)
87 continue;
88
89 if (str_cmp(sinfo->name, name) == 0) {
90 *rseat_id = seat_list->seats[i];
91 dispcfg_free_seat_info(sinfo);
92 return EOK;
93 }
94
95 dispcfg_free_seat_info(sinfo);
96 }
97
98 return ENOENT;
99}
100
101/** Create seat subcommand.
102 *
103 * @param dcfg_svc Display configuration service name
104 * @param argc Number of arguments
105 * @param argv Arguments
106 * @return EOK on success or an erro code
107 */
108static errno_t create_seat(const char *dcfg_svc, int argc, char *argv[])
109{
110 dispcfg_t *dispcfg;
111 char *seat_name;
112 sysarg_t seat_id;
113 errno_t rc;
114
115 if (argc < 1) {
116 printf(NAME ": Missing arguments.\n");
117 print_syntax();
118 return EINVAL;
119 }
120
121 if (argc > 1) {
122 printf(NAME ": Too many arguments.\n");
123 print_syntax();
124 return EINVAL;
125 }
126
127 seat_name = argv[0];
128
129 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
130 if (rc != EOK) {
131 printf(NAME ": Failed connecting to display configuration "
132 "service: %s.\n", str_error(rc));
133 return rc;
134 }
135
136 rc = dispcfg_seat_create(dispcfg, seat_name, &seat_id);
137 if (rc != EOK) {
138 printf(NAME ": Failed creating seat '%s' (%s)\n",
139 seat_name, str_error(rc));
140 dispcfg_close(dispcfg);
141 return EIO;
142 }
143
144 (void)seat_id;
145 dispcfg_close(dispcfg);
146 return EOK;
147}
148
149/** Delete seat subcommand.
150 *
151 * @param dcfg_svc Display configuration service name
152 * @param argc Number of arguments
153 * @param argv Arguments
154 * @return EOK on success or an erro code
155 */
156static errno_t delete_seat(const char *dcfg_svc, int argc, char *argv[])
157{
158 dispcfg_t *dispcfg;
159 char *seat_name;
160 sysarg_t seat_id;
161 errno_t rc;
162
163 if (argc < 1) {
164 printf(NAME ": Missing arguments.\n");
165 print_syntax();
166 return EINVAL;
167 }
168
169 if (argc > 1) {
170 printf(NAME ": Too many arguments.\n");
171 print_syntax();
172 return EINVAL;
173 }
174
175 seat_name = argv[0];
176
177 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
178 if (rc != EOK) {
179 printf(NAME ": Failed connecting to display configuration "
180 "service: %s.\n", str_error(rc));
181 return rc;
182 }
183
184 rc = seat_find_by_name(dispcfg, seat_name, &seat_id);
185 if (rc != EOK) {
186 printf(NAME ": Seat '%s' not found.\n", seat_name);
187 dispcfg_close(dispcfg);
188 return ENOENT;
189 }
190
191 rc = dispcfg_seat_delete(dispcfg, seat_id);
192 if (rc != EOK) {
193 printf(NAME ": Failed deleting seat '%s': %s\n", seat_name,
194 str_error(rc));
195 dispcfg_close(dispcfg);
196 return EIO;
197 }
198
199 dispcfg_close(dispcfg);
200 return EOK;
201}
202
203/** List seats subcommand.
204 *
205 * @param dcfg_svc Display configuration service name
206 * @param argc Number of arguments
207 * @param argv Arguments
208 * @return EOK on success or an erro code
209 */
210static errno_t list_seat(const char *dcfg_svc, int argc, char *argv[])
211{
212 dispcfg_t *dispcfg;
213 dispcfg_seat_list_t *seat_list;
214 dispcfg_seat_info_t *sinfo;
215 table_t *table = NULL;
216 size_t i;
217 errno_t rc;
218
219 if (argc > 0) {
220 printf(NAME ": Too many arguments.\n");
221 print_syntax();
222 return EINVAL;
223 }
224
225 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
226 if (rc != EOK) {
227 printf(NAME ": Failed connecting to display configuration "
228 "service: %s.\n", str_error(rc));
229 return rc;
230 }
231
232 rc = dispcfg_get_seat_list(dispcfg, &seat_list);
233 if (rc != EOK) {
234 printf(NAME ": Failed getting seat list.\n");
235 dispcfg_close(dispcfg);
236 return rc;
237 }
238
239 rc = table_create(&table);
240 if (rc != EOK) {
241 printf("Memory allocation failed.\n");
242 dispcfg_close(dispcfg);
243 goto out;
244 }
245
246 table_header_row(table);
247 table_printf(table, "Seat Name\n");
248
249 for (i = 0; i < seat_list->nseats; i++) {
250 rc = dispcfg_get_seat_info(dispcfg, seat_list->seats[i],
251 &sinfo);
252 if (rc != EOK) {
253 printf("Failed getting properties of seat %zu.\n",
254 (size_t)seat_list->seats[i]);
255 continue;
256 }
257
258 table_printf(table, "%s\n", sinfo->name);
259
260 dispcfg_free_seat_info(sinfo);
261 }
262
263 if (seat_list->nseats != 0) {
264 rc = table_print_out(table, stdout);
265 if (rc != EOK) {
266 printf("Error printing table.\n");
267 goto out;
268 }
269 }
270
271 rc = EOK;
272out:
273 table_destroy(table);
274 dispcfg_close(dispcfg);
275 return rc;
276}
277
[b3eeae5]278/** Assign device subcommand.
279 *
280 * @param dcfg_svc Display configuration service name
281 * @param argc Number of arguments
282 * @param argv Arguments
283 * @return EOK on success or an erro code
284 */
285static errno_t dev_assign(const char *dcfg_svc, int argc, char *argv[])
286{
287 dispcfg_t *dispcfg;
288 char *dev_name;
289 service_id_t svc_id;
290 char *seat_name;
291 sysarg_t seat_id;
292 errno_t rc;
293
294 if (argc < 2) {
295 printf(NAME ": Missing arguments.\n");
296 print_syntax();
297 return EINVAL;
298 }
299
300 if (argc > 2) {
301 printf(NAME ": Too many arguments.\n");
302 print_syntax();
303 return EINVAL;
304 }
305
306 dev_name = argv[0];
307 seat_name = argv[1];
308
309 rc = loc_service_get_id(dev_name, &svc_id, 0);
310 if (rc != EOK) {
311 printf(NAME ": Device service '%s' not found.\n",
312 dev_name);
313 return ENOENT;
314 }
315
316 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
317 if (rc != EOK) {
318 printf(NAME ": Failed connecting to display configuration "
319 "service: %s.\n", str_error(rc));
320 return rc;
321 }
322
323 rc = seat_find_by_name(dispcfg, seat_name, &seat_id);
324 if (rc != EOK) {
325 printf(NAME ": Seat '%s' not found.\n", seat_name);
326 dispcfg_close(dispcfg);
327 return ENOENT;
328 }
329
330 rc = dispcfg_dev_assign(dispcfg, svc_id, seat_id);
331 if (rc != EOK) {
332 printf(NAME ": Failed assigning device '%s' to seat '%s': "
333 "%s\n", dev_name, seat_name, str_error(rc));
334 dispcfg_close(dispcfg);
335 return EIO;
336 }
337
338 dispcfg_close(dispcfg);
339 return EOK;
340}
341
342/** Unassign device subcommand.
343 *
344 * @param dcfg_svc Display configuration service name
345 * @param argc Number of arguments
346 * @param argv Arguments
347 * @return EOK on success or an erro code
348 */
349static errno_t dev_unassign(const char *dcfg_svc, int argc, char *argv[])
350{
351 dispcfg_t *dispcfg;
352 char *dev_name;
353 service_id_t svc_id;
354 errno_t rc;
355
356 if (argc < 1) {
357 printf(NAME ": Missing arguments.\n");
358 print_syntax();
359 return EINVAL;
360 }
361
362 if (argc > 1) {
363 printf(NAME ": Too many arguments.\n");
364 print_syntax();
365 return EINVAL;
366 }
367
368 dev_name = argv[0];
369
370 rc = loc_service_get_id(dev_name, &svc_id, 0);
371 if (rc != EOK) {
372 printf(NAME ": Device service '%s' not found.\n",
373 dev_name);
374 return ENOENT;
375 }
376
377 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
378 if (rc != EOK) {
379 printf(NAME ": Failed connecting to display configuration "
380 "service: %s.\n", str_error(rc));
381 return rc;
382 }
383
384 rc = dispcfg_dev_unassign(dispcfg, svc_id);
385 if (rc != EOK) {
386 printf(NAME ": Failed unassigning device '%s': %s\n",
387 dev_name, str_error(rc));
388 dispcfg_close(dispcfg);
389 return EIO;
390 }
391
392 dispcfg_close(dispcfg);
393 return EOK;
394}
395
[c0757e1f]396/** List dev subcommand.
397 *
398 * @param dcfg_svc Display configuration service name
399 * @param argc Number of arguments
400 * @param argv Arguments
401 * @return EOK on success or an erro code
402 */
403static errno_t list_dev(const char *dcfg_svc, int argc, char *argv[])
404{
405 dispcfg_t *dispcfg;
406 char *seat_name;
407 sysarg_t seat_id;
408 dispcfg_dev_list_t *dev_list;
409 size_t i;
410 char *svc_name;
411 table_t *table = NULL;
412 errno_t rc;
413
414 if (argc < 1) {
415 printf(NAME ": Missing arguments.\n");
416 print_syntax();
417 return EINVAL;
418 }
419
420 if (argc > 1) {
421 printf(NAME ": Too many arguments.\n");
422 print_syntax();
423 return EINVAL;
424 }
425
426 seat_name = argv[0];
427
428 rc = dispcfg_open(dcfg_svc, NULL, NULL, &dispcfg);
429 if (rc != EOK) {
430 printf(NAME ": Failed connecting to display configuration "
431 "service: %s.\n", str_error(rc));
432 return rc;
433 }
434
435 rc = seat_find_by_name(dispcfg, seat_name, &seat_id);
436 if (rc != EOK) {
437 printf(NAME ": Seat '%s' not found.\n", seat_name);
438 dispcfg_close(dispcfg);
439 return ENOENT;
440 }
441
442 rc = dispcfg_get_asgn_dev_list(dispcfg, seat_id, &dev_list);
443 if (rc != EOK) {
444 printf(NAME ": Failed getting seat list.\n");
445 dispcfg_close(dispcfg);
446 return rc;
447 }
448
449 rc = table_create(&table);
450 if (rc != EOK) {
451 printf("Memory allocation failed.\n");
452 dispcfg_free_dev_list(dev_list);
453 dispcfg_close(dispcfg);
454 return rc;
455 }
456
457 table_header_row(table);
458 table_printf(table, "Device Name\n");
459
460 for (i = 0; i < dev_list->ndevs; i++) {
461 rc = loc_service_get_name(dev_list->devs[i], &svc_name);
462 if (rc != EOK) {
463 printf("Failed getting name of service %zu\n",
464 (size_t)dev_list->devs[i]);
465 continue;
466 }
467
468 table_printf(table, "%s\n", svc_name);
469 free(svc_name);
470 }
471
472 if (dev_list->ndevs != 0) {
473 rc = table_print_out(table, stdout);
474 if (rc != EOK) {
475 printf("Error printing table.\n");
476 table_destroy(table);
477 dispcfg_free_dev_list(dev_list);
478 dispcfg_close(dispcfg);
479 return rc;
480 }
481 }
482
483 dispcfg_close(dispcfg);
484 return EOK;
485}
486
[d8503fd]487int main(int argc, char *argv[])
488{
489 const char *dispcfg_svc = DISPCFG_DEFAULT;
490 errno_t rc;
491
492 if (argc < 2 || str_cmp(argv[1], "-h") == 0) {
493 print_syntax();
494 return 0;
495 }
496
497 if (str_cmp(argv[1], "list-seat") == 0) {
498 rc = list_seat(dispcfg_svc, argc - 2, argv + 2);
499 if (rc != EOK)
500 return 1;
501 } else if (str_cmp(argv[1], "create-seat") == 0) {
502 rc = create_seat(dispcfg_svc, argc - 2, argv + 2);
503 if (rc != EOK)
504 return 1;
505 } else if (str_cmp(argv[1], "delete-seat") == 0) {
506 rc = delete_seat(dispcfg_svc, argc - 2, argv + 2);
507 if (rc != EOK)
508 return 1;
[b3eeae5]509 } else if (str_cmp(argv[1], "assign-dev") == 0) {
510 rc = dev_assign(dispcfg_svc, argc - 2, argv + 2);
511 if (rc != EOK)
512 return 1;
513 } else if (str_cmp(argv[1], "unassign-dev") == 0) {
514 rc = dev_unassign(dispcfg_svc, argc - 2, argv + 2);
515 if (rc != EOK)
516 return 1;
[c0757e1f]517 } else if (str_cmp(argv[1], "list-dev") == 0) {
518 rc = list_dev(dispcfg_svc, argc - 2, argv + 2);
519 if (rc != EOK)
520 return 1;
[d8503fd]521 } else {
522 printf(NAME ": Unknown command '%s'.\n", argv[1]);
523 print_syntax();
524 return 1;
525 }
526
527 return 0;
528}
529
530/** @}
531 */
Note: See TracBrowser for help on using the repository browser.