source: mainline/uspace/lib/dispcfg/src/dispcfg_srv.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: 10.6 KB
Line 
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 libdispcfg
30 * @{
31 */
32/**
33 * @file
34 * @brief Display configuration protocol server stub
35 */
36
37#include <dispcfg.h>
38#include <dispcfg_srv.h>
39#include <errno.h>
40#include <ipc/dispcfg.h>
41#include <mem.h>
42#include <stdlib.h>
43#include <stddef.h>
44#include <str.h>
45#include "../private/dispcfg.h"
46
47static void dispcfg_callback_create_srv(dispcfg_srv_t *srv, ipc_call_t *call)
48{
49 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
50 if (sess == NULL) {
51 async_answer_0(call, ENOMEM);
52 return;
53 }
54
55 srv->client_sess = sess;
56 async_answer_0(call, EOK);
57}
58
59static void dispcfg_get_seat_list_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
60{
61 ipc_call_t call;
62 dispcfg_seat_list_t *list = NULL;
63 size_t size;
64 errno_t rc;
65
66 if (srv->ops->get_seat_list == NULL) {
67 async_answer_0(icall, ENOTSUP);
68 return;
69 }
70
71 rc = srv->ops->get_seat_list(srv->arg, &list);
72 if (rc != EOK) {
73 async_answer_0(icall, rc);
74 return;
75 }
76
77 /* Send list size */
78
79 if (!async_data_read_receive(&call, &size)) {
80 dispcfg_free_seat_list(list);
81 async_answer_0(&call, EREFUSED);
82 async_answer_0(icall, EREFUSED);
83 return;
84 }
85
86 if (size != sizeof(list->nseats)) {
87 dispcfg_free_seat_list(list);
88 async_answer_0(&call, EINVAL);
89 async_answer_0(icall, EINVAL);
90 return;
91 }
92
93 rc = async_data_read_finalize(&call, &list->nseats, size);
94 if (rc != EOK) {
95 dispcfg_free_seat_list(list);
96 async_answer_0(&call, rc);
97 async_answer_0(icall, rc);
98 return;
99 }
100
101 /* Send seat list */
102
103 if (!async_data_read_receive(&call, &size)) {
104 dispcfg_free_seat_list(list);
105 async_answer_0(&call, EREFUSED);
106 async_answer_0(icall, EREFUSED);
107 return;
108 }
109
110 if (size != list->nseats * sizeof(sysarg_t)) {
111 dispcfg_free_seat_list(list);
112 async_answer_0(&call, EINVAL);
113 async_answer_0(icall, EINVAL);
114 return;
115 }
116
117 rc = async_data_read_finalize(&call, list->seats, size);
118 if (rc != EOK) {
119 dispcfg_free_seat_list(list);
120 async_answer_0(&call, rc);
121 async_answer_0(icall, rc);
122 return;
123 }
124
125 async_answer_0(icall, EOK);
126 dispcfg_free_seat_list(list);
127}
128
129static void dispcfg_get_seat_info_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
130{
131 sysarg_t seat_id;
132 ipc_call_t call;
133 dispcfg_seat_info_t *info = NULL;
134 size_t namesize;
135 size_t size;
136 errno_t rc;
137
138 seat_id = ipc_get_arg1(icall);
139
140 if (srv->ops->get_seat_info == NULL) {
141 async_answer_0(icall, ENOTSUP);
142 return;
143 }
144
145 rc = srv->ops->get_seat_info(srv->arg, seat_id, &info);
146 if (rc != EOK) {
147 async_answer_0(icall, rc);
148 return;
149 }
150
151 /* Send name size */
152
153 if (!async_data_read_receive(&call, &size)) {
154 dispcfg_free_seat_info(info);
155 async_answer_0(&call, EREFUSED);
156 async_answer_0(icall, EREFUSED);
157 return;
158 }
159
160 if (size != sizeof(size_t)) {
161 dispcfg_free_seat_info(info);
162 async_answer_0(&call, EINVAL);
163 async_answer_0(icall, EINVAL);
164 return;
165 }
166
167 namesize = str_size(info->name);
168
169 rc = async_data_read_finalize(&call, &namesize, size);
170 if (rc != EOK) {
171 dispcfg_free_seat_info(info);
172 async_answer_0(&call, rc);
173 async_answer_0(icall, rc);
174 return;
175 }
176
177 /* Send name */
178
179 if (!async_data_read_receive(&call, &size)) {
180 dispcfg_free_seat_info(info);
181 async_answer_0(&call, EREFUSED);
182 async_answer_0(icall, EREFUSED);
183 return;
184 }
185
186 if (size != namesize) {
187 dispcfg_free_seat_info(info);
188 async_answer_0(&call, EINVAL);
189 async_answer_0(icall, EINVAL);
190 return;
191 }
192
193 rc = async_data_read_finalize(&call, info->name, size);
194 if (rc != EOK) {
195 dispcfg_free_seat_info(info);
196 async_answer_0(&call, rc);
197 async_answer_0(icall, rc);
198 return;
199 }
200
201 async_answer_0(icall, EOK);
202 dispcfg_free_seat_info(info);
203}
204
205static void dispcfg_seat_create_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
206{
207 sysarg_t seat_id;
208 ipc_call_t call;
209 char *name;
210 size_t size;
211 errno_t rc;
212
213 if (!async_data_write_receive(&call, &size)) {
214 async_answer_0(&call, EREFUSED);
215 async_answer_0(icall, EREFUSED);
216 return;
217 }
218
219 name = calloc(size + 1, 1);
220 if (name == NULL) {
221 async_answer_0(&call, ENOMEM);
222 async_answer_0(icall, ENOMEM);
223 return;
224 }
225
226 rc = async_data_write_finalize(&call, name, size);
227 if (rc != EOK) {
228 free(name);
229 async_answer_0(&call, rc);
230 async_answer_0(icall, rc);
231 return;
232 }
233
234 if (srv->ops->seat_create == NULL) {
235 free(name);
236 async_answer_0(icall, ENOTSUP);
237 return;
238 }
239
240 rc = srv->ops->seat_create(srv->arg, name, &seat_id);
241 async_answer_1(icall, rc, seat_id);
242 free(name);
243}
244
245static void dispcfg_seat_delete_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
246{
247 sysarg_t seat_id;
248 errno_t rc;
249
250 seat_id = ipc_get_arg1(icall);
251
252 if (srv->ops->seat_delete == NULL) {
253 async_answer_0(icall, ENOTSUP);
254 return;
255 }
256
257 rc = srv->ops->seat_delete(srv->arg, seat_id);
258 async_answer_0(icall, rc);
259}
260
261static void dispcfg_dev_assign_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
262{
263 sysarg_t svc_id;
264 sysarg_t seat_id;
265 errno_t rc;
266
267 svc_id = ipc_get_arg1(icall);
268 seat_id = ipc_get_arg2(icall);
269
270 if (srv->ops->dev_assign == NULL) {
271 async_answer_0(icall, ENOTSUP);
272 return;
273 }
274
275 rc = srv->ops->dev_assign(srv->arg, svc_id, seat_id);
276 async_answer_0(icall, rc);
277}
278
279static void dispcfg_dev_unassign_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
280{
281 sysarg_t svc_id;
282 errno_t rc;
283
284 svc_id = ipc_get_arg1(icall);
285
286 if (srv->ops->dev_unassign == NULL) {
287 async_answer_0(icall, ENOTSUP);
288 return;
289 }
290
291 rc = srv->ops->dev_unassign(srv->arg, svc_id);
292 async_answer_0(icall, rc);
293}
294
295static void dispcfg_get_asgn_dev_list_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
296{
297 sysarg_t seat_id;
298 ipc_call_t call;
299 dispcfg_dev_list_t *list = NULL;
300 size_t size;
301 errno_t rc;
302
303 seat_id = ipc_get_arg1(icall);
304
305 if (srv->ops->get_asgn_dev_list == NULL) {
306 async_answer_0(icall, ENOTSUP);
307 return;
308 }
309
310 rc = srv->ops->get_asgn_dev_list(srv->arg, seat_id, &list);
311 if (rc != EOK) {
312 async_answer_0(icall, rc);
313 return;
314 }
315
316 /* Send list size */
317
318 if (!async_data_read_receive(&call, &size)) {
319 dispcfg_free_dev_list(list);
320 async_answer_0(&call, EREFUSED);
321 async_answer_0(icall, EREFUSED);
322 return;
323 }
324
325 if (size != sizeof(list->ndevs)) {
326 dispcfg_free_dev_list(list);
327 async_answer_0(&call, EINVAL);
328 async_answer_0(icall, EINVAL);
329 return;
330 }
331
332 rc = async_data_read_finalize(&call, &list->ndevs, size);
333 if (rc != EOK) {
334 dispcfg_free_dev_list(list);
335 async_answer_0(&call, rc);
336 async_answer_0(icall, rc);
337 return;
338 }
339
340 /* Send device list */
341
342 if (!async_data_read_receive(&call, &size)) {
343 dispcfg_free_dev_list(list);
344 async_answer_0(&call, EREFUSED);
345 async_answer_0(icall, EREFUSED);
346 return;
347 }
348
349 if (size != list->ndevs * sizeof(sysarg_t)) {
350 dispcfg_free_dev_list(list);
351 async_answer_0(&call, EINVAL);
352 async_answer_0(icall, EINVAL);
353 return;
354 }
355
356 rc = async_data_read_finalize(&call, list->devs, size);
357 if (rc != EOK) {
358 dispcfg_free_dev_list(list);
359 async_answer_0(&call, rc);
360 async_answer_0(icall, rc);
361 return;
362 }
363
364 async_answer_0(icall, EOK);
365 dispcfg_free_dev_list(list);
366}
367
368static void dispcfg_get_event_srv(dispcfg_srv_t *srv, ipc_call_t *icall)
369{
370 dispcfg_ev_t event;
371 ipc_call_t call;
372 size_t size;
373 errno_t rc;
374
375 if (srv->ops->get_event == NULL) {
376 async_answer_0(icall, ENOTSUP);
377 return;
378 }
379
380 rc = srv->ops->get_event(srv->arg, &event);
381 if (rc != EOK) {
382 async_answer_0(icall, rc);
383 return;
384 }
385
386 /* Transfer event data */
387 if (!async_data_read_receive(&call, &size)) {
388 async_answer_0(&call, EREFUSED);
389 async_answer_0(icall, EREFUSED);
390 return;
391 }
392
393 if (size != sizeof(event)) {
394 async_answer_0(&call, EREFUSED);
395 async_answer_0(icall, EREFUSED);
396 return;
397 }
398
399 rc = async_data_read_finalize(&call, &event, sizeof(event));
400 if (rc != EOK) {
401 async_answer_0(&call, rc);
402 async_answer_0(icall, rc);
403 return;
404 }
405
406 async_answer_0(icall, EOK);
407}
408
409void dispcfg_conn(ipc_call_t *icall, dispcfg_srv_t *srv)
410{
411 /* Accept the connection */
412 async_accept_0(icall);
413
414 while (true) {
415 ipc_call_t call;
416
417 async_get_call(&call);
418 sysarg_t method = ipc_get_imethod(&call);
419
420 if (!method) {
421 /* The other side has hung up */
422 async_answer_0(&call, EOK);
423 break;
424 }
425
426 switch (method) {
427 case DISPCFG_CALLBACK_CREATE:
428 dispcfg_callback_create_srv(srv, &call);
429 break;
430 case DISPCFG_GET_SEAT_LIST:
431 dispcfg_get_seat_list_srv(srv, &call);
432 break;
433 case DISPCFG_GET_SEAT_INFO:
434 dispcfg_get_seat_info_srv(srv, &call);
435 break;
436 case DISPCFG_SEAT_CREATE:
437 dispcfg_seat_create_srv(srv, &call);
438 break;
439 case DISPCFG_SEAT_DELETE:
440 dispcfg_seat_delete_srv(srv, &call);
441 break;
442 case DISPCFG_DEV_ASSIGN:
443 dispcfg_dev_assign_srv(srv, &call);
444 break;
445 case DISPCFG_DEV_UNASSIGN:
446 dispcfg_dev_unassign_srv(srv, &call);
447 break;
448 case DISPCFG_GET_ASGN_DEV_LIST:
449 dispcfg_get_asgn_dev_list_srv(srv, &call);
450 break;
451 case DISPCFG_GET_EVENT:
452 dispcfg_get_event_srv(srv, &call);
453 break;
454 default:
455 async_answer_0(&call, ENOTSUP);
456 }
457 }
458
459 /* Hang up callback session */
460 if (srv->client_sess != NULL) {
461 async_hangup(srv->client_sess);
462 srv->client_sess = NULL;
463 }
464}
465
466/** Initialize display configuration server structure
467 *
468 * @param srv Display configuration server structure to initialize
469 */
470void dispcfg_srv_initialize(dispcfg_srv_t *srv)
471{
472 memset(srv, 0, sizeof(*srv));
473}
474
475/** Send 'pending' event to client.
476 *
477 * @param srv Display configuration server structure
478 */
479void dispcfg_srv_ev_pending(dispcfg_srv_t *srv)
480{
481 async_exch_t *exch;
482
483 exch = async_exchange_begin(srv->client_sess);
484 async_msg_0(exch, DISPCFG_EV_PENDING);
485 async_exchange_end(exch);
486}
487
488/** @}
489 */
Note: See TracBrowser for help on using the repository browser.