source: mainline/uspace/lib/c/generic/io/con_srv.c@ 902f0906

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

Multiple event type support in console IPC stubs.

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