source: mainline/uspace/lib/c/generic/io/chardev.c@ 8610c2c

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

IPC return values are always errno constants. Adjust types to reflect that.

In principle, IPC server is not allowed to return non-errno values via
the "main" return value, because kernel interprets it (e.g. EHANGUP).
It's still possible to return arbitrary additional return values alongside EOK,
which are not interpreted in normal communication.

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * Copyright (c) 2017 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libc
31 * @{
32 */
33/**
34 * @file
35 * @brief Character device client interface
36 */
37
38#include <errno.h>
39#include <mem.h>
40#include <io/chardev.h>
41#include <ipc/chardev.h>
42#include <stddef.h>
43#include <stdlib.h>
44
45/** Open character device.
46 *
47 * @param sess Session with the character device
48 * @param rchardev Place to store pointer to the new character device structure
49 *
50 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error
51 */
52int chardev_open(async_sess_t *sess, chardev_t **rchardev)
53{
54 chardev_t *chardev;
55
56 chardev = calloc(1, sizeof(chardev_t));
57 if (chardev == NULL)
58 return ENOMEM;
59
60 chardev->sess = sess;
61 *rchardev = chardev;
62
63 /* EIO might be used in a future implementation */
64 return EOK;
65}
66
67/** Close character device.
68 *
69 * Frees the character device structure. The underlying session is
70 * not affected.
71 *
72 * @param chardev Character device or @c NULL
73 */
74void chardev_close(chardev_t *chardev)
75{
76 free(chardev);
77}
78
79/** Read from character device.
80 *
81 * Read as much data as is available from character device up to @a size
82 * bytes into @a buf. On success EOK is returned and at least one byte
83 * is read (if no byte is available the function blocks). The number
84 * of bytes read is stored in @a *nread.
85 *
86 * On error a non-zero error code is returned and @a *nread is filled with
87 * the number of bytes that were successfully transferred.
88 *
89 * @param chardev Character device
90 * @param buf Destination buffer
91 * @param size Maximum number of bytes to read
92 * @param nread Place to store actual number of bytes read
93 *
94 * @return EOK on success or non-zero error code
95 */
96int chardev_read(chardev_t *chardev, void *buf, size_t size, size_t *nread)
97{
98 async_exch_t *exch = async_exchange_begin(chardev->sess);
99
100 if (size > DATA_XFER_LIMIT) {
101 /* This should not hurt anything. */
102 size = DATA_XFER_LIMIT;
103 }
104
105 ipc_call_t answer;
106 aid_t req = async_send_0(exch, CHARDEV_READ, &answer);
107 int rc = async_data_read_start(exch, buf, size);
108 async_exchange_end(exch);
109
110 if (rc != EOK) {
111 async_forget(req);
112 *nread = 0;
113 return rc;
114 }
115
116 int retval;
117 async_wait_for(req, &retval);
118
119 if (retval != EOK) {
120 *nread = 0;
121 return retval;
122 }
123
124 *nread = IPC_GET_ARG2(answer);
125 /* In case of partial success, ARG1 contains the error code */
126 return IPC_GET_ARG1(answer);
127
128}
129
130/** Write up to DATA_XFER_LIMIT bytes to character device.
131 *
132 * Write up to @a size or DATA_XFER_LIMIT bytes from @a data to character
133 * device. On success EOK is returned, bytes were written and @a *nwritten
134 * is set to min(@a size, DATA_XFER_LIMIT)
135 *
136 * On error a non-zero error code is returned and @a *nwritten is filled with
137 * the number of bytes that were successfully transferred.
138 *
139 * @param chardev Character device
140 * @param buf Destination buffer
141 * @param size Maximum number of bytes to read
142 * @param nwritten Place to store actual number of bytes written
143 *
144 * @return EOK on success or non-zero error code
145 */
146static int chardev_write_once(chardev_t *chardev, const void *data,
147 size_t size, size_t *nwritten)
148{
149 async_exch_t *exch = async_exchange_begin(chardev->sess);
150 ipc_call_t answer;
151 aid_t req;
152 int rc;
153
154 /* Break down large transfers */
155 if (size > DATA_XFER_LIMIT)
156 size = DATA_XFER_LIMIT;
157
158 req = async_send_0(exch, CHARDEV_WRITE, &answer);
159 rc = async_data_write_start(exch, data, size);
160 async_exchange_end(exch);
161
162 if (rc != EOK) {
163 async_forget(req);
164 *nwritten = 0;
165 return rc;
166 }
167
168 int retval;
169 async_wait_for(req, &retval);
170 if (retval != EOK) {
171 *nwritten = 0;
172 return retval;
173 }
174
175 *nwritten = IPC_GET_ARG2(answer);
176 /* In case of partial success, ARG1 contains the error code */
177 return IPC_GET_ARG1(answer);
178}
179
180/** Write to character device.
181 *
182 * Write @a size bytes from @a data to character device. On success EOK
183 * is returned, all bytes were written and @a *nwritten is set to @a size.
184 *
185 * On error a non-zero error code is returned and @a *nwritten is filled with
186 * the number of bytes that were successfully transferred.
187 *
188 * @param chardev Character device
189 * @param buf Destination buffer
190 * @param size Maximum number of bytes to read
191 * @param nwritten Place to store actual number of bytes written
192 *
193 * @return EOK on success or non-zero error code
194 */
195int chardev_write(chardev_t *chardev, const void *data, size_t size,
196 size_t *nwritten)
197{
198 size_t nw;
199 size_t p;
200 int rc;
201
202 p = 0;
203 while (p < size) {
204 rc = chardev_write_once(chardev, data + p, size - p, &nw);
205 /* nw is always valid, we can have partial success */
206 p += nw;
207
208 if (rc != EOK) {
209 /* We can return partial success */
210 *nwritten = p;
211 return rc;
212 }
213 }
214
215 *nwritten = p;
216 return EOK;
217}
218
219/** @}
220 */
Note: See TracBrowser for help on using the repository browser.