source: mainline/uspace/lib/c/generic/io/chardev_srv.c@ f2d88f3

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

Add forgotten changes to enable non-blocking chardev read

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*
2 * Copyright (c) 2014 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 Character device server stub
35 */
36#include <errno.h>
37#include <io/chardev_srv.h>
38#include <ipc/chardev.h>
39#include <macros.h>
40#include <stdlib.h>
41#include <stddef.h>
42
43static chardev_srv_t *chardev_srv_create(chardev_srvs_t *);
44
45static void chardev_read_srv(chardev_srv_t *srv, ipc_call_t *icall)
46{
47 void *buf;
48 size_t size;
49 size_t nread;
50 chardev_flags_t flags;
51 errno_t rc;
52
53 flags = IPC_GET_ARG1(*icall);
54
55 ipc_call_t call;
56 if (!async_data_read_receive(&call, &size)) {
57 async_answer_0(icall, EINVAL);
58 return;
59 }
60
61 buf = malloc(size);
62 if (buf == NULL) {
63 async_answer_0(&call, ENOMEM);
64 async_answer_0(icall, ENOMEM);
65 return;
66 }
67
68 if (srv->srvs->ops->read == NULL) {
69 async_answer_0(&call, ENOTSUP);
70 async_answer_0(icall, ENOTSUP);
71 free(buf);
72 return;
73 }
74
75 rc = srv->srvs->ops->read(srv, buf, size, &nread, flags);
76 if (rc != EOK && nread == 0) {
77 async_answer_0(&call, rc);
78 async_answer_0(icall, rc);
79 free(buf);
80 return;
81 }
82
83 async_data_read_finalize(&call, buf, nread);
84
85 free(buf);
86 async_answer_2(icall, EOK, (sysarg_t) rc, nread);
87}
88
89static void chardev_write_srv(chardev_srv_t *srv, ipc_call_t *icall)
90{
91 void *data;
92 size_t size;
93 size_t nwr;
94 errno_t rc;
95
96 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
97 if (rc != EOK) {
98 async_answer_0(icall, rc);
99 return;
100 }
101
102 if (srv->srvs->ops->write == NULL) {
103 async_answer_0(icall, ENOTSUP);
104 return;
105 }
106
107 rc = srv->srvs->ops->write(srv, data, size, &nwr);
108 free(data);
109 if (rc != EOK && nwr == 0) {
110 async_answer_0(icall, rc);
111 return;
112 }
113
114 async_answer_2(icall, EOK, (sysarg_t) rc, nwr);
115}
116
117static chardev_srv_t *chardev_srv_create(chardev_srvs_t *srvs)
118{
119 chardev_srv_t *srv;
120
121 srv = calloc(1, sizeof(chardev_srv_t));
122 if (srv == NULL)
123 return NULL;
124
125 srv->srvs = srvs;
126 return srv;
127}
128
129void chardev_srvs_init(chardev_srvs_t *srvs)
130{
131 srvs->ops = NULL;
132 srvs->sarg = NULL;
133}
134
135errno_t chardev_conn(ipc_call_t *icall, chardev_srvs_t *srvs)
136{
137 chardev_srv_t *srv;
138 errno_t rc;
139
140 /* Accept the connection */
141 async_accept_0(icall);
142
143 srv = chardev_srv_create(srvs);
144 if (srv == NULL)
145 return ENOMEM;
146
147 if (srvs->ops->open != NULL) {
148 rc = srvs->ops->open(srvs, srv);
149 if (rc != EOK)
150 return rc;
151 }
152
153 while (true) {
154 ipc_call_t call;
155 async_get_call(&call);
156 sysarg_t method = IPC_GET_IMETHOD(call);
157
158 if (!method) {
159 /* The other side has hung up */
160 async_answer_0(&call, EOK);
161 break;
162 }
163
164 switch (method) {
165 case CHARDEV_READ:
166 chardev_read_srv(srv, &call);
167 break;
168 case CHARDEV_WRITE:
169 chardev_write_srv(srv, &call);
170 break;
171 default:
172 if (srv->srvs->ops->def_handler != NULL)
173 srv->srvs->ops->def_handler(srv, &call);
174 else
175 async_answer_0(&call, ENOTSUP);
176 }
177 }
178
179 if (srvs->ops->close != NULL)
180 rc = srvs->ops->close(srv);
181 else
182 rc = EOK;
183
184 free(srv);
185
186 return rc;
187}
188
189/** @}
190 */
Note: See TracBrowser for help on using the repository browser.