source: mainline/uspace/lib/graph/graph.c@ a4e78743

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a4e78743 was fafb8e5, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Mechanically lowercase IPC_SET_*/IPC_GET_*

  • Property mode set to 100644
File size: 14.2 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
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 graph
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <inttypes.h>
39#include <stdio.h>
40#include <as.h>
41#include <stdlib.h>
42#include "graph.h"
43
44#define NAMESPACE "graphemu"
45#define VISUALIZER_NAME "vsl"
46#define RENDERER_NAME "rnd"
47
48static sysarg_t namespace_idx = 0;
49static sysarg_t visualizer_idx = 0;
50static sysarg_t renderer_idx = 0;
51
52static LIST_INITIALIZE(visualizer_list);
53static LIST_INITIALIZE(renderer_list);
54
55static FIBRIL_MUTEX_INITIALIZE(visualizer_list_mtx);
56static FIBRIL_MUTEX_INITIALIZE(renderer_list_mtx);
57
58visualizer_t *graph_alloc_visualizer(void)
59{
60 return ((visualizer_t *) malloc(sizeof(visualizer_t)));
61}
62
63renderer_t *graph_alloc_renderer(void)
64{
65 // TODO
66 return ((renderer_t *) malloc(sizeof(renderer_t)));
67}
68
69void graph_init_visualizer(visualizer_t *vs)
70{
71 link_initialize(&vs->link);
72 atomic_flag_clear(&vs->claimed);
73 vs->notif_sess = NULL;
74 fibril_mutex_initialize(&vs->mode_mtx);
75 list_initialize(&vs->modes);
76 vs->mode_set = false;
77 vs->cells.data = NULL;
78 vs->dev_ctx = NULL;
79}
80
81void graph_init_renderer(renderer_t *rnd)
82{
83 // TODO
84 link_initialize(&rnd->link);
85 refcount_init(&rnd->ref_cnt);
86}
87
88errno_t graph_register_visualizer(visualizer_t *vs)
89{
90 char node[LOC_NAME_MAXLEN + 1];
91 snprintf(node, LOC_NAME_MAXLEN, "%s%zu/%s%zu", NAMESPACE,
92 namespace_idx, VISUALIZER_NAME, visualizer_idx++);
93
94 category_id_t cat;
95 errno_t rc = loc_category_get_id("visualizer", &cat, 0);
96 if (rc != EOK)
97 return rc;
98
99 rc = loc_service_register(node, &vs->reg_svc_handle);
100 if (rc != EOK)
101 return rc;
102
103 rc = loc_service_add_to_cat(vs->reg_svc_handle, cat);
104 if (rc != EOK) {
105 loc_service_unregister(vs->reg_svc_handle);
106 return rc;
107 }
108
109 fibril_mutex_lock(&visualizer_list_mtx);
110 list_append(&vs->link, &visualizer_list);
111 fibril_mutex_unlock(&visualizer_list_mtx);
112
113 return rc;
114}
115
116errno_t graph_register_renderer(renderer_t *rnd)
117{
118 char node[LOC_NAME_MAXLEN + 1];
119 snprintf(node, LOC_NAME_MAXLEN, "%s%zu/%s%zu", NAMESPACE,
120 namespace_idx, RENDERER_NAME, renderer_idx++);
121
122 category_id_t cat;
123 errno_t rc = loc_category_get_id("renderer", &cat, 0);
124 if (rc != EOK)
125 return rc;
126
127 rc = loc_service_register(node, &rnd->reg_svc_handle);
128 if (rc != EOK)
129 return rc;
130
131 rc = loc_service_add_to_cat(rnd->reg_svc_handle, cat);
132 if (rc != EOK) {
133 loc_service_unregister(rnd->reg_svc_handle);
134 return rc;
135 }
136
137 fibril_mutex_lock(&renderer_list_mtx);
138 list_append(&rnd->link, &renderer_list);
139 fibril_mutex_unlock(&renderer_list_mtx);
140
141 return rc;
142}
143
144visualizer_t *graph_get_visualizer(sysarg_t handle)
145{
146 visualizer_t *vs = NULL;
147
148 fibril_mutex_lock(&visualizer_list_mtx);
149
150 list_foreach(visualizer_list, link, visualizer_t, vcur) {
151 if (vcur->reg_svc_handle == handle) {
152 vs = vcur;
153 break;
154 }
155 }
156
157 fibril_mutex_unlock(&visualizer_list_mtx);
158
159 return vs;
160}
161
162renderer_t *graph_get_renderer(sysarg_t handle)
163{
164 renderer_t *rnd = NULL;
165
166 fibril_mutex_lock(&renderer_list_mtx);
167
168 list_foreach(renderer_list, link, renderer_t, rcur) {
169 if (rcur->reg_svc_handle == handle) {
170 rnd = rcur;
171 break;
172 }
173 }
174
175 if (rnd)
176 refcount_up(&rnd->ref_cnt);
177
178 fibril_mutex_unlock(&renderer_list_mtx);
179
180 return rnd;
181}
182
183errno_t graph_unregister_visualizer(visualizer_t *vs)
184{
185 fibril_mutex_lock(&visualizer_list_mtx);
186 errno_t rc = loc_service_unregister(vs->reg_svc_handle);
187 list_remove(&vs->link);
188 fibril_mutex_unlock(&visualizer_list_mtx);
189
190 return rc;
191}
192
193errno_t graph_unregister_renderer(renderer_t *rnd)
194{
195 fibril_mutex_lock(&renderer_list_mtx);
196 errno_t rc = loc_service_unregister(rnd->reg_svc_handle);
197 list_remove(&rnd->link);
198 fibril_mutex_unlock(&renderer_list_mtx);
199
200 return rc;
201}
202
203void graph_destroy_visualizer(visualizer_t *vs)
204{
205 assert(!atomic_flag_test_and_set(&vs->claimed));
206 assert(vs->notif_sess == NULL);
207 assert(!fibril_mutex_is_locked(&vs->mode_mtx));
208 assert(list_empty(&vs->modes));
209 assert(vs->mode_set == false);
210 assert(vs->cells.data == NULL);
211 assert(vs->dev_ctx == NULL);
212
213 free(vs);
214}
215
216void graph_destroy_renderer(renderer_t *rnd)
217{
218 // TODO
219 if (refcount_down(&rnd->ref_cnt))
220 free(rnd);
221}
222
223errno_t graph_notify_mode_change(async_sess_t *sess, sysarg_t handle, sysarg_t mode_idx)
224{
225 async_exch_t *exch = async_exchange_begin(sess);
226 errno_t ret = async_req_2_0(exch, VISUALIZER_MODE_CHANGE, handle, mode_idx);
227 async_exchange_end(exch);
228
229 return ret;
230}
231
232errno_t graph_notify_disconnect(async_sess_t *sess, sysarg_t handle)
233{
234 async_exch_t *exch = async_exchange_begin(sess);
235 errno_t ret = async_req_1_0(exch, VISUALIZER_DISCONNECT, handle);
236 async_exchange_end(exch);
237
238 async_hangup(sess);
239
240 return ret;
241}
242
243static void vs_claim(visualizer_t *vs, ipc_call_t *icall)
244{
245 vs->client_side_handle = ipc_get_arg1(icall);
246 errno_t rc = vs->ops.claim(vs);
247 async_answer_0(icall, rc);
248}
249
250static void vs_yield(visualizer_t *vs, ipc_call_t *icall)
251{
252 /* Deallocate resources for the current mode. */
253 if (vs->mode_set) {
254 if (vs->cells.data != NULL) {
255 as_area_destroy((void *) vs->cells.data);
256 vs->cells.data = NULL;
257 }
258 }
259
260 /* Driver might also deallocate resources for the current mode. */
261 errno_t rc = vs->ops.yield(vs);
262
263 /*
264 * Now that the driver was given a chance to deallocate resources,
265 * current mode can be unset.
266 */
267 if (vs->mode_set)
268 vs->mode_set = false;
269
270 async_answer_0(icall, rc);
271}
272
273static void vs_enumerate_modes(visualizer_t *vs, ipc_call_t *icall)
274{
275 size_t len;
276
277 ipc_call_t call;
278 if (!async_data_read_receive(&call, &len)) {
279 async_answer_0(&call, EREFUSED);
280 async_answer_0(icall, EREFUSED);
281 return;
282 }
283
284 fibril_mutex_lock(&vs->mode_mtx);
285 link_t *link = list_nth(&vs->modes, ipc_get_arg1(icall));
286
287 if (link != NULL) {
288 vslmode_list_element_t *mode_elem =
289 list_get_instance(link, vslmode_list_element_t, link);
290
291 errno_t rc = async_data_read_finalize(&call, &mode_elem->mode, len);
292 async_answer_0(icall, rc);
293 } else {
294 async_answer_0(&call, ENOENT);
295 async_answer_0(icall, ENOENT);
296 }
297
298 fibril_mutex_unlock(&vs->mode_mtx);
299}
300
301static void vs_get_default_mode(visualizer_t *vs, ipc_call_t *icall)
302{
303 ipc_call_t call;
304 size_t len;
305 if (!async_data_read_receive(&call, &len)) {
306 async_answer_0(&call, EREFUSED);
307 async_answer_0(icall, EREFUSED);
308 return;
309 }
310
311 fibril_mutex_lock(&vs->mode_mtx);
312 vslmode_list_element_t *mode_elem = NULL;
313
314 list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
315 if (cur->mode.index == vs->def_mode_idx) {
316 mode_elem = cur;
317 break;
318 }
319 }
320
321 if (mode_elem != NULL) {
322 errno_t rc = async_data_read_finalize(&call, &mode_elem->mode, len);
323 async_answer_0(icall, rc);
324 } else {
325 fibril_mutex_unlock(&vs->mode_mtx);
326 async_answer_0(&call, ENOENT);
327 async_answer_0(icall, ENOENT);
328 }
329
330 fibril_mutex_unlock(&vs->mode_mtx);
331}
332
333static void vs_get_current_mode(visualizer_t *vs, ipc_call_t *icall)
334{
335 ipc_call_t call;
336 size_t len;
337 if (!async_data_read_receive(&call, &len)) {
338 async_answer_0(&call, EREFUSED);
339 async_answer_0(icall, EREFUSED);
340 return;
341 }
342
343 if (vs->mode_set) {
344 errno_t rc = async_data_read_finalize(&call, &vs->cur_mode, len);
345 async_answer_0(icall, rc);
346 } else {
347 async_answer_0(&call, ENOENT);
348 async_answer_0(icall, ENOENT);
349 }
350}
351
352static void vs_get_mode(visualizer_t *vs, ipc_call_t *icall)
353{
354 ipc_call_t call;
355 size_t len;
356 if (!async_data_read_receive(&call, &len)) {
357 async_answer_0(&call, EREFUSED);
358 async_answer_0(icall, EREFUSED);
359 return;
360 }
361
362 sysarg_t mode_idx = ipc_get_arg1(icall);
363
364 fibril_mutex_lock(&vs->mode_mtx);
365 vslmode_list_element_t *mode_elem = NULL;
366
367 list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
368 if (cur->mode.index == mode_idx) {
369 mode_elem = cur;
370 break;
371 }
372 }
373
374 if (mode_elem != NULL) {
375 errno_t rc = async_data_read_finalize(&call, &mode_elem->mode, len);
376 async_answer_0(icall, rc);
377 } else {
378 async_answer_0(&call, ENOENT);
379 async_answer_0(icall, ENOENT);
380 }
381
382 fibril_mutex_unlock(&vs->mode_mtx);
383}
384
385static void vs_set_mode(visualizer_t *vs, ipc_call_t *icall)
386{
387 ipc_call_t call;
388 size_t size;
389 unsigned int flags;
390
391 /* Retrieve the shared cell storage for the new mode. */
392 if (!async_share_out_receive(&call, &size, &flags)) {
393 async_answer_0(&call, EREFUSED);
394 async_answer_0(icall, EREFUSED);
395 return;
396 }
397
398 /* Retrieve mode index and version. */
399 sysarg_t mode_idx = ipc_get_arg1(icall);
400 sysarg_t mode_version = ipc_get_arg2(icall);
401
402 /* Find mode in the list. */
403 fibril_mutex_lock(&vs->mode_mtx);
404 vslmode_list_element_t *mode_elem = NULL;
405
406 list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
407 if (cur->mode.index == mode_idx) {
408 mode_elem = cur;
409 break;
410 }
411 }
412
413 if (mode_elem == NULL) {
414 fibril_mutex_unlock(&vs->mode_mtx);
415 async_answer_0(&call, ENOENT);
416 async_answer_0(icall, ENOENT);
417 return;
418 }
419
420 /* Extract mode description from the list node. */
421 vslmode_t new_mode = mode_elem->mode;
422 fibril_mutex_unlock(&vs->mode_mtx);
423
424 /* Check whether the mode is still up-to-date. */
425 if (new_mode.version != mode_version) {
426 async_answer_0(&call, EINVAL);
427 async_answer_0(icall, EINVAL);
428 return;
429 }
430
431 void *new_cell_storage;
432 errno_t rc = async_share_out_finalize(&call, &new_cell_storage);
433 if ((rc != EOK) || (new_cell_storage == AS_MAP_FAILED)) {
434 async_answer_0(icall, ENOMEM);
435 return;
436 }
437
438 /* Change device internal state. */
439 rc = vs->ops.change_mode(vs, new_mode);
440
441 /* Device driver could not establish new mode. Rollback. */
442 if (rc != EOK) {
443 as_area_destroy(new_cell_storage);
444 async_answer_0(icall, ENOMEM);
445 return;
446 }
447
448 /*
449 * Because resources for the new mode were successfully
450 * claimed, it is finally possible to free resources
451 * allocated for the old mode.
452 */
453 if (vs->mode_set) {
454 if (vs->cells.data != NULL) {
455 as_area_destroy((void *) vs->cells.data);
456 vs->cells.data = NULL;
457 }
458 }
459
460 /* Insert new mode into the visualizer. */
461 vs->cells.width = new_mode.screen_width;
462 vs->cells.height = new_mode.screen_height;
463 vs->cells.data = (pixel_t *) new_cell_storage;
464 vs->cur_mode = new_mode;
465 vs->mode_set = true;
466
467 async_answer_0(icall, EOK);
468}
469
470static void vs_update_damaged_region(visualizer_t *vs, ipc_call_t *icall)
471{
472 sysarg_t x_offset = (ipc_get_arg5(icall) >> 16);
473 sysarg_t y_offset = (ipc_get_arg5(icall) & 0x0000ffff);
474
475 errno_t rc = vs->ops.handle_damage(vs,
476 ipc_get_arg1(icall), ipc_get_arg2(icall),
477 ipc_get_arg3(icall), ipc_get_arg4(icall),
478 x_offset, y_offset);
479 async_answer_0(icall, rc);
480}
481
482static void vs_suspend(visualizer_t *vs, ipc_call_t *icall)
483{
484 errno_t rc = vs->ops.suspend(vs);
485 async_answer_0(icall, rc);
486}
487
488static void vs_wakeup(visualizer_t *vs, ipc_call_t *icall)
489{
490 errno_t rc = vs->ops.wakeup(vs);
491 async_answer_0(icall, rc);
492}
493
494void graph_visualizer_connection(visualizer_t *vs, ipc_call_t *icall, void *arg)
495{
496 /* Claim the visualizer. */
497 if (atomic_flag_test_and_set(&vs->claimed)) {
498 async_answer_0(icall, ELIMIT);
499 return;
500 }
501
502 /* Accept the connection. */
503 async_accept_0(icall);
504
505 /* Establish callback session. */
506 ipc_call_t call;
507 async_get_call(&call);
508 vs->notif_sess = async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
509 if (vs->notif_sess != NULL)
510 async_answer_0(&call, EOK);
511 else
512 async_answer_0(&call, ELIMIT);
513
514 /* Enter command loop. */
515 while (true) {
516 async_get_call(&call);
517
518 if (!ipc_get_imethod(&call)) {
519 async_answer_0(&call, EOK);
520 break;
521 }
522
523 switch (ipc_get_imethod(&call)) {
524 case VISUALIZER_CLAIM:
525 vs_claim(vs, &call);
526 break;
527 case VISUALIZER_YIELD:
528 vs_yield(vs, &call);
529 goto terminate;
530 case VISUALIZER_ENUMERATE_MODES:
531 vs_enumerate_modes(vs, &call);
532 break;
533 case VISUALIZER_GET_DEFAULT_MODE:
534 vs_get_default_mode(vs, &call);
535 break;
536 case VISUALIZER_GET_CURRENT_MODE:
537 vs_get_current_mode(vs, &call);
538 break;
539 case VISUALIZER_GET_MODE:
540 vs_get_mode(vs, &call);
541 break;
542 case VISUALIZER_SET_MODE:
543 vs_set_mode(vs, &call);
544 break;
545 case VISUALIZER_UPDATE_DAMAGED_REGION:
546 vs_update_damaged_region(vs, &call);
547 break;
548 case VISUALIZER_SUSPEND:
549 vs_suspend(vs, &call);
550 break;
551 case VISUALIZER_WAKE_UP:
552 vs_wakeup(vs, &call);
553 break;
554 default:
555 async_answer_0(&call, EINVAL);
556 goto terminate;
557 }
558 }
559
560terminate:
561 async_hangup(vs->notif_sess);
562 vs->notif_sess = NULL;
563 atomic_flag_clear(&vs->claimed);
564}
565
566void graph_renderer_connection(renderer_t *rnd, ipc_call_t *icall, void *arg)
567{
568 // TODO
569
570 /* Accept the connection. */
571 async_accept_0(icall);
572
573 /* Enter command loop. */
574 while (true) {
575 ipc_call_t call;
576 async_get_call(&call);
577
578 if (!ipc_get_imethod(&call)) {
579 async_answer_0(&call, EOK);
580 break;
581 }
582
583 switch (ipc_get_imethod(&call)) {
584 default:
585 async_answer_0(&call, EINVAL);
586 goto terminate;
587 }
588 }
589
590terminate:
591 graph_destroy_renderer(rnd);
592}
593
594void graph_client_connection(ipc_call_t *icall, void *arg)
595{
596 /* Find the visualizer or renderer with the given service ID. */
597 visualizer_t *vs = graph_get_visualizer(ipc_get_arg2(icall));
598 renderer_t *rnd = graph_get_renderer(ipc_get_arg2(icall));
599
600 if (vs != NULL)
601 graph_visualizer_connection(vs, icall, arg);
602 else if (rnd != NULL)
603 graph_renderer_connection(rnd, icall, arg);
604 else
605 async_answer_0(icall, ENOENT);
606}
607
608/** @}
609 */
Note: See TracBrowser for help on using the repository browser.