source: mainline/uspace/lib/c/generic/io/con_srv.c@ 984a9ba

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 984a9ba was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/*
2 * Copyright (c) 2012 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 libc
30 * @{
31 */
32/**
33 * @file
34 * @brief Console protocol server stub
35 */
36#include <errno.h>
37#include <io/cons_event.h>
38#include <ipc/console.h>
39#include <stdlib.h>
40#include <stddef.h>
41
42#include <io/con_srv.h>
43
44static errno_t console_ev_encode(cons_event_t *event, ipc_call_t *icall)
45{
46 IPC_SET_ARG1(*icall, event->type);
47
48 switch (event->type) {
49 case CEV_KEY:
50 IPC_SET_ARG2(*icall, event->ev.key.type);
51 IPC_SET_ARG3(*icall, event->ev.key.key);
52 IPC_SET_ARG4(*icall, event->ev.key.mods);
53 IPC_SET_ARG5(*icall, event->ev.key.c);
54 break;
55 case CEV_POS:
56 IPC_SET_ARG2(*icall, (event->ev.pos.pos_id << 16) | (event->ev.pos.type & 0xffff));
57 IPC_SET_ARG3(*icall, event->ev.pos.btn_num);
58 IPC_SET_ARG4(*icall, event->ev.pos.hpos);
59 IPC_SET_ARG5(*icall, event->ev.pos.vpos);
60 break;
61 default:
62 return EIO;
63 }
64
65 return EOK;
66}
67
68static void con_read_srv(con_srv_t *srv, ipc_call_t *icall)
69{
70 void *buf;
71 size_t size;
72 errno_t rc;
73
74 ipc_call_t call;
75 if (!async_data_read_receive(&call, &size)) {
76 async_answer_0(icall, EINVAL);
77 return;
78 }
79
80 buf = malloc(size);
81 if (buf == NULL) {
82 async_answer_0(&call, ENOMEM);
83 async_answer_0(icall, ENOMEM);
84 return;
85 }
86
87 if (srv->srvs->ops->read == NULL) {
88 async_answer_0(&call, ENOTSUP);
89 async_answer_0(icall, ENOTSUP);
90 free(buf);
91 return;
92 }
93
94 size_t nread;
95 rc = srv->srvs->ops->read(srv, buf, size, &nread);
96 if (rc != EOK) {
97 async_answer_0(&call, rc);
98 async_answer_0(icall, rc);
99 free(buf);
100 return;
101 }
102
103 async_data_read_finalize(&call, buf, nread);
104 free(buf);
105
106 async_answer_1(icall, EOK, nread);
107}
108
109static void con_write_srv(con_srv_t *srv, ipc_call_t *icall)
110{
111 void *data;
112 size_t size;
113 errno_t rc;
114
115 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
116 if (rc != EOK) {
117 async_answer_0(icall, rc);
118 return;
119 }
120
121 if (srv->srvs->ops->write == NULL) {
122 async_answer_0(icall, ENOTSUP);
123 return;
124 }
125
126 size_t nwritten = 0;
127 rc = srv->srvs->ops->write(srv, data, size, &nwritten);
128 free(data);
129
130 async_answer_1(icall, rc, nwritten);
131}
132
133static void con_sync_srv(con_srv_t *srv, ipc_call_t *icall)
134{
135 if (srv->srvs->ops->sync == NULL) {
136 async_answer_0(icall, ENOTSUP);
137 return;
138 }
139
140 srv->srvs->ops->sync(srv);
141 async_answer_0(icall, EOK);
142}
143
144static void con_clear_srv(con_srv_t *srv, ipc_call_t *icall)
145{
146 if (srv->srvs->ops->clear == NULL) {
147 async_answer_0(icall, ENOTSUP);
148 return;
149 }
150
151 srv->srvs->ops->clear(srv);
152 async_answer_0(icall, EOK);
153}
154
155static void con_set_pos_srv(con_srv_t *srv, ipc_call_t *icall)
156{
157 sysarg_t col;
158 sysarg_t row;
159
160 col = IPC_GET_ARG1(*icall);
161 row = IPC_GET_ARG2(*icall);
162
163 if (srv->srvs->ops->set_pos == NULL) {
164 async_answer_0(icall, ENOTSUP);
165 return;
166 }
167
168 srv->srvs->ops->set_pos(srv, col, row);
169 async_answer_0(icall, EOK);
170}
171
172static void con_get_pos_srv(con_srv_t *srv, ipc_call_t *icall)
173{
174 errno_t rc;
175 sysarg_t col;
176 sysarg_t row;
177
178 if (srv->srvs->ops->get_pos == NULL) {
179 async_answer_0(icall, ENOTSUP);
180 return;
181 }
182
183 rc = srv->srvs->ops->get_pos(srv, &col, &row);
184 async_answer_2(icall, rc, col, row);
185}
186
187static void con_get_size_srv(con_srv_t *srv, ipc_call_t *icall)
188{
189 errno_t rc;
190 sysarg_t cols;
191 sysarg_t rows;
192
193 if (srv->srvs->ops->get_size == NULL) {
194 async_answer_0(icall, ENOTSUP);
195 return;
196 }
197
198 rc = srv->srvs->ops->get_size(srv, &cols, &rows);
199 async_answer_2(icall, rc, cols, rows);
200}
201
202static void con_get_color_cap_srv(con_srv_t *srv, ipc_call_t *icall)
203{
204 errno_t rc;
205 console_caps_t ccap;
206
207 if (srv->srvs->ops->get_color_cap == NULL) {
208 async_answer_0(icall, ENOTSUP);
209 return;
210 }
211
212 rc = srv->srvs->ops->get_color_cap(srv, &ccap);
213 async_answer_1(icall, rc, (sysarg_t)ccap);
214}
215
216static void con_set_style_srv(con_srv_t *srv, ipc_call_t *icall)
217{
218 console_style_t style;
219
220 style = IPC_GET_ARG1(*icall);
221
222 if (srv->srvs->ops->set_style == NULL) {
223 async_answer_0(icall, ENOTSUP);
224 return;
225 }
226
227 srv->srvs->ops->set_style(srv, style);
228 async_answer_0(icall, EOK);
229}
230
231static void con_set_color_srv(con_srv_t *srv, ipc_call_t *icall)
232{
233 console_color_t bgcolor;
234 console_color_t fgcolor;
235 console_color_attr_t flags;
236
237 bgcolor = IPC_GET_ARG1(*icall);
238 fgcolor = IPC_GET_ARG2(*icall);
239 flags = IPC_GET_ARG3(*icall);
240
241 if (srv->srvs->ops->set_color == NULL) {
242 async_answer_0(icall, ENOTSUP);
243 return;
244 }
245
246 srv->srvs->ops->set_color(srv, bgcolor, fgcolor, flags);
247 async_answer_0(icall, EOK);
248}
249
250static void con_set_rgb_color_srv(con_srv_t *srv, ipc_call_t *icall)
251{
252 pixel_t bgcolor;
253 pixel_t fgcolor;
254
255 bgcolor = IPC_GET_ARG1(*icall);
256 fgcolor = IPC_GET_ARG2(*icall);
257
258 if (srv->srvs->ops->set_rgb_color == NULL) {
259 async_answer_0(icall, ENOTSUP);
260 return;
261 }
262
263 srv->srvs->ops->set_rgb_color(srv, bgcolor, fgcolor);
264 async_answer_0(icall, EOK);
265}
266
267static void con_set_cursor_visibility_srv(con_srv_t *srv, ipc_call_t *icall)
268{
269 bool show;
270
271 show = IPC_GET_ARG1(*icall);
272
273 if (srv->srvs->ops->set_cursor_visibility == NULL) {
274 async_answer_0(icall, ENOTSUP);
275 return;
276 }
277
278 srv->srvs->ops->set_cursor_visibility(srv, show);
279 async_answer_0(icall, EOK);
280}
281
282static void con_get_event_srv(con_srv_t *srv, ipc_call_t *icall)
283{
284 errno_t rc;
285 cons_event_t event;
286 ipc_call_t result;
287
288 if (srv->srvs->ops->get_event == NULL) {
289 async_answer_0(icall, ENOTSUP);
290 return;
291 }
292
293 rc = srv->srvs->ops->get_event(srv, &event);
294 if (rc != EOK) {
295 async_answer_0(icall, rc);
296 return;
297 }
298
299 rc = console_ev_encode(&event, &result);
300 if (rc != EOK) {
301 async_answer_0(icall, rc);
302 return;
303 }
304
305 async_answer_5(icall, rc, IPC_GET_ARG1(result), IPC_GET_ARG2(result),
306 IPC_GET_ARG3(result), IPC_GET_ARG4(result), IPC_GET_ARG5(result));
307}
308
309static con_srv_t *con_srv_create(con_srvs_t *srvs)
310{
311 con_srv_t *srv;
312
313 srv = calloc(1, sizeof(*srv));
314 if (srv == NULL)
315 return NULL;
316
317 srv->srvs = srvs;
318 return srv;
319}
320
321void con_srvs_init(con_srvs_t *srvs)
322{
323 srvs->ops = NULL;
324 srvs->sarg = NULL;
325 srvs->abort_timeout = 0;
326 srvs->aborted = false;
327}
328
329errno_t con_conn(ipc_call_t *icall, con_srvs_t *srvs)
330{
331 con_srv_t *srv;
332 errno_t rc;
333
334 /* Accept the connection */
335 async_answer_0(icall, EOK);
336
337 srv = con_srv_create(srvs);
338 if (srv == NULL)
339 return ENOMEM;
340
341 srv->client_sess = NULL;
342
343 rc = srvs->ops->open(srvs, srv);
344 if (rc != EOK)
345 return rc;
346
347 while (true) {
348 ipc_call_t call;
349 bool received = false;
350
351 while (!received) {
352 /* XXX Need to be able to abort immediately */
353 received = async_get_call_timeout(&call,
354 srvs->abort_timeout);
355
356 if (srv->srvs->aborted) {
357 if (received)
358 async_answer_0(&call, EINTR);
359 break;
360 }
361 }
362
363 if (!received)
364 break;
365
366 sysarg_t method = IPC_GET_IMETHOD(call);
367
368 if (!method) {
369 /* The other side has hung up */
370 async_answer_0(&call, EOK);
371 break;
372 }
373
374 switch (method) {
375 case VFS_OUT_READ:
376 con_read_srv(srv, &call);
377 break;
378 case VFS_OUT_WRITE:
379 con_write_srv(srv, &call);
380 break;
381 case VFS_OUT_SYNC:
382 con_sync_srv(srv, &call);
383 break;
384 case CONSOLE_CLEAR:
385 con_clear_srv(srv, &call);
386 break;
387 case CONSOLE_SET_POS:
388 con_set_pos_srv(srv, &call);
389 break;
390 case CONSOLE_GET_POS:
391 con_get_pos_srv(srv, &call);
392 break;
393 case CONSOLE_GET_SIZE:
394 con_get_size_srv(srv, &call);
395 break;
396 case CONSOLE_GET_COLOR_CAP:
397 con_get_color_cap_srv(srv, &call);
398 break;
399 case CONSOLE_SET_STYLE:
400 con_set_style_srv(srv, &call);
401 break;
402 case CONSOLE_SET_COLOR:
403 con_set_color_srv(srv, &call);
404 break;
405 case CONSOLE_SET_RGB_COLOR:
406 con_set_rgb_color_srv(srv, &call);
407 break;
408 case CONSOLE_SET_CURSOR_VISIBILITY:
409 con_set_cursor_visibility_srv(srv, &call);
410 break;
411 case CONSOLE_GET_EVENT:
412 con_get_event_srv(srv, &call);
413 break;
414 default:
415 async_answer_0(&call, ENOTSUP);
416 }
417 }
418
419 rc = srvs->ops->close(srv);
420 free(srv);
421
422 return rc;
423}
424
425/** @}
426 */
Note: See TracBrowser for help on using the repository browser.